[PATCH 1/9] ethdev: sharing indirect actions between ports
The RTE Flow API implements the concept of shared objects, known as indirect actions (RTE_FLOW_ACTION_TYPE_INDIRECT). An application can create the indirect action of desired type and configuration with rte_flow_action_handle_create call and then specify the obtained action handle in multiple flows. The initial concept supposes the action handle has strict attachment to the port it was created on and to be used exclusively in the flows being installed on the port. Nowadays the multipath network topologies are quite common, packets belonging to the same connection might arrive and be sent over multiple ports, and there is the raising demand to handle these "spread" connections. To fulfil this demand it is proposed to extend indirect action sharing across the multiple ports. This kind of sharing would be extremely useful for the meters and counters, allowing to manage the single connection over the multiple ports. This cross-port object sharing is hard to implement in generic way merely with software on the upper layers, but can be provided by the driver over the single hardware instance, where multiple ports reside on the same physical NIC and share the same hardware context. To allow this action sharing application should specify the "host port" during flow configuring to claim the intention to share the indirect actions. All indirect actions reside within "host port" context and can be shared in flows being installed on the host port and on all the ports referencing this one. If sharing between host and port being configured is not supported the configuration should be rejected with error. There might be multiple independent (mutual exclusive) sharing domains with dedicated host and referencing ports. To manage the shared indirect action any port from sharing domain can be specified. To share or not the created action is up to application, no API change is needed. Signed-off-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c | 6 ++ lib/ethdev/rte_flow.h | 11 +++ 2 files changed, 17 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 7d0c24366c..692d37925a 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1476,6 +1476,12 @@ rte_flow_configure(uint16_t port_id, RTE_FLOW_LOG(ERR, "Port %"PRIu16" queue info is NULL.\n", port_id); return -EINVAL; } + if ((port_attr->flags & RTE_FLOW_PORT_FLAG_SHARE_INDIRECT) && +!rte_eth_dev_is_valid_port(port_attr->host_port_id)) { + return rte_flow_error_set(error, ENODEV, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENODEV)); + } if (likely(!!ops->configure)) { ret = ops->configure(dev, port_attr, nb_queue, queue_attr, error); if (ret == 0) diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index b60987db4b..c784f4ec30 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -4903,6 +4903,13 @@ rte_flow_info_get(uint16_t port_id, struct rte_flow_queue_info *queue_info, struct rte_flow_error *error); +/** + * Indicate all steering objects should be created on contexts + * of the host port, providing indirect object sharing beetween + * ports. + */ +#define RTE_FLOW_PORT_FLAG_SHARE_INDIRECT RTE_BIT32(0) + /** * @warning * @b EXPERIMENTAL: this API may change without prior notice. @@ -4932,6 +4939,10 @@ struct rte_flow_port_attr { * @see RTE_FLOW_ACTION_TYPE_CONNTRACK */ uint32_t nb_conn_tracks; + /** +* Port to base shared objects on. +*/ + uint16_t host_port_id; /** * Port flags (RTE_FLOW_PORT_FLAG_*). */ -- 2.18.1
[PATCH 2/9] net/mlx5/hws: Matcher, Free FT from RTC id before set the new value
From: Erez Shitrit While matcher is being connect/disconnect in shared gvmi flow we set the first ft in the table to point on the first matcher, The FW is increasing the refcount on the first matcher RTC because of that no matcher if it is the same RTC that was set before, and when we will try to release that RTC we will get the following syndrome: 0xaa0093 - destroy_rtc_object: rtc in use or doesn't exist. In order to resolve that we clean the current pointed RTC from that ft and only after that setting it to the new RTC value. Signed-off-by: Erez Shitrit Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/hws/mlx5dr_matcher.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c index d509a2f0e1..32bf3f5886 100644 --- a/drivers/net/mlx5/hws/mlx5dr_matcher.c +++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c @@ -334,6 +334,24 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher) return ret; } + if (!next) { + /* ft no longer points to any RTC, drop refcount */ + ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx, + tbl->fw_ft_type, + tbl->type, + prev_ft); + if (ret) { + DR_LOG(ERR, "Failed to reset last RTC refcount"); + return ret; + } + } + + ret = mlx5dr_matcher_shared_update_local_ft(tbl); + if (ret) { + DR_LOG(ERR, "Failed to update local_ft in shared table"); + return ret; + } + return 0; } -- 2.18.1
[PATCH 3/9] net/mlx5/hws: fix disconnecting matcher
From: Erez Shitrit This patch fixes the matcher disconnection handling, by removing the RTC references from flow table if the currently removed matcher was the last one for the given table. As a result RTC in this matcher can be correctly freed, since there are no dangling references to the RTC. Fixes: c467608215b2 ("net/mlx5/hws: add matcher object") Signed-off-by: Erez Shitrit Signed-off-by: Dariusz Sosnowski Reviewed-by: Alex Vesker Acked-by: Matan Azrad --- drivers/net/mlx5/hws/mlx5dr_matcher.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c index 32bf3f5886..a0297c9787 100644 --- a/drivers/net/mlx5/hws/mlx5dr_matcher.c +++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c @@ -346,12 +346,6 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher) } } - ret = mlx5dr_matcher_shared_update_local_ft(tbl); - if (ret) { - DR_LOG(ERR, "Failed to update local_ft in shared table"); - return ret; - } - return 0; } -- 2.18.1
[PATCH 4/9] common/mlx5: add cross port object sharing capability
Add query port capabilities to share steering objects between multiple ports of the same physical NIC. Signed-off-by: Viacheslav Ovsiienko --- drivers/common/mlx5/mlx5_devx_cmds.c | 13 + drivers/common/mlx5/mlx5_devx_cmds.h | 1 + 2 files changed, 14 insertions(+) diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index e3a4927d0f..17128035ec 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -1047,6 +1047,19 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, attr->flow_counter_bulk_log_granularity = MLX5_GET(cmd_hca_cap_2, hcattr, flow_counter_bulk_log_granularity); + rc = MLX5_GET(cmd_hca_cap_2, hcattr, + cross_vhca_object_to_object_supported); + attr->cross_vhca = + (rc & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_TIR) && + (rc & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_STC_TO_FT) && + (rc & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_FT_TO_FT) && + (rc & MLX5_CROSS_VHCA_OBJ_TO_OBJ_TYPE_FT_TO_RTC); + rc = MLX5_GET(cmd_hca_cap_2, hcattr, + allowed_object_for_other_vhca_access); + attr->cross_vhca = attr->cross_vhca && + (rc & MLX5_CROSS_VHCA_ALLOWED_OBJS_TIR) && + (rc & MLX5_CROSS_VHCA_ALLOWED_OBJS_FT) && + (rc & MLX5_CROSS_VHCA_ALLOWED_OBJS_RTC); } if (attr->log_min_stride_wqe_sz == 0) attr->log_min_stride_wqe_sz = MLX5_MPRQ_LOG_MIN_STRIDE_WQE_SIZE; diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h index c94b9eac06..b65ba569bc 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.h +++ b/drivers/common/mlx5/mlx5_devx_cmds.h @@ -288,6 +288,7 @@ struct mlx5_hca_attr { uint32_t alloc_flow_counter_pd:1; uint32_t flow_counter_access_aso:1; uint32_t flow_access_aso_opc_mod:8; + uint32_t cross_vhca:1; }; /* LAG Context. */ -- 2.18.1
[PATCH 5/9] net/mlx5: add cross port shared mode for HW steering
Add host port option for sharing steering objects between multiple ports of the same physical NIC. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5.c | 6 +++ drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_flow_hw.c | 78 +++-- drivers/net/mlx5/mlx5_hws_cnt.c | 12 + 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index b8643cebdd..2eca2cceef 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -2013,6 +2013,12 @@ mlx5_dev_close(struct rte_eth_dev *dev) } if (!priv->sh) return 0; + if (priv->shared_refcnt) { + DRV_LOG(ERR, "port %u is shared host in use (%u)", + dev->data->port_id, priv->shared_refcnt); + rte_errno = EBUSY; + return -EBUSY; + } DRV_LOG(DEBUG, "port %u closing device \"%s\"", dev->data->port_id, ((priv->sh->cdev->ctx != NULL) ? diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 16b33e1548..525bdd47f7 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -1780,6 +1780,8 @@ struct mlx5_priv { struct mlx5_flow_hw_ctrl_rx *hw_ctrl_rx; /**< HW steering templates used to create control flow rules. */ #endif + struct rte_eth_dev *shared_host; /* Host device for HW steering. */ + uint16_t shared_refcnt; /* HW steering host reference counter. */ }; #define PORT_ID(priv) ((priv)->dev_data->port_id) diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index ce9e0219e1..fc87e687c9 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -5,6 +5,8 @@ #include #include + +#include "mlx5.h" #include "mlx5_defs.h" #include "mlx5_flow.h" #include "mlx5_rx.h" @@ -6302,6 +6304,12 @@ flow_hw_ct_pool_create(struct rte_eth_dev *dev, int reg_id; uint32_t flags; + if (port_attr->flags & RTE_FLOW_PORT_FLAG_SHARE_INDIRECT) { + DRV_LOG(ERR, "Connection tracking is not supported " +"in cross vHCA sharing mode"); + rte_errno = ENOTSUP; + return NULL; + } pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool), 0, SOCKET_ID_ANY); if (!pool) { rte_errno = ENOMEM; @@ -6786,6 +6794,7 @@ flow_hw_configure(struct rte_eth_dev *dev, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_priv *host_priv = NULL; struct mlx5dr_context *dr_ctx = NULL; struct mlx5dr_context_attr dr_ctx_attr = {0}; struct mlx5_hw_q *hw_q; @@ -6800,7 +6809,8 @@ flow_hw_configure(struct rte_eth_dev *dev, .free = mlx5_free, .type = "mlx5_hw_action_construct_data", }; - /* Adds one queue to be used by PMD. + /* +* Adds one queue to be used by PMD. * The last queue will be used by the PMD. */ uint16_t nb_q_updated = 0; @@ -6919,6 +6929,57 @@ flow_hw_configure(struct rte_eth_dev *dev, dr_ctx_attr.queues = nb_q_updated; /* Queue size should all be the same. Take the first one. */ dr_ctx_attr.queue_size = _queue_attr[0]->size; + if (port_attr->flags & RTE_FLOW_PORT_FLAG_SHARE_INDIRECT) { + struct rte_eth_dev *host_dev = NULL; + uint16_t port_id; + + MLX5_ASSERT(rte_eth_dev_is_valid_port(port_attr->host_port_id)); + if (is_proxy) { + DRV_LOG(ERR, "cross vHCA shared mode not supported " +" for E-Switch confgiurations"); + rte_errno = ENOTSUP; + goto err; + } + MLX5_ETH_FOREACH_DEV(port_id, dev->device) { + if (port_id == port_attr->host_port_id) { + host_dev = &rte_eth_devices[port_id]; + break; + } + } + if (!host_dev || host_dev == dev || + !host_dev->data || !host_dev->data->dev_private) { + DRV_LOG(ERR, "Invalid cross vHCA host port %u", + port_attr->host_port_id); + rte_errno = EINVAL; + goto err; + } + host_priv = host_dev->data->dev_private; + if (host_priv->sh->cdev->ctx == priv->sh->cdev->ctx) { + DRV_LOG(ERR, "Sibling ports %u and %u do not " +
[PATCH 6/9] net/mlx5: support counters in cross port shared mode
In the cross vHCA sharing mode the host counter pool should be used in counter related routines. The local port pool is used to store the dedicated DR action handle, per queue counter caches and query data are ignored and not allocated on local pool. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_hw.c | 12 ++- drivers/net/mlx5/mlx5_hws_cnt.c | 163 drivers/net/mlx5/mlx5_hws_cnt.h | 109 +++-- 3 files changed, 150 insertions(+), 134 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c index fc87e687c9..1495bc384e 100644 --- a/drivers/net/mlx5/mlx5_flow_hw.c +++ b/drivers/net/mlx5/mlx5_flow_hw.c @@ -2311,8 +2311,10 @@ flow_hw_actions_construct(struct rte_eth_dev *dev, break; /* Fall-through. */ case RTE_FLOW_ACTION_TYPE_COUNT: - ret = mlx5_hws_cnt_pool_get(priv->hws_cpool, &queue, - &cnt_id, age_idx); + ret = mlx5_hws_cnt_pool_get(priv->hws_cpool, + (priv->shared_refcnt || +priv->hws_cpool->cfg.host_cpool) ? + NULL : &queue, &cnt_id, age_idx); if (ret != 0) return ret; ret = mlx5_hws_cnt_pool_get_action_offset @@ -7997,6 +7999,7 @@ static int flow_hw_query_counter(const struct rte_eth_dev *dev, uint32_t counter, void *data, struct rte_flow_error *error) { + struct mlx5_hws_cnt_pool *hpool; struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_hws_cnt *cnt; struct rte_flow_query_count *qc = data; @@ -8007,8 +8010,9 @@ flow_hw_query_counter(const struct rte_eth_dev *dev, uint32_t counter, return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "counter are not available"); - iidx = mlx5_hws_cnt_iidx(priv->hws_cpool, counter); - cnt = &priv->hws_cpool->pool[iidx]; + hpool = mlx5_hws_cnt_host_pool(priv->hws_cpool); + iidx = mlx5_hws_cnt_iidx(hpool, counter); + cnt = &hpool->pool[iidx]; __hws_cnt_query_raw(priv->hws_cpool, counter, &pkts, &bytes); qc->hits_set = 1; qc->bytes_set = 1; diff --git a/drivers/net/mlx5/mlx5_hws_cnt.c b/drivers/net/mlx5/mlx5_hws_cnt.c index afc93821e4..12b2cb0b27 100644 --- a/drivers/net/mlx5/mlx5_hws_cnt.c +++ b/drivers/net/mlx5/mlx5_hws_cnt.c @@ -24,12 +24,8 @@ static void __hws_cnt_id_load(struct mlx5_hws_cnt_pool *cpool) { - uint32_t preload; - uint32_t q_num = cpool->cache->q_num; uint32_t cnt_num = mlx5_hws_cnt_pool_get_size(cpool); - cnt_id_t cnt_id; - uint32_t qidx, iidx = 0; - struct rte_ring *qcache = NULL; + uint32_t iidx; /* * Counter ID order is important for tracking the max number of in used @@ -39,18 +35,9 @@ __hws_cnt_id_load(struct mlx5_hws_cnt_pool *cpool) * and then the global free list. * In the end, user fetch the counter from minimal to the maximum. */ - preload = RTE_MIN(cpool->cache->preload_sz, cnt_num / q_num); - for (qidx = 0; qidx < q_num; qidx++) { - for (; iidx < preload * (qidx + 1); iidx++) { - cnt_id = mlx5_hws_cnt_id_gen(cpool, iidx); - qcache = cpool->cache->qcache[qidx]; - if (qcache) - rte_ring_enqueue_elem(qcache, &cnt_id, - sizeof(cnt_id)); - } - } - for (; iidx < cnt_num; iidx++) { - cnt_id = mlx5_hws_cnt_id_gen(cpool, iidx); + for (iidx = 0; iidx < cnt_num; iidx++) { + cnt_id_t cnt_id = mlx5_hws_cnt_id_gen(cpool, iidx); + rte_ring_enqueue_elem(cpool->free_list, &cnt_id, sizeof(cnt_id)); } @@ -334,7 +321,26 @@ mlx5_hws_cnt_svc(void *opaque) return NULL; } -struct mlx5_hws_cnt_pool * +static void +mlx5_hws_cnt_pool_deinit(struct mlx5_hws_cnt_pool * const cntp) +{ + uint32_t qidx = 0; + if (cntp == NULL) + return; + rte_ring_free(cntp->free_list); + rte_ring_free(cntp->wait_reset_list); + rte_ring_free(cntp->reuse_list); + if (cntp->cache) { + for (qidx = 0; qidx < cntp->cache->q_num; qidx++) + rte_ring_free(cntp->cache->qcache[qidx]); + } + mlx5_free(cntp->cache); + mlx5_free(cntp->raw_mng); + mlx5_free(cntp->
[PATCH 7/9] app/testpmd: add host port parameter into flow config
Host port id parameter is added to "flow configure" command. Signed-off-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 88108498e0..b88756903b 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -228,6 +228,7 @@ enum index { CONFIG_METERS_NUMBER, CONFIG_CONN_TRACK_NUMBER, CONFIG_FLAGS, + CONFIG_HOST_PORT, /* Indirect action arguments */ INDIRECT_ACTION_CREATE, @@ -1098,6 +1099,7 @@ static const enum index next_config_attr[] = { CONFIG_METERS_NUMBER, CONFIG_CONN_TRACK_NUMBER, CONFIG_FLAGS, + CONFIG_HOST_PORT, END, ZERO, }; @@ -2719,6 +2721,14 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY(struct buffer, args.configure.port_attr.flags)), }, + [CONFIG_HOST_PORT] = { + .name = "host_port", + .help = "host port for shared objects", + .next = NEXT(next_config_attr, +NEXT_ENTRY(COMMON_UNSIGNED)), + .args = ARGS(ARGS_ENTRY(struct buffer, + args.configure.port_attr.host_port_id)), + }, /* Top-level command. */ [PATTERN_TEMPLATE] = { .name = "pattern_template", -- 2.18.1
[PATCH 8/9] app/testpmd: add shared indirect action support
The shared indirect action can be shared between ports, action should be created on single port and the handle can be used in the templates and flows on multiple ports, example: flow configure 0 queues_number 1 queues_size 64 counters_number 64 flow configure 1 queues_number 1 queues_size 64 counters_number 0 host_port 0 flags 1 flow indirect_action 0 create ingress action_id 0 action count / end flow actions_template 0 create ingress actions_template_id 8 template indirect 0 / queue index 0 / end mask count / queue index 0 / end flow actions_template 1 create ingress actions_template_id 18 template shared_indirect 0 0 / queue index 0 / end mask count / queue index 0 / end Signed-off-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 53 - 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index b88756903b..734959ba9b 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -595,6 +595,8 @@ enum index { ACTION_SAMPLE_INDEX, ACTION_SAMPLE_INDEX_VALUE, ACTION_INDIRECT, + ACTION_SHARED_INDIRECT, + INDIRECT_ACTION_PORT, INDIRECT_ACTION_ID2PTR, ACTION_MODIFY_FIELD, ACTION_MODIFY_FIELD_OP, @@ -1882,6 +1884,7 @@ static const enum index next_action[] = { ACTION_AGE_UPDATE, ACTION_SAMPLE, ACTION_INDIRECT, + ACTION_SHARED_INDIRECT, ACTION_MODIFY_FIELD, ACTION_CONNTRACK, ACTION_CONNTRACK_UPDATE, @@ -2387,6 +2390,9 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token, static int parse_ia_id2ptr(struct context *ctx, const struct token *token, const char *str, unsigned int len, void *buf, unsigned int size); +static int parse_ia_port(struct context *ctx, const struct token *token, +const char *str, unsigned int len, void *buf, +unsigned int size); static int parse_mp(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -6374,6 +6380,23 @@ static const struct token token_list[] = { .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), .call = parse_vc, }, + [ACTION_SHARED_INDIRECT] = { + .name = "shared_indirect", + .help = "apply indirect action by id and port", + .priv = PRIV_ACTION(INDIRECT, 0), + .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)), + .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)), +ARGS_ENTRY_ARB(0, sizeof(uint32_t))), + .call = parse_vc, + }, + [INDIRECT_ACTION_PORT] = { + .name = "{indirect_action_port}", + .type = "INDIRECT_ACTION_PORT", + .help = "indirect action port", + .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)), + .call = parse_ia_port, + .comp = comp_none, + }, [INDIRECT_ACTION_ID2PTR] = { .name = "{action_id}", .type = "INDIRECT_ACTION_ID", @@ -9788,6 +9811,31 @@ parse_port(struct context *ctx, const struct token *token, return ret; } +/** Parse tokens for shared indirect actions. */ +static int +parse_ia_port(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct rte_flow_action *action = ctx->object; + uint32_t id; + int ret; + + (void)buf; + (void)size; + ctx->objdata = 0; + ctx->object = &id; + ctx->objmask = NULL; + ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); + ctx->object = action; + if (ret != (int)len) + return ret; + /* set indirect action */ + if (action) + action->conf = (void *)(uintptr_t)id; + return ret; +} + static int parse_ia_id2ptr(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -9808,7 +9856,10 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token, return ret; /* set indirect action */ if (action) { - action->conf = port_action_handle_get_by_id(ctx->port, id); + portid_t port_id = ctx->port; + if (ctx->prev == INDIRECT_ACTION_PORT) + port_id = (portid_t)(uintptr_t)action->conf; + action->conf = port_action_handle_get_by_id(port_id, id); ret = (action->conf) ? ret : -1; } return ret; -- 2.18.1
[PATCH 9/9] doc: update cross-port indirect shared action
The patch updates the Release Notes and documentation for the indirect RTE Flow actions as shared ones between ports on the same physical NIC. Signed-off-by: Viacheslav Ovsiienko --- doc/guides/rel_notes/release_23_03.rst | 6 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst index c15f6fbb9f..eb6643bc66 100644 --- a/doc/guides/rel_notes/release_23_03.rst +++ b/doc/guides/rel_notes/release_23_03.rst @@ -55,6 +55,12 @@ New Features Also, make sure to start the actual text at the margin. === +* **Added cross-port indirect action in asynchronous Flow API.** + + * Added ``RTE_FLOW_PORT_FLAG_SHARE_INDIRECT`` flag option to +``rte_flow_configure``. + * Added ``host_port_id`` to ``rte_flow_port_attr`` structure. + * **Updated Intel QuickAssist Technology (QAT) crypto driver.** * Added support for SHA3 224/256/384/512 plain hash in QAT GEN 3. diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 0037506a79..cf6c214197 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3047,7 +3047,9 @@ for asynchronous flow creation/destruction operations. It is bound to [queues_number {number}] [queues_size {size}] [counters_number {number}] [aging_counters_number {number}] - [meters_number {number}] [flags {number}] + [host_port {number}] + [meters_number {number}] + [flags {number}] If successful, it will show:: -- 2.18.1
[PATCH] net/mlx5/hws: support match on ESP item
From: Hamdan Igbaria Add the support to match on SPI and sequence number fields of ESP header. The match on ESP header in harwdare steering is supported only if firmware reports the device supports IPsec offload. Signed-off-by: Hamdan Igbaria Acked-by: Viacheslav Ovsiienko --- drivers/common/mlx5/mlx5_prm.h| 3 ++- drivers/net/mlx5/hws/mlx5dr_cmd.c | 3 +++ drivers/net/mlx5/hws/mlx5dr_cmd.h | 1 + drivers/net/mlx5/hws/mlx5dr_definer.c | 38 ++- drivers/net/mlx5/hws/mlx5dr_definer.h | 2 ++ drivers/net/mlx5/mlx5_flow_hw.c | 1 + 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h index 9294f65e24..0ee4b575d4 100644 --- a/drivers/common/mlx5/mlx5_prm.h +++ b/drivers/common/mlx5/mlx5_prm.h @@ -1695,7 +1695,8 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 reserved_at_460[0x8]; u8 aes_xts[0x1]; u8 crypto[0x1]; - u8 reserved_at_46a[0x6]; + u8 ipsec_offload[0x1]; + u8 reserved_at_46b[0x5]; u8 max_num_eqs[0x10]; u8 reserved_at_480[0x3]; u8 log_max_l2_table[0x5]; diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c b/drivers/net/mlx5/hws/mlx5dr_cmd.c index 32378673cf..c60da381b2 100644 --- a/drivers/net/mlx5/hws/mlx5dr_cmd.c +++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c @@ -850,6 +850,9 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx, caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.sq_ts_format); + caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out, + capability.cmd_hca_cap.ipsec_offload); + MLX5_SET(query_hca_cap_in, in, op_mod, MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | MLX5_HCA_CAP_OPMOD_GET_CUR); diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h b/drivers/net/mlx5/hws/mlx5dr_cmd.h index 468557ba16..af779e4bcd 100644 --- a/drivers/net/mlx5/hws/mlx5dr_cmd.h +++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h @@ -188,6 +188,7 @@ struct mlx5dr_cmd_query_caps { bool cross_vhca_resources; uint32_t shared_vhca_id; char fw_ver[64]; + bool ipsec_offload; }; int mlx5dr_cmd_destroy_obj(struct mlx5dr_devx_obj *devx_obj); diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c index 6b98eb8c96..ab65409629 100644 --- a/drivers/net/mlx5/hws/mlx5dr_definer.c +++ b/drivers/net/mlx5/hws/mlx5dr_definer.c @@ -162,7 +162,9 @@ struct mlx5dr_definer_conv_data { X(SET_BE32, gre_opt_key,v->key.key, rte_flow_item_gre_opt) \ X(SET_BE32, gre_opt_seq,v->sequence.sequence, rte_flow_item_gre_opt) \ X(SET_BE16, gre_opt_checksum, v->checksum_rsvd.checksum, rte_flow_item_gre_opt) \ - X(SET, meter_color,rte_col_2_mlx5_col(v->color), rte_flow_item_meter_color) + X(SET, meter_color,rte_col_2_mlx5_col(v->color), rte_flow_item_meter_color) \ + X(SET_BE32, ipsec_spi, v->hdr.spi, rte_flow_item_esp) \ + X(SET_BE32, ipsec_sequence_number, v->hdr.seq, rte_flow_item_esp) /* Item set function format */ #define X(set_type, func_name, value, item_type) \ @@ -1465,6 +1467,36 @@ mlx5dr_definer_conv_item_meter_color(struct mlx5dr_definer_conv_data *cd, return 0; } +static int +mlx5dr_definer_conv_item_esp(struct mlx5dr_definer_conv_data *cd, +struct rte_flow_item *item, +int item_idx) +{ + const struct rte_flow_item_esp *m = item->mask; + struct mlx5dr_definer_fc *fc; + + if (!cd->caps->ipsec_offload) { + rte_errno = ENOTSUP; + return rte_errno; + } + + if (!m) + return 0; + if (m->hdr.spi) { + fc = &cd->fc[MLX5DR_DEFINER_FNAME_ESP_SPI]; + fc->item_idx = item_idx; + fc->tag_set = &mlx5dr_definer_ipsec_spi_set; + DR_CALC_SET_HDR(fc, ipsec, spi); + } + if (m->hdr.seq) { + fc = &cd->fc[MLX5DR_DEFINER_FNAME_ESP_SEQUENCE_NUMBER]; + fc->item_idx = item_idx; + fc->tag_set = &mlx5dr_definer_ipsec_sequence_number_set; + DR_CALC_SET_HDR(fc, ipsec, sequence_number); + } + return 0; +} + static int mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context *ctx, struct mlx5dr_match_template *mt, @@ -1581,6 +1613,10 @@ mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context *ctx, ret = mlx5dr_definer_conv_item_meter_color(&cd, items, i); item_flags |= MLX5_FLOW_ITEM_METER_COLOR; break; + case RT
[dpdk-dev] [PATCH] net/mlx4: fix buffer leakage on device close
The mlx4 PMD tracks the buffers (mbufs) for the packets being transmitted in the dedicated array named as "elts". The tx_burst routine frees the mbufs from this array once it needs to rearm the hardware descriptor and store the new mbuf, so it looks like as replacement mbuf pointer in the elts array. On the device stop mlx4 PMD freed only the part of elts according tail and head pointers, leaking the rest of buffers, remained in the elts array. Fixes: a2ce2121c01c ("net/mlx4: separate Tx configuration functions") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx4/mlx4_rxtx.c | 4 drivers/net/mlx4/mlx4_txq.c | 19 +-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/net/mlx4/mlx4_rxtx.c b/drivers/net/mlx4/mlx4_rxtx.c index adc1c9bf81..ecf08f53cf 100644 --- a/drivers/net/mlx4/mlx4_rxtx.c +++ b/drivers/net/mlx4/mlx4_rxtx.c @@ -921,10 +921,6 @@ mlx4_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n) if (likely(elt->buf != NULL)) { struct rte_mbuf *tmp = elt->buf; -#ifdef RTE_LIBRTE_MLX4_DEBUG - /* Poisoning. */ - memset(&elt->buf, 0x66, sizeof(struct rte_mbuf *)); -#endif /* Faster than rte_pktmbuf_free(). */ do { struct rte_mbuf *next = tmp->next; diff --git a/drivers/net/mlx4/mlx4_txq.c b/drivers/net/mlx4/mlx4_txq.c index 31ab308050..2df26842fb 100644 --- a/drivers/net/mlx4/mlx4_txq.c +++ b/drivers/net/mlx4/mlx4_txq.c @@ -206,19 +206,18 @@ mlx4_tx_uar_uninit_secondary(struct rte_eth_dev *dev __rte_unused) static void mlx4_txq_free_elts(struct txq *txq) { - unsigned int elts_head = txq->elts_head; - unsigned int elts_tail = txq->elts_tail; struct txq_elt (*elts)[txq->elts_n] = txq->elts; - unsigned int elts_m = txq->elts_n - 1; + unsigned int n = txq->elts_n; - DEBUG("%p: freeing WRs", (void *)txq); - while (elts_tail != elts_head) { - struct txq_elt *elt = &(*elts)[elts_tail++ & elts_m]; + DEBUG("%p: freeing WRs, %u", (void *)txq, n); + while (n--) { + struct txq_elt *elt = &(*elts)[n]; - MLX4_ASSERT(elt->buf != NULL); - rte_pktmbuf_free(elt->buf); - elt->buf = NULL; - elt->wqe = NULL; + if (elt->buf) { + rte_pktmbuf_free(elt->buf); + elt->buf = NULL; + elt->wqe = NULL; + } } txq->elts_tail = txq->elts_head; } -- 2.18.1
[dpdk-dev] [PATCH] net/mlx5: fix probing the device in legacy bonding mode
If the device was configured as legacy bond one (without involving E-Switch), the mlx5 PMD erroneously tried to deduce the vport index raising the fatal error and preventing device from being used. The patch checks whether there is E-Switch present and we should use vport index indeed. Fixes: 2eb4d0107acc ("net/mlx5: refactor PCI probing on Linux") Fixes: d5c06b1b10ae ("net/mlx5: query vport index match mode and parameters") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/linux/mlx5_os.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index ad43141e47..8f4b34e577 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -1097,7 +1097,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, } if (devx_port.comp_mask & MLX5DV_DEVX_PORT_VPORT) { priv->vport_id = devx_port.vport_num; - } else if (spawn->pf_bond >= 0) { + } else if (spawn->pf_bond >= 0 && + (switch_info->representor || switch_info->master)) { DRV_LOG(ERR, "can't deduce vport index for port %d" " on bonding device %s", spawn->phys_port, -- 2.28.0
[dpdk-dev] [PATCH] net/mlx5: fix Tx queue doorbell record field offset
If the Send Queue (backing one for PMD Tx queue) the was created with DevX API the doorbell record offset for the producer index field was incorrect. If hardware missed the doorbell register write event the wrong content of doorbell record might cause queue malfunction. For the Send Queues created with Verbs API the doorbell record offset was configured correctly. Fixes: 86d259cec852 ("net/mlx5: separate Tx queue object creations") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_devx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c index 76d31f5539..531a81d7fa 100644 --- a/drivers/net/mlx5/mlx5_devx.c +++ b/drivers/net/mlx5/mlx5_devx.c @@ -1113,7 +1113,7 @@ mlx5_txq_devx_obj_new(struct rte_eth_dev *dev, uint16_t idx) txq_data->wqe_pi = 0; txq_data->wqe_comp = 0; txq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV; - txq_data->qp_db = txq_obj->sq_obj.db_rec; + txq_data->qp_db = &txq_obj->sq_obj.db_rec[MLX5_SND_DBR]; *txq_data->qp_db = 0; txq_data->qp_num_8s = txq_obj->sq_obj.sq->id << 8; /* Change Send Queue state to Ready-to-Send. */ -- 2.18.1
[dpdk-dev] [PATCH] net/mlx5: fix query missed Rx packet stats
There was a typo - the device context was wrongly provided instead of counter's one for the DevX query operation. Fixes: e6988afdc75a ("net/mlx5: fix imissed statistics") Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/linux/mlx5_os.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index 41622c1bf7..e461f9461a 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -2682,8 +2682,8 @@ mlx5_os_read_dev_stat(struct mlx5_priv *priv, const char *ctr_name, if (priv->sh) { if (priv->q_counters != NULL && strcmp(ctr_name, "out_of_buffer") == 0) - return mlx5_devx_cmd_queue_counter_query(priv->sh->ctx, - 0, (uint32_t *)stat); + return mlx5_devx_cmd_queue_counter_query + (priv->q_counters, 0, (uint32_t *)stat); MKSTR(path, "%s/ports/%d/hw_counters/%s", priv->sh->ibdev_path, priv->dev_port, -- 2.18.1
[dpdk-dev] [PATCH v2 0/5] Add support of indirect action API for count action.
v1: http://patches.dpdk.org/project/dpdk/patch/20210426124250.42771-2-michae...@nvidia.com/ V2: patch rebase Michael Baum (5): net/mlx5: support flow count action handle app/testpmd: remove indirect RSS action query app/testpmd: support indirect counter action query net/mlx5: fix flow age event triggering net/mlx5: use aging by counter when counter is existed app/test-pmd/config.c | 152 +- doc/guides/nics/mlx5.rst | 13 +- doc/guides/rel_notes/release_21_05.rst | 1 + drivers/net/mlx5/mlx5.c| 8 +- drivers/net/mlx5/mlx5.h| 9 +- drivers/net/mlx5/mlx5_defs.h | 2 +- drivers/net/mlx5/mlx5_flow.c | 6 + drivers/net/mlx5/mlx5_flow.h | 3 +- drivers/net/mlx5/mlx5_flow_dv.c| 369 + drivers/net/mlx5/mlx5_flow_verbs.c | 2 +- 10 files changed, 360 insertions(+), 205 deletions(-) -- 2.18.1
[dpdk-dev] [PATCH v2 2/5] app/testpmd: remove indirect RSS action query
From: Michael Baum The port_action_handle_query function supports query operation for indirect RSS action. No driver currently supports this operation, and this support is unnecessary. Remove it. Signed-off-by: Michael Baum Acked-by: Matan Azrad --- app/test-pmd/config.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index e189062efd..a9805cc198 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1626,7 +1626,6 @@ port_action_handle_query(portid_t port_id, uint32_t id) if (!pia) return -EINVAL; switch (pia->type) { - case RTE_FLOW_ACTION_TYPE_RSS: case RTE_FLOW_ACTION_TYPE_AGE: data = &default_data; break; @@ -1638,12 +1637,6 @@ port_action_handle_query(portid_t port_id, uint32_t id) if (rte_flow_action_handle_query(port_id, pia->handle, data, &error)) ret = port_flow_complain(&error); switch (pia->type) { - case RTE_FLOW_ACTION_TYPE_RSS: - if (!ret) - printf("Shared RSS action:\n\trefs:%u\n", - *((uint32_t *)data)); - data = NULL; - break; case RTE_FLOW_ACTION_TYPE_AGE: if (!ret) { struct rte_flow_query_age *resp = data; -- 2.18.1
[dpdk-dev] [PATCH v2 1/5] net/mlx5: support flow count action handle
From: Michael Baum Existing API supports counter action to count traffic of a single flow. The user can share the count action among different flows using the shared flag and the same counter ID in the count action configuration. Recent patch [1] introduced the indirect action API. Using this API, an action can be created as indirect, unattached to any flow rule. Multiple flows can then be created using the same indirect action. The new API also supports query operation of an indirect action. The new API is more efficient because the driver gets it's own handler for the count action instead of managing a mapping between the user ID to the driver handle. Support create, query and destroy indirect action operations for flow count action. Application will use the indirect action query operation to query this count action. In the meantime the old sharing mechanism (with the sharing flag) continues to be supported, and the user can choose the way he wants to share the counter. The new indirect action API is only supported in DevX, so sharing counter action in Verbs can only be done through the old mechanism. [1] https://mails.dpdk.org/archives/dev/2020-July/174110.html Signed-off-by: Michael Baum Acked-by: Matan Azrad --- doc/guides/nics/mlx5.rst | 13 +- doc/guides/rel_notes/release_21_05.rst | 1 + drivers/net/mlx5/mlx5.h| 7 +- drivers/net/mlx5/mlx5_defs.h | 2 +- drivers/net/mlx5/mlx5_flow.c | 6 + drivers/net/mlx5/mlx5_flow.h | 3 +- drivers/net/mlx5/mlx5_flow_dv.c| 222 + drivers/net/mlx5/mlx5_flow_verbs.c | 2 +- 8 files changed, 175 insertions(+), 81 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 2bb4f18a08..b2c357e016 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -1692,10 +1692,15 @@ Supported hardware offloads | | | | | rdma-core 33 | | | | | | ConnectX-5| +---+-+-+ - | Age | | DPDK 20.11 | | DPDK 20.11| - | | | OFED 5.2 | | OFED 5.2 | - | | | rdma-core 32 | | rdma-core 32 | - | | | ConnectX-6 Dx| | ConnectX-6 Dx | + | Age | | DPDK 20.11| | DPDK 20.11| + | | | OFED 5.2 | | OFED 5.2 | + | | | rdma-core 32 | | rdma-core 32 | + | | | ConnectX-6 Dx | | ConnectX-6 Dx | + +---+-+-+ + | Count | | DPDK 21.05| | DPDK 21.05| + | | | OFED 4.6 | | OFED 4.6 | + | | | rdma-core 24 | | rdma-core 23 | + | | | ConnectX-5| | ConnectX-5| +---+-+-+ Notes for metadata diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index 133a0dbbf2..4628ae3ad9 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -161,6 +161,7 @@ New Features Updated the Mellanox mlx5 driver with new features and improvements, including: * Added support for VXLAN and NVGRE encap as sample actions. + * Added support for flow COUNT action handle. * Support push VLAN on ingress traffic and pop VLAN on egress traffic in E-Switch mode. * Added support for pre-defined meter policy API. * Added support for ASO (Advanced Steering Operation) meter. diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index d4aec717f0..efb80a4a49 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -291,7 +291,7 @@ struct mlx5_drop { #define MLX5_MAX_PENDING_QUERIES 4 #define MLX5_CNT_CONTAINER_RESIZE 64 #define MLX5_CNT_SHARED_OFFSET 0x8000 -#define IS_SHARED_CNT(cnt) (!!((cnt) & MLX5_CNT_SHARED_OFFSET)) +#define IS_LEGACY_SHARED_CNT(cnt) (!!((cnt) & MLX5_CNT_SHARED_OFFSET)) #define IS_BATCH_CNT(cnt) (((cnt) & (MLX5_CNT_SHARED_OFFSET - 1)) >= \ MLX5_CNT_BATCH_OFFSET) #define MLX5_CNT_SIZE (sizeof(struct mlx5_flow_counter)) @@ -353,7 +353,10 @@ struct flow_counter_stats { /* Shared counters information for counters. */ struct mlx5_flow_counter_shared { - uint32_t id; /**< User counter ID. */ + union { + uint32_t refcnt; /* Only for shared action management. */ + uint32_t id; /* User counter ID for legacy sharing. */ + }; }; /* Shared counter configuration. */ diff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h index 6e9c4b9cdd..906aa43c5a 100644 --- a/drivers/net/mlx5/mlx5_defs.h +++ b/drivers/net/mlx5/mlx5_defs.h @@ -193,7 +193,7 @@ #define MLX5_HAIRPIN_JUMBO_LOG_SIZE
[dpdk-dev] [PATCH v2 3/5] app/testpmd: support indirect counter action query
From: Michael Baum Counter action query was implemented as part of flow query, but was not implemented as part of indirect action query. This patch adds the required implementation. Signed-off-by: Michael Baum Acked-by: Matan Azrad --- app/test-pmd/config.c | 145 ++ 1 file changed, 77 insertions(+), 68 deletions(-) diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index a9805cc198..bedbfcbb7b 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1618,90 +1618,99 @@ port_action_handle_query(portid_t port_id, uint32_t id) { struct rte_flow_error error; struct port_indirect_action *pia; - uint64_t default_data; - void *data = NULL; - int ret = 0; + union { + struct rte_flow_query_count count; + struct rte_flow_query_age age; + struct rte_flow_action_conntrack ct; + } query; pia = action_get_by_id(port_id, id); if (!pia) return -EINVAL; switch (pia->type) { case RTE_FLOW_ACTION_TYPE_AGE: - data = &default_data; + case RTE_FLOW_ACTION_TYPE_COUNT: break; default: - printf("Indirect action %u (type: %d) on port %u doesn't" - " support query\n", id, pia->type, port_id); - return -1; + printf("Indirect action %u (type: %d) on port %u doesn't support query\n", + id, pia->type, port_id); + return -ENOTSUP; } - if (rte_flow_action_handle_query(port_id, pia->handle, data, &error)) - ret = port_flow_complain(&error); + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x55, sizeof(error)); + memset(&query, 0, sizeof(query)); + if (rte_flow_action_handle_query(port_id, pia->handle, &query, &error)) + return port_flow_complain(&error); switch (pia->type) { case RTE_FLOW_ACTION_TYPE_AGE: - if (!ret) { - struct rte_flow_query_age *resp = data; - - printf("AGE:\n" - " aged: %u\n" - " sec_since_last_hit_valid: %u\n" - " sec_since_last_hit: %" PRIu32 "\n", - resp->aged, - resp->sec_since_last_hit_valid, - resp->sec_since_last_hit); - } - data = NULL; + printf("Indirect AGE action:\n" + " aged: %u\n" + " sec_since_last_hit_valid: %u\n" + " sec_since_last_hit: %" PRIu32 "\n", + query.age.aged, + query.age.sec_since_last_hit_valid, + query.age.sec_since_last_hit); + break; + case RTE_FLOW_ACTION_TYPE_COUNT: + printf("Indirect COUNT action:\n" + " hits_set: %u\n" + " bytes_set: %u\n" + " hits: %" PRIu64 "\n" + " bytes: %" PRIu64 "\n", + query.count.hits_set, + query.count.bytes_set, + query.count.hits, + query.count.bytes); break; case RTE_FLOW_ACTION_TYPE_CONNTRACK: - if (!ret) { - struct rte_flow_action_conntrack *ct = data; - - printf("Conntrack Context:\n" - " Peer: %u, Flow dir: %s, Enable: %u\n" - " Live: %u, SACK: %u, CACK: %u\n" - " Packet dir: %s, Liberal: %u, State: %u\n" - " Factor: %u, Retrans: %u, TCP flags: %u\n" - " Last Seq: %u, Last ACK: %u\n" - " Last Win: %u, Last End: %u\n", - ct->peer_port, - ct->is_original_dir ? "Original" : "Reply", - ct->enable, ct->live_connection, - ct->selective_ack, ct->challenge_ack_passed, - ct->last_direction ? "Original" : "Reply", - ct->liberal_mode, ct->state, - ct->max_ack_window, ct->retransmission_limit, - ct->last_index, ct->last_seq, ct->last_ack, - ct->last_window, ct->last_end); - printf(" Original Dir:\n" - "scale: %u, fin: %u, ack seen: %u\n" - " unacked data: %u\nSent end: %u," - "Reply end: %u, Max win: %u, Max ACK: %u\n", - ct->original_dir.scale, -
[dpdk-dev] [PATCH v2 4/5] net/mlx5: fix flow age event triggering
From: Michael Baum A FLOW_AGE event should be invoked when a new aged-out flow is detected by the PMD after the last user get-aged query calling. The PMD manages 2 flags for this information and check them in order to decide if an event should be invoked: MLX5_AGE_EVENT_NEW - a new aged-out flow was detected. after the last check. MLX5_AGE_TRIGGER - get-aged query was called after the last aged-out flow. The 2 flags were unset after the event invoking. When the user calls get-aged query from the event callback, the TRIGGER flag was set inside the user callback and unset directly after the callback what may stop the event invoking forever. Unset the TRIGGER flag before the event invoking in order to allow set it by the user callback. Fixes: f935ed4b645a ("net/mlx5: support flow hit action for aging") Cc: sta...@dpdk.org Reported-by: David Bouyeure Signed-off-by: Michael Baum Acked-by: Matan Azrad --- drivers/net/mlx5/mlx5.c | 8 +--- drivers/net/mlx5/mlx5.h | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 19ffa16769..10d44c7bbe 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -662,11 +662,13 @@ mlx5_age_event_prepare(struct mlx5_dev_ctx_shared *sh) age_info = &sh->port[i].age_info; if (!MLX5_AGE_GET(age_info, MLX5_AGE_EVENT_NEW)) continue; - if (MLX5_AGE_GET(age_info, MLX5_AGE_TRIGGER)) + MLX5_AGE_UNSET(age_info, MLX5_AGE_EVENT_NEW); + if (MLX5_AGE_GET(age_info, MLX5_AGE_TRIGGER)) { + MLX5_AGE_UNSET(age_info, MLX5_AGE_TRIGGER); rte_eth_dev_callback_process (&rte_eth_devices[sh->port[i].devx_ih_port_id], RTE_ETH_EVENT_FLOW_AGED, NULL); - age_info->flags = 0; + } } } @@ -675,7 +677,7 @@ mlx5_age_event_prepare(struct mlx5_dev_ctx_shared *sh) * * @param[in] sh * Pointer to mlx5_dev_ctx_shared object. - * @param[in] sh + * @param[in] config * Pointer to user dev config. */ static void diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index efb80a4a49..79ae8fbef1 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -563,6 +563,8 @@ struct mlx5_geneve_tlv_option_resource { #define MLX5_AGE_TRIGGER 2 #define MLX5_AGE_SET(age_info, BIT) \ ((age_info)->flags |= (1 << (BIT))) +#define MLX5_AGE_UNSET(age_info, BIT) \ + ((age_info)->flags &= ~(1 << (BIT))) #define MLX5_AGE_GET(age_info, BIT) \ ((age_info)->flags & (1 << (BIT))) #define GET_PORT_AGE_INFO(priv) \ -- 2.18.1
[dpdk-dev] [PATCH v2 5/5] net/mlx5: use aging by counter when counter is existed
From: Michael Baum The driver support 2 mechanisms in order to support AGE action: 1. Aging by counter - HW counter will be configured to the flow traffic, the driver polls the counter values efficiently to detect flow timeout. 2. Aging by ASO flow hit bit - HW ASO flow-hit bit is allocated for the flow, the driver polls the bit efficiently to detect flow timeout. ASO bit is only single bit resource while counter is 16 bytes, hence, it is better to use ASO instead of counter for aging. When a non-shared COUNT action is also configured to the flow, the driver can use the same counter also for AGE action and no need to create more ASO action for it. The current code always uses ASO when it is supported in the device, change it to reuse the non-shared counter if it exists in the flow. Signed-off-by: Michael Baum Acked-by: Matan Azrad --- drivers/net/mlx5/mlx5_flow_dv.c | 149 ++-- 1 file changed, 102 insertions(+), 47 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index b74bac1083..2fb6621017 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -7143,6 +7143,12 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "Shared ASO age action is not supported for group 0"); + if (action_flags & MLX5_FLOW_ACTION_AGE) + return rte_flow_error_set + (error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "duplicate age actions set"); action_flags |= MLX5_FLOW_ACTION_AGE; ++actions_n; break; @@ -11162,6 +11168,47 @@ flow_dv_translate_create_aso_age(struct rte_eth_dev *dev, return age_idx; } +/** + * Prepares DV flow counter with aging configuration. + * Gets it by index when exists, creates a new one when doesn't. + * + * @param[in] dev + * Pointer to rte_eth_dev structure. + * @param[in] dev_flow + * Pointer to the mlx5_flow. + * @param[in, out] flow + * Pointer to the sub flow. + * @param[in] count + * Pointer to the counter action configuration. + * @param[in] age + * Pointer to the aging action configuration. + * @param[out] error + * Pointer to the error structure. + * + * @return + * Pointer to the counter, NULL otherwise. + */ +static struct mlx5_flow_counter * +flow_dv_prepare_counter(struct rte_eth_dev *dev, + struct mlx5_flow *dev_flow, + struct rte_flow *flow, + const struct rte_flow_action_count *count, + const struct rte_flow_action_age *age, + struct rte_flow_error *error) +{ + if (!flow->counter) { + flow->counter = flow_dv_translate_create_counter(dev, dev_flow, +count, age); + if (!flow->counter) { + rte_flow_error_set(error, rte_errno, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "cannot create counter object."); + return NULL; + } + } + return flow_dv_counter_get_by_idx(dev, flow->counter, NULL); +} + /** * Fill the flow with DV spec, lock free * (mutex should be acquired by caller). @@ -11215,7 +11262,7 @@ flow_dv_translate(struct rte_eth_dev *dev, } mhdr_dummy; struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res; const struct rte_flow_action_count *count = NULL; - const struct rte_flow_action_age *age = NULL; + const struct rte_flow_action_age *non_shared_age = NULL; union flow_dv_attr flow_attr = { .attr = 0 }; uint32_t tag_be; union mlx5_flow_tbl_key tbl_key; @@ -11230,6 +11277,7 @@ flow_dv_translate(struct rte_eth_dev *dev, const struct rte_flow_action_sample *sample = NULL; struct mlx5_flow_sub_actions_list *sample_act; uint32_t sample_act_pos = UINT32_MAX; + uint32_t age_act_pos = UINT32_MAX; uint32_t num_of_dest = 0; int tmp_actions_n = 0; uint32_t table; @@ -11452,7 +11500,12 @@ flow_dv_translate(struct rte_eth_dev *dev, age_act = flow_aso_age_get_by_idx(dev, flow->age); __atomic_fetch_add(&age_act->refcnt, 1, __ATOMIC_RELAXED); - dev_flow->dv.actions[actions_n++] = age_act->dr_action; + age_act_pos = actions_n++; +
[dpdk-dev] [PATCH v2] common/mlx5: add provider query port support to glue library
The rdma-core mlx5 provider introduced the port attributes query API since version v35.0 - the mlx5dv_query_port routine. In order to support this change in the rdma-core the conditional compilation flag HAVE_MLX5DV_DR_DEVX_PORT_V35 is introduced by the this patch. In the OFED rdma-core version the new compatible mlx5dv_query_port routine was introduced as well, replacing the existing proprietary mlx5dv_query_devx_port routine. The proprietary routine was controlled in PMD code with HAVE_MLX5DV_DR_DEVX_PORT conditional flag. Currently, the OFED rdma-core library contains both versions of port query API. And this version is a transitional one, there are the plans to remove the proprietary mlx5dv_query_devx_port routine and the HAVE_MLX5DV_DR_DEVX_PORT flag in PMD will not work anymore. We had one more dependency on this flag in the code (for the mlx5dv_dr_action_create_dest_ib_port routine) and the patch fixes mentioned dependency also, by introducing the new dedicated conditional flag - HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT. This patch is highly desirable to be provided in DPDK LTS releases due to it covers the major compatibility issue. Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- v1: http://patches.dpdk.org/project/dpdk/patch/20210607093726.14546-1-viachesl...@nvidia.com/ v2: commit message was clarified drivers/common/mlx5/linux/meson.build | 4 ++ drivers/common/mlx5/linux/mlx5_glue.c | 57 - drivers/common/mlx5/linux/mlx5_glue.h | 16 ++- drivers/net/mlx5/linux/mlx5_os.c | 60 --- drivers/net/mlx5/mlx5_flow_dv.c | 2 +- 5 files changed, 93 insertions(+), 46 deletions(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 007834a49b..5cea1b44d7 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -93,6 +93,10 @@ has_sym_args = [ 'IBV_WQ_FLAG_RX_END_PADDING' ], [ 'HAVE_MLX5DV_DR_DEVX_PORT', 'infiniband/mlx5dv.h', 'mlx5dv_query_devx_port' ], + [ 'HAVE_MLX5DV_DR_DEVX_PORT_V35', 'infiniband/mlx5dv.h', + 'mlx5dv_query_port' ], + [ 'HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT', 'infiniband/mlx5dv.h', + 'mlx5dv_dr_action_create_dest_ib_port' ], [ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h', 'mlx5dv_devx_obj_create' ], [ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h', diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c index d3bd645a5b..00be8114be 100644 --- a/drivers/common/mlx5/linux/mlx5_glue.c +++ b/drivers/common/mlx5/linux/mlx5_glue.c @@ -391,7 +391,7 @@ mlx5_glue_dr_create_flow_action_dest_flow_tbl(void *tbl) static void * mlx5_glue_dr_create_flow_action_dest_port(void *domain, uint32_t port) { -#ifdef HAVE_MLX5DV_DR_DEVX_PORT +#ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT return mlx5dv_dr_action_create_dest_ib_port(domain, port); #else #ifdef HAVE_MLX5DV_DR_ESWITCH @@ -1087,17 +1087,54 @@ mlx5_glue_devx_wq_query(struct ibv_wq *wq, const void *in, size_t inlen, static int mlx5_glue_devx_port_query(struct ibv_context *ctx, uint32_t port_num, - struct mlx5dv_devx_port *mlx5_devx_port) -{ + struct mlx5_port_info *info) +{ + int err = 0; + + info->query_flags = 0; +#ifdef HAVE_MLX5DV_DR_DEVX_PORT_V35 + /* The DevX port query API is implemented (rdma-core v35 and above). */ + struct mlx5_ib_uapi_query_port devx_port; + + memset(&devx_port, 0, sizeof(devx_port)); + err = mlx5dv_query_port(ctx, port_num, &devx_port); + if (err) + return err; + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT_REG_C0) { + info->vport_meta_tag = devx_port.reg_c0.value; + info->vport_meta_mask = devx_port.reg_c0.mask; + info->query_flags |= MLX5_PORT_QUERY_REG_C0; + } + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT) { + info->vport_id = devx_port.vport; + info->query_flags |= MLX5_PORT_QUERY_VPORT; + } +#else #ifdef HAVE_MLX5DV_DR_DEVX_PORT - return mlx5dv_query_devx_port(ctx, port_num, mlx5_devx_port); + /* The legacy DevX port query API is implemented (prior v35). */ + struct mlx5dv_devx_port devx_port = { + .comp_mask = MLX5DV_DEVX_PORT_VPORT | +MLX5DV_DEVX_PORT_MATCH_REG_C_0 + }; + + err = mlx5dv_query_devx_port(ctx, port_num, &devx_port); + if (err) + return err; + if (devx_port.comp_mask & MLX5DV_DEVX_PORT_MATCH_REG_C_0) { + info->vport_meta_ta
[dpdk-dev] [PATCH] common/mlx5: fix Netlink port name attribute padding
On some kernels the string attributes within Netlink reply messages might be not padded with zeroes (in cases when string length is aligned with 4-byte boundary). This caused wrong physical port names recognition and mlx5 PMD load failures. Fixes: 30a86157f6d5 ("net/mlx5: support PF representor") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/common/mlx5/linux/mlx5_nl.c | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c index f0d04f9473..3f1912d078 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.c +++ b/drivers/common/mlx5/linux/mlx5_nl.c @@ -33,6 +33,8 @@ #define MLX5_SEND_BUF_SIZE 32768 /* Receive buffer size for the Netlink socket */ #define MLX5_RECV_BUF_SIZE 32768 +/* Maximal physical port name length. */ +#define MLX5_PHYS_PORT_NAME_MAX 128 /** Parameters of VLAN devices created by driver. */ #define MLX5_VMWA_VLAN_DEVICE_PFX "evmlx" @@ -1191,6 +1193,7 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg) size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg)); bool switch_id_set = false; bool num_vf_set = false; + int len; if (nh->nlmsg_type != RTM_NEWLINK) goto error; @@ -1206,7 +1209,24 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg) num_vf_set = true; break; case IFLA_PHYS_PORT_NAME: - mlx5_translate_port_name((char *)payload, &info); + len = RTA_PAYLOAD(ra); + /* Some kernels do not pad attributes with zero. */ + if (len > 0 && len < MLX5_PHYS_PORT_NAME_MAX) { + char name[MLX5_PHYS_PORT_NAME_MAX]; + + /* +* We can't just patch the message with padding +* zero - it might corrupt the following items +* in the message, we have to copy the string +* by attribute length and pad the copied one. +*/ + memcpy(name, payload, len); + name[len] = 0; + mlx5_translate_port_name(name, &info); + } else { + info.name_type = + MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; + } break; case IFLA_PHYS_SWITCH_ID: info.switch_id = 0; -- 2.18.1
[dpdk-dev] [PATCH] app/testpmd: fix offloads for the newly attached port
For the newly attached ports (with "port attach" command) the default offloads settings, configured from application command line, were not applied, causing port start failure following the attach. For example, if scattering offload was configured in command line and rxpkts was configured for multiple segments, the newly attached port start was failed due to missing scattering offload enable in the new port settings. The missing code to apply the offloads to the new device and its queues is added. Cc: sta...@dpdk.org Fixes: c9cce42876f5 ("ethdev: remove deprecated attach/detach functions") Signed-off-by: Viacheslav Ovsiienko --- app/test-pmd/testpmd.c | 32 1 file changed, 32 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 8ed1b97dec..b4ec182423 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -1599,6 +1599,7 @@ reconfig(portid_t new_port_id, unsigned socket_id) { struct rte_port *port; int ret; + int i; /* Reconfiguration of Ethernet ports. */ port = &ports[new_port_id]; @@ -1611,7 +1612,38 @@ reconfig(portid_t new_port_id, unsigned socket_id) port->need_reconfig = 1; port->need_reconfig_queues = 1; port->socket_id = socket_id; + port->tx_metadata = 0; + + /* Apply default TxRx configuration to the port */ + port->dev_conf.txmode = tx_mode; + port->dev_conf.rxmode = rx_mode; + + if (!(port->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)) + port->dev_conf.txmode.offloads &= + ~DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + /* Apply Rx offloads configuration */ + for (i = 0; i < port->dev_info.max_rx_queues; i++) + port->rx_conf[i].offloads = port->dev_conf.rxmode.offloads; + /* Apply Tx offloads configuration */ + for (i = 0; i < port->dev_info.max_tx_queues; i++) + port->tx_conf[i].offloads = port->dev_conf.txmode.offloads; + + /* Check for maximum number of segments per MTU. Accordingly +* update the mbuf data size. +*/ + if (port->dev_info.rx_desc_lim.nb_mtu_seg_max != UINT16_MAX && + port->dev_info.rx_desc_lim.nb_mtu_seg_max != 0) { + uint16_t data_size = rx_mode.max_rx_pkt_len / + port->dev_info.rx_desc_lim.nb_mtu_seg_max; + if ((data_size + RTE_PKTMBUF_HEADROOM) > mbuf_data_size[0]) { + mbuf_data_size[0] = data_size + RTE_PKTMBUF_HEADROOM; + TESTPMD_LOG(WARNING, + "Adjusted mbuf size of the first segment %hu\n", + mbuf_data_size[0]); + } + } init_port_config(); } -- 2.18.1
[dpdk-dev] [PATCH] net/mlx5: fix TSO multi-segment inline length
The inline data length for TSO ethernet segment should be calculated from the TSO header instead of the inline size configured by txq_inline_min devarg or reported by the NIC. It is imposed by the nature of TSO offload - inline header is being duplicated to every output TCP packet. Fixes: cacb44a09962 ("net/mlx5: add no-inline Tx flag") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_tx.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_tx.h b/drivers/net/mlx5/mlx5_tx.h index 7d3ff8407c..e8b1c0f108 100644 --- a/drivers/net/mlx5/mlx5_tx.h +++ b/drivers/net/mlx5/mlx5_tx.h @@ -1338,7 +1338,8 @@ mlx5_tx_eseg_mdat(struct mlx5_txq_data *__rte_restrict txq, * Copying may be interrupted inside the routine * if run into no inline hint flag. */ - copy = tlen >= txq->inlen_mode ? 0 : (txq->inlen_mode - tlen); + copy = tso ? inlen : txq->inlen_mode; + copy = tlen >= copy ? 0 : (copy - tlen); copy = mlx5_tx_mseg_memcpy(pdst, loc, part, copy, olx); tlen += copy; if (likely(inlen <= tlen) || copy < part) { -- 2.18.1
[dpdk-dev] [PATCH] net/mlx5: fix multi-segment inline for the first segment
If the first segment in the multi-segment packet is short and below the inline threshold it should be inline into the WQE to improve the performance. For example, the T-Rex traffic generator might use small leading segments to handle packet headers and performance was affected. Fixes: cacb44a09962 ("net/mlx5: add no-inline Tx flag") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_tx.h | 28 +--- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/net/mlx5/mlx5_tx.h b/drivers/net/mlx5/mlx5_tx.h index e8b1c0f108..1a35919371 100644 --- a/drivers/net/mlx5/mlx5_tx.h +++ b/drivers/net/mlx5/mlx5_tx.h @@ -2041,6 +2041,8 @@ mlx5_tx_packet_multi_inline(struct mlx5_txq_data *__rte_restrict txq, unsigned int nxlen; uintptr_t start; + mbuf = loc->mbuf; + nxlen = rte_pktmbuf_data_len(mbuf); /* * Packet length exceeds the allowed inline data length, * check whether the minimal inlining is required. @@ -2050,28 +2052,23 @@ mlx5_tx_packet_multi_inline(struct mlx5_txq_data *__rte_restrict txq, MLX5_ESEG_MIN_INLINE_SIZE); MLX5_ASSERT(txq->inlen_mode <= txq->inlen_send); inlen = txq->inlen_mode; - } else { - if (loc->mbuf->ol_flags & PKT_TX_DYNF_NOINLINE || - !vlan || txq->vlan_en) { - /* -* VLAN insertion will be done inside by HW. -* It is not utmost effective - VLAN flag is -* checked twice, but we should proceed the -* inlining length correctly and take into -* account the VLAN header being inserted. -*/ - return mlx5_tx_packet_multi_send - (txq, loc, olx); - } + } else if (vlan && !txq->vlan_en) { + /* +* VLAN insertion is requested and hardware does not +* support the offload, will do with software inline. +*/ inlen = MLX5_ESEG_MIN_INLINE_SIZE; + } else if (mbuf->ol_flags & PKT_TX_DYNF_NOINLINE || + nxlen > txq->inlen_send) { + return mlx5_tx_packet_multi_send(txq, loc, olx); + } else { + goto do_first; } /* * Now we know the minimal amount of data is requested * to inline. Check whether we should inline the buffers * from the chain beginning to eliminate some mbufs. */ - mbuf = loc->mbuf; - nxlen = rte_pktmbuf_data_len(mbuf); if (unlikely(nxlen <= txq->inlen_send)) { /* We can inline first mbuf at least. */ if (nxlen < inlen) { @@ -2093,6 +2090,7 @@ mlx5_tx_packet_multi_inline(struct mlx5_txq_data *__rte_restrict txq, goto do_align; } } +do_first: do { inlen = nxlen; mbuf = NEXT(mbuf); -- 2.18.1
[dpdk-dev] [PATCH v3 1/2] common/mlx5: add provider query port support to glue library
In order to get E-Switch vport identifiers the mlx5 PMD relies on two approaches: - use port query API if it is provided by rdma-core library - otherwise, deduce vport ids from the related VF index The latter is not reliable and may not work with newer kernel driver versions and in some configurations (LAG), causing the E-Switch malfunction. Hence, engaging the port query API is highly desirable. The port attributes query API was supported by vendor rdma-core versions only (in OFED). In Upstream, the rdma-core mlx5 provider introduced the port attributes query API since version v35.0 - the mlx5dv_query_port routine, that differs from vendor API. In order to support this change in the rdma-core the conditional compilation flag HAVE_MLX5DV_DR_DEVX_PORT_V35 is introduced by the this patch. In the OFED rdma-core version the new compatible mlx5dv_query_port routine was introduced as well, replacing the existing proprietary mlx5dv_query_devx_port routine. The proprietary routine is still controlled in PMD code with HAVE_MLX5DV_DR_DEVX_PORT conditional flag. Currently, the OFED rdma-core library contains both versions of port query API. And this version is a transitional one, there are the plans to remove the proprietary mlx5dv_query_devx_port routine and the HAVE_MLX5DV_DR_DEVX_PORT flag in PMD will not work anymore. With this patch applied the mlx5 PMD can be compiled and operates over all rdma-core versions: - Upstream rdma-core before v35 (deduces vport id from VF name) (* E-Switch may not operate correctly) - Upstream rdma-core v35 and above (uses common port query API) - rdma-core OFED before 5.5 (uses proprietary port query API) - rdma-core OFED 5.5 and above (uses common port query API) Despite this patch is not a bugfix (it follows the introduced API variation in underlying library), it covers the major compatibility issue and is highly desired to be ported to DPDK LTS. Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- v1: http://patches.dpdk.org/project/dpdk/patch/20210607093726.14546-1-viachesl...@nvidia.com/ v2: http://patches.dpdk.org/project/dpdk/patch/20210619124830.25297-1-viachesl...@nvidia.com/#134196 - commit message was clarified v3: - reword commit message addressing comments - split patch into small series --- drivers/common/mlx5/linux/meson.build | 2 + drivers/common/mlx5/linux/mlx5_glue.c | 55 drivers/common/mlx5/linux/mlx5_glue.h | 16 ++- drivers/net/mlx5/linux/mlx5_os.c | 60 --- 4 files changed, 89 insertions(+), 44 deletions(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 007834a49b..5a0ee51b37 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -93,6 +93,8 @@ has_sym_args = [ 'IBV_WQ_FLAG_RX_END_PADDING' ], [ 'HAVE_MLX5DV_DR_DEVX_PORT', 'infiniband/mlx5dv.h', 'mlx5dv_query_devx_port' ], + [ 'HAVE_MLX5DV_DR_DEVX_PORT_V35', 'infiniband/mlx5dv.h', + 'mlx5dv_query_port' ], [ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h', 'mlx5dv_devx_obj_create' ], [ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h', diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c index d3bd645a5b..38b174aa31 100644 --- a/drivers/common/mlx5/linux/mlx5_glue.c +++ b/drivers/common/mlx5/linux/mlx5_glue.c @@ -1087,17 +1087,54 @@ mlx5_glue_devx_wq_query(struct ibv_wq *wq, const void *in, size_t inlen, static int mlx5_glue_devx_port_query(struct ibv_context *ctx, uint32_t port_num, - struct mlx5dv_devx_port *mlx5_devx_port) -{ + struct mlx5_port_info *info) +{ + int err = 0; + + info->query_flags = 0; +#ifdef HAVE_MLX5DV_DR_DEVX_PORT_V35 + /* The DevX port query API is implemented (rdma-core v35 and above). */ + struct mlx5_ib_uapi_query_port devx_port; + + memset(&devx_port, 0, sizeof(devx_port)); + err = mlx5dv_query_port(ctx, port_num, &devx_port); + if (err) + return err; + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT_REG_C0) { + info->vport_meta_tag = devx_port.reg_c0.value; + info->vport_meta_mask = devx_port.reg_c0.mask; + info->query_flags |= MLX5_PORT_QUERY_REG_C0; + } + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT) { + info->vport_id = devx_port.vport; + info->query_flags |= MLX5_PORT_QUERY_VPORT; + } +#else #ifdef HAVE_MLX5DV_DR_DEVX_PORT - return mlx5dv_query_devx_port(ctx, port_num, mlx5_devx_port); + /* The l
[dpdk-dev] [PATCH v3 2/2] common/mlx5: fix compilation flag on port query API
There is the compilation flag HAVE_MLX5DV_DR_DEVX_PORT that depends on presence of mlx5dv_query_devx_port routine in rdma-core library. The mlx5dv_query_devx_port routine is vendor specific, exists only in OFED version of rdma-core library and there are the plans to remove the routine and replace one with Upstream compatible mlx5dv_query_port version. As mlx5dv_query_devx_port is being removed we should reconsider all the dependencies on the HAVE_MLX5DV_DR_DEVX_PORT compilation flag and introduce the new dedicated compilation flags as needed. Fixes: 6cfe84fbe7b1 ("net/mlx5: fix port action for LAG") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- drivers/common/mlx5/linux/meson.build | 2 ++ drivers/common/mlx5/linux/mlx5_glue.c | 2 +- drivers/net/mlx5/mlx5_flow_dv.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 5a0ee51b37..5cea1b44d7 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -95,6 +95,8 @@ has_sym_args = [ 'mlx5dv_query_devx_port' ], [ 'HAVE_MLX5DV_DR_DEVX_PORT_V35', 'infiniband/mlx5dv.h', 'mlx5dv_query_port' ], + [ 'HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT', 'infiniband/mlx5dv.h', + 'mlx5dv_dr_action_create_dest_ib_port' ], [ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h', 'mlx5dv_devx_obj_create' ], [ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h', diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c index 38b174aa31..00be8114be 100644 --- a/drivers/common/mlx5/linux/mlx5_glue.c +++ b/drivers/common/mlx5/linux/mlx5_glue.c @@ -391,7 +391,7 @@ mlx5_glue_dr_create_flow_action_dest_flow_tbl(void *tbl) static void * mlx5_glue_dr_create_flow_action_dest_port(void *domain, uint32_t port) { -#ifdef HAVE_MLX5DV_DR_DEVX_PORT +#ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT return mlx5dv_dr_action_create_dest_ib_port(domain, port); #else #ifdef HAVE_MLX5DV_DR_ESWITCH diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 62edc4fa85..c5d4b01e57 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -10342,7 +10342,7 @@ flow_dv_translate_action_port_id(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "No eswitch info was found for port"); -#ifdef HAVE_MLX5DV_DR_DEVX_PORT +#ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT /* * This parameter is transferred to * mlx5dv_dr_action_create_dest_ib_port(). -- 2.18.1
[dpdk-dev] [PATCH] common/mlx5: fix Netlink receive message buffer size
If there are many VFs the Netlink message length sent by kernel in reply to RTM_GETLINK request can be large. We should query the size of message being received in advance and allocate the large enough buffer to handle these large messages. Fixes: ccdcba53a3f4 ("net/mlx5: use Netlink to add/remove MAC addresses") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/common/mlx5/linux/mlx5_nl.c | 69 +++-- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c index 3f1912d078..dc8dafd0a8 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.c +++ b/drivers/common/mlx5/linux/mlx5_nl.c @@ -189,8 +189,8 @@ int mlx5_nl_init(int protocol) { int fd; - int sndbuf_size = MLX5_SEND_BUF_SIZE; - int rcvbuf_size = MLX5_RECV_BUF_SIZE; + int buf_size; + socklen_t opt_size; struct sockaddr_nl local = { .nl_family = AF_NETLINK, }; @@ -201,16 +201,36 @@ mlx5_nl_init(int protocol) rte_errno = errno; return -rte_errno; } - ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, sizeof(int)); + opt_size = sizeof(buf_size); + ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, &opt_size); if (ret == -1) { rte_errno = errno; goto error; } - ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(int)); + DRV_LOG(DEBUG, "Netlink socket send buffer: %d", buf_size); + if (buf_size < MLX5_SEND_BUF_SIZE) { + ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, +&buf_size, sizeof(buf_size)); + if (ret == -1) { + rte_errno = errno; + goto error; + } + } + opt_size = sizeof(buf_size); + ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, &opt_size); if (ret == -1) { rte_errno = errno; goto error; } + DRV_LOG(DEBUG, "Netlink socket recv buffer: %d", buf_size); + if (buf_size < MLX5_RECV_BUF_SIZE) { + ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, +&buf_size, sizeof(buf_size)); + if (ret == -1) { + rte_errno = errno; + goto error; + } + } ret = bind(fd, (struct sockaddr *)&local, sizeof(local)); if (ret == -1) { rte_errno = errno; @@ -332,11 +352,7 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg), void *arg) { struct sockaddr_nl sa; - void *buf = mlx5_malloc(0, MLX5_RECV_BUF_SIZE, 0, SOCKET_ID_ANY); - struct iovec iov = { - .iov_base = buf, - .iov_len = MLX5_RECV_BUF_SIZE, - }; + struct iovec iov; struct msghdr msg = { .msg_name = &sa, .msg_namelen = sizeof(sa), @@ -344,18 +360,43 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg), /* One message at a time */ .msg_iovlen = 1, }; + void *buf = NULL; int multipart = 0; int ret = 0; - if (!buf) { - rte_errno = ENOMEM; - return -rte_errno; - } do { struct nlmsghdr *nh; - int recv_bytes = 0; + int recv_bytes; do { + /* Query length of incoming message. */ + iov.iov_base = NULL; + iov.iov_len = 0; + recv_bytes = recvmsg(nlsk_fd, &msg, +MSG_PEEK | MSG_TRUNC); + if (recv_bytes < 0) { + rte_errno = errno; + ret = -rte_errno; + goto exit; + } + if (recv_bytes == 0) { + rte_errno = ENODATA; + ret = -rte_errno; + goto exit; + } + /* Allocate buffer to fetch the message. */ + if (recv_bytes < MLX5_RECV_BUF_SIZE) + recv_bytes = MLX5_RECV_BUF_SIZE; + mlx5_free(buf); + buf = mlx5_malloc(0, recv_bytes, 0, SOCKET_ID_ANY); + if (!buf) { + rte_errno = ENOMEM; + ret = -rte_errno; + goto exit; + } + /* Fetch the message. */ +
[dpdk-dev] [PATCH v4 1/2] common/mlx5: add provider query port support to glue library
In order to get E-Switch vport identifiers the mlx5 PMD relies on two approaches: [a] use port query API if it is provided by rdma-core library [b] otherwise, deduce vport ids from the related VF index The latter is not reliable and may not work with newer kernel drivers and in some configurations (LAG), causing E-Switch malfunction. Hence, engaging the port query API is highly desirable. Depending on rdma-core version the port query API is: - very old OFED versions have no query API (approach [b]) - rdma-core OFED < 5.5 provides mlx5dv_query_devx_port, HAVE_MLX5DV_DR_DEVX_PORT flag is defined (approach [a]) - rdma-core OFED >= 5.5 has mlx5dv_query_port, flag HAVE_MLX5DV_DR_DEVX_PORT_V35 is defined (approach [a]) - future OFED versions might remove mlx5dv_query_devx_port and HAVE_MLX5DV_DR_DEVX_PORT will not be defined - Upstream rdma-core < v35 has no port query API (approach [b]) - Upstream rdma-core >= v35 has mlx5dv_query_port, flag HAVE_MLX5DV_DR_DEVX_PORT_V35 is defined (approach [a]) In order to support the new mlx5dv_query_port routine, the conditional compilation flag HAVE_MLX5DV_DR_DEVX_PORT_V35 is introduced by the this patch. The flag HAVE_MLX5DV_DR_DEVX_PORT is kept for compatibility with previous rdma-core versions. Despite this patch is not a bugfix (it follows the introduced API variation in underlying library), it resolves the compatibility issue and is highly desired to be ported to DPDK LTS. Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- drivers/common/mlx5/linux/meson.build | 2 + drivers/common/mlx5/linux/mlx5_glue.c | 55 drivers/common/mlx5/linux/mlx5_glue.h | 16 ++- drivers/net/mlx5/linux/mlx5_os.c | 60 --- 4 files changed, 89 insertions(+), 44 deletions(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 007834a49b..7168edc62c 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -93,6 +93,8 @@ has_sym_args = [ 'IBV_WQ_FLAG_RX_END_PADDING' ], [ 'HAVE_MLX5DV_DR_DEVX_PORT', 'infiniband/mlx5dv.h', 'mlx5dv_query_devx_port' ], +[ 'HAVE_MLX5DV_DR_DEVX_PORT_V35', 'infiniband/mlx5dv.h', +'mlx5dv_query_port' ], [ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h', 'mlx5dv_devx_obj_create' ], [ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h', diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c index d3bd645a5b..38b174aa31 100644 --- a/drivers/common/mlx5/linux/mlx5_glue.c +++ b/drivers/common/mlx5/linux/mlx5_glue.c @@ -1087,17 +1087,54 @@ mlx5_glue_devx_wq_query(struct ibv_wq *wq, const void *in, size_t inlen, static int mlx5_glue_devx_port_query(struct ibv_context *ctx, uint32_t port_num, - struct mlx5dv_devx_port *mlx5_devx_port) -{ + struct mlx5_port_info *info) +{ + int err = 0; + + info->query_flags = 0; +#ifdef HAVE_MLX5DV_DR_DEVX_PORT_V35 + /* The DevX port query API is implemented (rdma-core v35 and above). */ + struct mlx5_ib_uapi_query_port devx_port; + + memset(&devx_port, 0, sizeof(devx_port)); + err = mlx5dv_query_port(ctx, port_num, &devx_port); + if (err) + return err; + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT_REG_C0) { + info->vport_meta_tag = devx_port.reg_c0.value; + info->vport_meta_mask = devx_port.reg_c0.mask; + info->query_flags |= MLX5_PORT_QUERY_REG_C0; + } + if (devx_port.flags & MLX5DV_QUERY_PORT_VPORT) { + info->vport_id = devx_port.vport; + info->query_flags |= MLX5_PORT_QUERY_VPORT; + } +#else #ifdef HAVE_MLX5DV_DR_DEVX_PORT - return mlx5dv_query_devx_port(ctx, port_num, mlx5_devx_port); + /* The legacy DevX port query API is implemented (prior v35). */ + struct mlx5dv_devx_port devx_port = { + .comp_mask = MLX5DV_DEVX_PORT_VPORT | +MLX5DV_DEVX_PORT_MATCH_REG_C_0 + }; + + err = mlx5dv_query_devx_port(ctx, port_num, &devx_port); + if (err) + return err; + if (devx_port.comp_mask & MLX5DV_DEVX_PORT_MATCH_REG_C_0) { + info->vport_meta_tag = devx_port.reg_c_0.value; + info->vport_meta_mask = devx_port.reg_c_0.mask; + info->query_flags |= MLX5_PORT_QUERY_REG_C0; + } + if (devx_port.comp_mask & MLX5DV_DEVX_PORT_VPORT) { + info->vport_id = devx_port.vport_num; + info->query_flags |= MLX5_PORT_QUERY_VPORT; + } #else -
[dpdk-dev] [PATCH v4 2/2] common/mlx5: fix compilation flag on port query API
The compilation flag HAVE_MLX5DV_DR_DEVX_PORT depends on presence of mlx5dv_query_devx_port routine in rdma-core library. The mlx5dv_query_devx_port routine exists only in OFED versions of rdma-core library and is being planned to be removed and replaced with Upstream compatible mlx5dv_query_port. As mlx5dv_query_devx_port is being removed all the dependencies on the HAVE_MLX5DV_DR_DEVX_PORT compilation flag are reconsidered. Fixes: 6cfe84fbe7b1 ("net/mlx5: fix port action for LAG") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- drivers/common/mlx5/linux/meson.build | 2 ++ drivers/common/mlx5/linux/mlx5_glue.c | 2 +- drivers/net/mlx5/mlx5_flow_dv.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 7168edc62c..4ef163e1ef 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -95,6 +95,8 @@ has_sym_args = [ 'mlx5dv_query_devx_port' ], [ 'HAVE_MLX5DV_DR_DEVX_PORT_V35', 'infiniband/mlx5dv.h', 'mlx5dv_query_port' ], +[ 'HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT', 'infiniband/mlx5dv.h', +'mlx5dv_dr_action_create_dest_ib_port' ], [ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h', 'mlx5dv_devx_obj_create' ], [ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h', diff --git a/drivers/common/mlx5/linux/mlx5_glue.c b/drivers/common/mlx5/linux/mlx5_glue.c index 38b174aa31..00be8114be 100644 --- a/drivers/common/mlx5/linux/mlx5_glue.c +++ b/drivers/common/mlx5/linux/mlx5_glue.c @@ -391,7 +391,7 @@ mlx5_glue_dr_create_flow_action_dest_flow_tbl(void *tbl) static void * mlx5_glue_dr_create_flow_action_dest_port(void *domain, uint32_t port) { -#ifdef HAVE_MLX5DV_DR_DEVX_PORT +#ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT return mlx5dv_dr_action_create_dest_ib_port(domain, port); #else #ifdef HAVE_MLX5DV_DR_ESWITCH diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 62edc4fa85..c5d4b01e57 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -10342,7 +10342,7 @@ flow_dv_translate_action_port_id(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "No eswitch info was found for port"); -#ifdef HAVE_MLX5DV_DR_DEVX_PORT +#ifdef HAVE_MLX5DV_DR_CREATE_DEST_IB_PORT /* * This parameter is transferred to * mlx5dv_dr_action_create_dest_ib_port(). -- 2.18.1
[dpdk-dev] [PATCH] net/mlx5: fix the drop action for the DR/DV
There are multiple branches in rdma-core library backing: the rte flows: - Verbs - Direct Verbs (DV) - Direct Rules (DR) The Verbs API always requires the specifying the queue even if there is the drop action in the flow, though the kernel optimizes out the actual queue usage for the flows containing the drop action. The PMD handles the dedicated Rx queue to provide Verbs API compatibility. The DV/DR API does not require explicit specifying the queue at the flow creation, but PMD still specified the dedicated drop queue as action. It performed the packet forwarding to the dummy queue (that was not polled at all) causing the steering pipeline resources usage and degrading the overall packet processing rate. For example, with inserted flow to drop all the ingress packets the statistics reported only 15Mpps of 64B packets were received over 100Gbps line. Since the Direct Rule API for E-Switch was introduced the rdma-core supports the dedicated drop action, that is recognized both for DV and DR and can be used for the entire device in unified fashion, regardless of steering domain. The similar drop action was introduced for E-Switch, the usage of this one can be extended for other steering domains, not for E-Switch's one only. This patch: - renames esw_drop_action to dr_drop_action to emphasize the global nature of the variable (not only E-Switch domain) - specifies this global drop action instead of dedicated drop queue for the DR/DV flows Cc: sta...@dpdk.org Fixes: 34fa7c0268e7 ("net/mlx5: add drop action to Direct Verbs E-Switch") Fixes: 65b3cd0dc39b ("net/mlx5: create global drop action") Signed-off-by: Viacheslav Ovsiienko Acked-by: Matan Azrad --- drivers/net/mlx5/linux/mlx5_os.c | 24 +--- drivers/net/mlx5/mlx5.h | 2 +- drivers/net/mlx5/mlx5_flow_dv.c | 13 +++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index 5e3ae9f10e..c9f997963c 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -325,7 +325,17 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv) goto error; } sh->fdb_domain = domain; - sh->esw_drop_action = mlx5_glue->dr_create_flow_action_drop(); + } + /* +* The drop action is just some dummy placeholder in rdma-core. It +* does not belong to domains and has no any attributes, and, can be +* shared by the entire device. +*/ + sh->dr_drop_action = mlx5_glue->dr_create_flow_action_drop(); + if (!sh->dr_drop_action) { + DRV_LOG(ERR, "FDB mlx5dv_dr_create_flow_action_drop"); + err = errno; + goto error; } #endif if (!sh->tunnel_hub) @@ -361,9 +371,9 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv) mlx5_glue->dr_destroy_domain(sh->fdb_domain); sh->fdb_domain = NULL; } - if (sh->esw_drop_action) { - mlx5_glue->destroy_flow_action(sh->esw_drop_action); - sh->esw_drop_action = NULL; + if (sh->dr_drop_action) { + mlx5_glue->destroy_flow_action(sh->dr_drop_action); + sh->dr_drop_action = NULL; } if (sh->pop_vlan_action) { mlx5_glue->destroy_flow_action(sh->pop_vlan_action); @@ -418,9 +428,9 @@ mlx5_os_free_shared_dr(struct mlx5_priv *priv) mlx5_glue->dr_destroy_domain(sh->fdb_domain); sh->fdb_domain = NULL; } - if (sh->esw_drop_action) { - mlx5_glue->destroy_flow_action(sh->esw_drop_action); - sh->esw_drop_action = NULL; + if (sh->dr_drop_action) { + mlx5_glue->destroy_flow_action(sh->dr_drop_action); + sh->dr_drop_action = NULL; } #endif if (sh->pop_vlan_action) { diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index e4963bd107..1c70e28c77 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -713,7 +713,7 @@ struct mlx5_dev_ctx_shared { struct mlx5_hlist *flow_tbls; struct mlx5_flow_tunnel_hub *tunnel_hub; /* Direct Rules tables for FDB, NIC TX+RX */ - void *esw_drop_action; /* Pointer to DR E-Switch drop action. */ + void *dr_drop_action; /* Pointer to DR drop action, any domain. */ void *pop_vlan_action; /* Pointer to DR pop VLAN action. */ struct mlx5_hlist *encaps_decaps; /* Encap/decap action hash list. */ struct mlx5_hlist *modify_cmds; diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 23e5849783..eb70bae900 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -12002,11 +12002,19 @@
[dpdk-dev] [PATCH] net/mlx5: fix drop queue function declarations
There are some leftovers of removed code - there are no drop queue handling routines anymore. Fixes: 78be885295b8 ("net/mlx5: handle drop queues as regular queues") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 1c70e28c77..4dfb85de4e 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -1210,8 +1210,6 @@ int mlx5_ctrl_flow(struct rte_eth_dev *dev, struct rte_flow_item_eth *eth_mask); int mlx5_flow_lacp_miss(struct rte_eth_dev *dev); struct rte_flow *mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev); -int mlx5_flow_create_drop_queue(struct rte_eth_dev *dev); -void mlx5_flow_delete_drop_queue(struct rte_eth_dev *dev); void mlx5_flow_async_pool_query_handle(struct mlx5_dev_ctx_shared *sh, uint64_t async_id, int status); void mlx5_set_query_alarm(struct mlx5_dev_ctx_shared *sh); -- 2.28.0
[dpdk-dev] [PATCH] net/mlx4: fix RSS action hash key null pointer
If RSS action contains non zero hash key length and NULL key buffer pointer the default hash key should be used. The check for the NULL pointer this was missing in the mlx4 PMD causing crash, for example, in testpmd with command: flow validate 0 ingress group 0 pattern eth / ipv4 / end actions rss queues 0 end key_len 40 / end Fixes: ac8d22de2394 ("ethdev: flatten RSS configuration in flow API") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx4/mlx4_flow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c index 43a65abcc0..71ea91b3fb 100644 --- a/drivers/net/mlx4/mlx4_flow.c +++ b/drivers/net/mlx4/mlx4_flow.c @@ -791,7 +791,8 @@ mlx4_flow_prepare(struct mlx4_priv *priv, rss = action->conf; /* Default RSS configuration if none is provided. */ if (rss->key_len) { - rss_key = rss->key; + rss_key = rss->key ? + rss->key : mlx4_rss_hash_key_default; rss_key_len = rss->key_len; } else { rss_key = mlx4_rss_hash_key_default; -- 2.28.0
[PATCH v2 1/2] net/mlx5: fix metadata endianness in modify field action
As modify field action immediate source parameter the metadata should follow the CPU endianness (according to SET_META action structure format), and mlx5 PMD wrongly handled the immediate parameter metadata buffer as big-endian, resulting in wrong metadata set action with incorrect endianness. Fixes: 40c8fb1fd3b3 ("net/mlx5: update modify field action") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_dv.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index af90a7fd0a..10ef2af06a 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1867,7 +1867,7 @@ flow_dv_convert_action_modify_field struct field_modify_info dcopy[MLX5_ACT_MAX_MOD_FIELDS] = { {0, 0, 0} }; uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0}; - uint32_t type; + uint32_t type, meta = 0; uint32_t shift = 0; if (conf->src.field == RTE_FLOW_FIELD_POINTER || @@ -1880,6 +1880,11 @@ flow_dv_convert_action_modify_field item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ? (void *)(uintptr_t)conf->src.pvalue : (void *)(uintptr_t)&conf->src.value; + if (conf->dst.field == RTE_FLOW_FIELD_META) { + meta = *(const unaligned_uint32_t *)item.spec; + meta = rte_cpu_to_be_32(meta); + item.spec = &meta; + } } else { type = MLX5_MODIFICATION_TYPE_COPY; /** For COPY fill the destination field (dcopy) without mask. */ -- 2.18.1
[PATCH v2 2/2] net/mlx5: remove unused metadata shift parameter
Due to updated modify field actionimmediate value buffer pattern [1] the implicit shift for the metadata is not needed anymore and should be removed. [1] commit 40c8fb1fd3b3 ("net/mlx5: update modify field action") Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_dv.c | 16 +--- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 10ef2af06a..ef9c66eddf 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1451,7 +1451,7 @@ static void mlx5_flow_field_id_to_modify_info (const struct rte_flow_action_modify_data *data, struct field_modify_info *info, uint32_t *mask, -uint32_t width, uint32_t *shift, struct rte_eth_dev *dev, +uint32_t width, struct rte_eth_dev *dev, const struct rte_flow_attr *attr, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; @@ -1806,16 +1806,11 @@ mlx5_flow_field_id_to_modify_info { uint32_t meta_mask = priv->sh->dv_meta_mask; uint32_t meta_count = __builtin_popcount(meta_mask); - uint32_t msk_c0 = - rte_cpu_to_be_32(priv->sh->dv_regc0_mask); - uint32_t shl_c0 = rte_bsf32(msk_c0); int reg = flow_dv_get_metadata_reg(dev, attr, error); if (reg < 0) return; MLX5_ASSERT(reg != REG_NON); MLX5_ASSERT((unsigned int)reg < RTE_DIM(reg_to_field)); - if (reg == REG_C_0) - *shift = shl_c0; info[idx] = (struct field_modify_info){4, 0, reg_to_field[reg]}; if (mask) @@ -1868,14 +1863,13 @@ flow_dv_convert_action_modify_field {0, 0, 0} }; uint32_t mask[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0}; uint32_t type, meta = 0; - uint32_t shift = 0; if (conf->src.field == RTE_FLOW_FIELD_POINTER || conf->src.field == RTE_FLOW_FIELD_VALUE) { type = MLX5_MODIFICATION_TYPE_SET; /** For SET fill the destination field (field) first. */ mlx5_flow_field_id_to_modify_info(&conf->dst, field, mask, - conf->width, &shift, dev, + conf->width, dev, attr, error); item.spec = conf->src.field == RTE_FLOW_FIELD_POINTER ? (void *)(uintptr_t)conf->src.pvalue : @@ -1889,12 +1883,12 @@ flow_dv_convert_action_modify_field type = MLX5_MODIFICATION_TYPE_COPY; /** For COPY fill the destination field (dcopy) without mask. */ mlx5_flow_field_id_to_modify_info(&conf->dst, dcopy, NULL, - conf->width, &shift, dev, + conf->width, dev, attr, error); /** Then construct the source field (field) with mask. */ mlx5_flow_field_id_to_modify_info(&conf->src, field, mask, - conf->width, &shift, - dev, attr, error); + conf->width, dev, + attr, error); } item.mask = &mask; return flow_dv_convert_modify_action(&item, -- 2.18.1
[PATCH 0/4] net/mlx5: support send scheduling for ConnextX-7
Since the ConnectX-6DX the send scheduling capability is provided. An application can register the dynamic field and dynamic flags in mbuf for timestamp and specify the desired moment of time the packet should sent. The send scheduling feature over ConnectX-6DX uses the complicated infrastructure with reference Clock Queue and inter-queue synchronizing operations. Since ConnectX-7 the new wait descriptor format is introduced where the timestamp can be promoted to hardware directly. The patchset adds support for this new hardware option in PMD. Signed-off-by: Viacheslav Ovsiienko Viacheslav Ovsiienko (4): common/mlx5: add send on time capability check net/mlx5: configure Tx queue with send on time offload net/mlx5: add wait on time support in Tx datapath doc: update send scheduling mlx5 feature description doc/guides/nics/mlx5.rst | 5 ++ doc/guides/rel_notes/release_22_03.rst | 6 +++ drivers/common/mlx5/mlx5_devx_cmds.c | 1 + drivers/common/mlx5/mlx5_devx_cmds.h | 1 + drivers/common/mlx5/mlx5_prm.h | 27 +- drivers/net/mlx5/linux/mlx5_verbs.c| 4 ++ drivers/net/mlx5/mlx5.h| 3 ++ drivers/net/mlx5/mlx5_devx.c | 2 + drivers/net/mlx5/mlx5_tx.h | 75 +++--- drivers/net/mlx5/mlx5_txq.c| 16 +- 10 files changed, 129 insertions(+), 11 deletions(-) -- 2.18.1
[PATCH 1/4] common/mlx5: add send on time capability check
The patch provides check for send scheduling on time hardware capability. With this capability enabled hardware is able to handle Wait WQEs with directly specified timestamp values. No Clock Queue is needed anymore to handle send scheduling. Signed-off-by: Viacheslav Ovsiienko --- drivers/common/mlx5/mlx5_devx_cmds.c | 1 + drivers/common/mlx5/mlx5_devx_cmds.h | 1 + drivers/common/mlx5/mlx5_prm.h | 27 ++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c index 2e807a0829..fb55ef96ea 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.c +++ b/drivers/common/mlx5/mlx5_devx_cmds.c @@ -962,6 +962,7 @@ mlx5_devx_cmd_query_hca_attr(void *ctx, MLX5_GET(cmd_hca_cap, hcattr, umr_indirect_mkey_disabled); attr->umr_modify_entity_size_disabled = MLX5_GET(cmd_hca_cap, hcattr, umr_modify_entity_size_disabled); + attr->wait_on_time = MLX5_GET(cmd_hca_cap, hcattr, wait_on_time); attr->crypto = MLX5_GET(cmd_hca_cap, hcattr, crypto); if (attr->crypto) attr->aes_xts = MLX5_GET(cmd_hca_cap, hcattr, aes_xts); diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h index 37821b493e..909d91adae 100644 --- a/drivers/common/mlx5/mlx5_devx_cmds.h +++ b/drivers/common/mlx5/mlx5_devx_cmds.h @@ -201,6 +201,7 @@ struct mlx5_hca_attr { uint32_t scatter_fcs_w_decap_disable:1; uint32_t flow_hit_aso:1; /* General obj type FLOW_HIT_ASO supported. */ uint32_t roce:1; + uint32_t wait_on_time:1; uint32_t rq_ts_format:2; uint32_t sq_ts_format:2; uint32_t steering_format_version:4; diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h index 495b63191a..4ce302b478 100644 --- a/drivers/common/mlx5/mlx5_prm.h +++ b/drivers/common/mlx5/mlx5_prm.h @@ -133,6 +133,19 @@ #define MLX5_OPCODE_WAIT 0x0fu #endif +#define MLX5_OPC_MOD_WAIT_CQ_PI 0u +#define MLX5_OPC_MOD_WAIT_DATA 1u +#define MLX5_OPC_MOD_WAIT_TIME 2u + + +#define MLX5_WAIT_COND_INVERT 0x10u +#define MLX5_WAIT_COND_ALWAYS_TRUE 0u +#define MLX5_WAIT_COND_EQUAL 1u +#define MLX5_WAIT_COND_BIGGER 2u +#define MLX5_WAIT_COND_SMALLER 3u +#define MLX5_WAIT_COND_CYCLIC_BIGGER 4u +#define MLX5_WAIT_COND_CYCLIC_SMALLER 5u + #ifndef HAVE_MLX5_OPCODE_ACCESS_ASO #define MLX5_OPCODE_ACCESS_ASO 0x2du #endif @@ -348,6 +361,15 @@ struct mlx5_wqe_qseg { uint32_t qpn_cqn; } __rte_packed; +struct mlx5_wqe_wseg { + uint32_t operation; + uint32_t lkey; + uint32_t va_high; + uint32_t va_low; + uint64_t value; + uint64_t mask; +} __rte_packed; + /* The title WQEBB, header of WQE. */ struct mlx5_wqe { union { @@ -1659,7 +1681,10 @@ struct mlx5_ifc_cmd_hca_cap_bits { u8 num_vhca_ports[0x8]; u8 reserved_at_618[0x6]; u8 sw_owner_id[0x1]; - u8 reserved_at_61f[0x129]; + u8 reserved_at_61f[0x6C]; + u8 wait_on_data[0x1]; + u8 wait_on_time[0x1]; + u8 reserved_at_68d[0xBB]; u8 dma_mmo_qp[0x1]; u8 regexp_mmo_qp[0x1]; u8 compress_mmo_qp[0x1]; -- 2.18.1
[PATCH 2/4] net/mlx5: configure Tx queue with send on time offload
The wait on time configuration flag is copied to the Tx queue structure due to performance considerations. Timestamp mask is preparted and stored in queue structure as well. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/linux/mlx5_verbs.c | 2 ++ drivers/net/mlx5/mlx5.h | 3 +++ drivers/net/mlx5/mlx5_devx.c| 2 ++ drivers/net/mlx5/mlx5_tx.h | 3 +++ drivers/net/mlx5/mlx5_txq.c | 11 ++- 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/net/mlx5/linux/mlx5_verbs.c b/drivers/net/mlx5/linux/mlx5_verbs.c index 2b6eef44a7..80dd0bb6c1 100644 --- a/drivers/net/mlx5/linux/mlx5_verbs.c +++ b/drivers/net/mlx5/linux/mlx5_verbs.c @@ -1036,6 +1036,8 @@ mlx5_txq_ibv_obj_new(struct rte_eth_dev *dev, uint16_t idx) txq_data->wqe_pi = 0; txq_data->wqe_comp = 0; txq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV; + txq_data->wait_on_time = !!(!priv->config.tx_pp && +priv->config.hca_attr.wait_on_time); #ifdef HAVE_IBV_FLOW_DV_SUPPORT /* * If using DevX need to query and store TIS transport domain value. diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 737ad6895c..3983d3aa50 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -341,6 +341,9 @@ struct mlx5_lb_ctx { #define MLX5_CNT_ARRAY_IDX(pool, cnt) \ ((int)(((uint8_t *)(cnt) - (uint8_t *)((pool) + 1)) / \ MLX5_CNT_LEN(pool))) +#define MLX5_TS_MASK_SECS 8ull +/* timestamp wrapping in seconds, must be power of 2. */ + /* * The pool index and offset of counter in the pool array makes up the * counter index. In case the counter is from pool 0 and offset 0, it diff --git a/drivers/net/mlx5/mlx5_devx.c b/drivers/net/mlx5/mlx5_devx.c index 91243f684f..c6994e4a75 100644 --- a/drivers/net/mlx5/mlx5_devx.c +++ b/drivers/net/mlx5/mlx5_devx.c @@ -1327,6 +1327,8 @@ mlx5_txq_devx_obj_new(struct rte_eth_dev *dev, uint16_t idx) txq_data->qp_num_8s = txq_obj->sq_obj.sq->id << 8; txq_data->db_heu = sh->cdev->config.dbnc == MLX5_TXDB_HEURISTIC; txq_data->db_nc = sh->tx_uar.dbnc; + txq_data->wait_on_time = !!(!priv->config.tx_pp && +priv->config.hca_attr.wait_on_time); /* Change Send Queue state to Ready-to-Send. */ ret = mlx5_txq_devx_modify(txq_obj, MLX5_TXQ_MOD_RST2RDY, 0); if (ret) { diff --git a/drivers/net/mlx5/mlx5_tx.h b/drivers/net/mlx5/mlx5_tx.h index c4b8271f6f..b50deb8b67 100644 --- a/drivers/net/mlx5/mlx5_tx.h +++ b/drivers/net/mlx5/mlx5_tx.h @@ -138,6 +138,8 @@ struct mlx5_txq_data { uint16_t vlan_en:1; /* VLAN insertion in WQE is supported. */ uint16_t db_nc:1; /* Doorbell mapped to non-cached region. */ uint16_t db_heu:1; /* Doorbell heuristic write barrier. */ + uint16_t rt_timestamp:1; /* Realtime timestamp format. */ + uint16_t wait_on_time:1; /* WQE with timestamp is supported. */ uint16_t fast_free:1; /* mbuf fast free on Tx is enabled. */ uint16_t inlen_send; /* Ordinary send data inline size. */ uint16_t inlen_empw; /* eMPW max packet size to inline. */ @@ -157,6 +159,7 @@ struct mlx5_txq_data { volatile uint32_t *cq_db; /* Completion queue doorbell. */ uint16_t port_id; /* Port ID of device. */ uint16_t idx; /* Queue index. */ + uint64_t rt_timemask; /* Scheduling timestamp mask. */ uint64_t ts_mask; /* Timestamp flag dynamic mask. */ int32_t ts_offset; /* Timestamp field dynamic offset. */ struct mlx5_dev_ctx_shared *sh; /* Shared context. */ diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c index 4e0bf7af9c..3585546628 100644 --- a/drivers/net/mlx5/mlx5_txq.c +++ b/drivers/net/mlx5/mlx5_txq.c @@ -108,7 +108,7 @@ mlx5_get_tx_port_offloads(struct rte_eth_dev *dev) RTE_ETH_TX_OFFLOAD_TCP_CKSUM); if (config->tso) offloads |= RTE_ETH_TX_OFFLOAD_TCP_TSO; - if (config->tx_pp) + if (config->tx_pp || config->hca_attr.wait_on_time) offloads |= RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP; if (config->swp) { if (config->swp & MLX5_SW_PARSING_CSUM_CAP) @@ -1290,7 +1290,14 @@ mlx5_txq_dynf_timestamp_set(struct rte_eth_dev *dev) int off, nbit; unsigned int i; uint64_t mask = 0; + uint64_t ts_mask; + if (priv->config.rt_timestamp || !priv->config.hca_attr.dev_freq_khz) + ts_mask = MLX5_TS_MASK_SECS << 32; + else + ts_mask = rte_align64pow2(MLX5_TS_MASK_SECS * 1000ull * + priv->config.hca_attr.dev_freq_khz); + ts_mask = rte_cpu_to_be_64(ts_mask - 1ull); nbit = rte_mbuf_dynflag_lookup
[PATCH 3/4] net/mlx5: add wait on time support in Tx datapath
The hardware since ConnectX-7 supports waiting on specified moment of time with new introduced wait descriptor. A timestamp can be directrly placed into descriptor and pushed to sending queue. Once hardware encounter the wait descriptor the queue operation is suspended till specified moment of time. This patch update the Tx datapath to handle this new hardware wait capability. Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/linux/mlx5_verbs.c | 4 +- drivers/net/mlx5/mlx5_tx.h | 72 + drivers/net/mlx5/mlx5_txq.c | 7 ++- 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/drivers/net/mlx5/linux/mlx5_verbs.c b/drivers/net/mlx5/linux/mlx5_verbs.c index 80dd0bb6c1..5f821c4645 100644 --- a/drivers/net/mlx5/linux/mlx5_verbs.c +++ b/drivers/net/mlx5/linux/mlx5_verbs.c @@ -1037,7 +1037,9 @@ mlx5_txq_ibv_obj_new(struct rte_eth_dev *dev, uint16_t idx) txq_data->wqe_comp = 0; txq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV; txq_data->wait_on_time = !!(!priv->config.tx_pp && -priv->config.hca_attr.wait_on_time); +priv->config.hca_attr.wait_on_time && +txq_data->offloads & +DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP); #ifdef HAVE_IBV_FLOW_DV_SUPPORT /* * If using DevX need to query and store TIS transport domain value. diff --git a/drivers/net/mlx5/mlx5_tx.h b/drivers/net/mlx5/mlx5_tx.h index b50deb8b67..0adc3f4839 100644 --- a/drivers/net/mlx5/mlx5_tx.h +++ b/drivers/net/mlx5/mlx5_tx.h @@ -780,7 +780,7 @@ mlx5_tx_cseg_init(struct mlx5_txq_data *__rte_restrict txq, * compile time and may be used for optimization. */ static __rte_always_inline void -mlx5_tx_wseg_init(struct mlx5_txq_data *restrict txq, +mlx5_tx_qseg_init(struct mlx5_txq_data *restrict txq, struct mlx5_txq_local *restrict loc __rte_unused, struct mlx5_wqe *restrict wqe, unsigned int wci, @@ -795,6 +795,43 @@ mlx5_tx_wseg_init(struct mlx5_txq_data *restrict txq, qs->reserved1 = RTE_BE32(0); } +/** + * Build the Wait on Time Segment with specified timestamp value. + * + * @param txq + * Pointer to TX queue structure. + * @param loc + * Pointer to burst routine local context. + * @param wqe + * Pointer to WQE to fill with built Control Segment. + * @param ts + * Timesatmp value to wait. + * @param olx + * Configured Tx offloads mask. It is fully defined at + * compile time and may be used for optimization. + */ +static __rte_always_inline void +mlx5_tx_wseg_init(struct mlx5_txq_data *restrict txq, + struct mlx5_txq_local *restrict loc __rte_unused, + struct mlx5_wqe *restrict wqe, + uint64_t ts, + unsigned int olx __rte_unused) +{ + struct mlx5_wqe_wseg *ws; + + ws = RTE_PTR_ADD(wqe, MLX5_WSEG_SIZE); + ws->operation = rte_cpu_to_be_32(MLX5_WAIT_COND_CYCLIC_BIGGER); + ws->lkey = RTE_BE32(0); + ws->va_high = RTE_BE32(0); + ws->va_low = RTE_BE32(0); + if (txq->rt_timestamp) { + ts = ts % (uint64_t)NS_PER_S + | (ts / (uint64_t)NS_PER_S) << 32; + } + ws->value = rte_cpu_to_be_64(ts); + ws->mask = txq->rt_timemask; +} + /** * Build the Ethernet Segment without inlined data. * Supports Software Parser, Checksums and VLAN insertion Tx offload features. @@ -1626,9 +1663,9 @@ mlx5_tx_schedule_send(struct mlx5_txq_data *restrict txq, { if (MLX5_TXOFF_CONFIG(TXPP) && loc->mbuf->ol_flags & txq->ts_mask) { + struct mlx5_dev_ctx_shared *sh; struct mlx5_wqe *wqe; uint64_t ts; - int32_t wci; /* * Estimate the required space quickly and roughly. @@ -1640,13 +1677,32 @@ mlx5_tx_schedule_send(struct mlx5_txq_data *restrict txq, return MLX5_TXCMP_CODE_EXIT; /* Convert the timestamp into completion to wait. */ ts = *RTE_MBUF_DYNFIELD(loc->mbuf, txq->ts_offset, uint64_t *); - wci = mlx5_txpp_convert_tx_ts(txq->sh, ts); - if (unlikely(wci < 0)) - return MLX5_TXCMP_CODE_SINGLE; - /* Build the WAIT WQE with specified completion. */ wqe = txq->wqes + (txq->wqe_ci & txq->wqe_m); - mlx5_tx_cseg_init(txq, loc, wqe, 2, MLX5_OPCODE_WAIT, olx); - mlx5_tx_wseg_init(txq, loc, wqe, wci, olx); + sh = txq->sh; + if (txq->wait_on_time) { + /* The wait on time capability should be used. */ + ts -= sh->txpp.skew
[PATCH 4/4] doc: update send scheduling mlx5 feature description
Updated: - send scheduling feature description for mlx5 - release notes Signed-off-by: Viacheslav Ovsiienko --- doc/guides/nics/mlx5.rst | 5 + doc/guides/rel_notes/release_22_03.rst | 6 ++ 2 files changed, 11 insertions(+) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index c3cc0c0f41..6494f4ae39 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -934,6 +934,11 @@ Driver options By default (if the ``tx_pp`` is not specified) send scheduling on timestamps feature is disabled. + Starting since ConnectX-7 the capability to schedule traffic directly + on timestamp specified in descriptor is provided, no extra objects are + needed anymore and scheduling capability is advertised and handled + regardless tx_pp parameter presence. + - ``tx_skew`` parameter [int] The parameter adjusts the send packet scheduling on timestamps and represents diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst index ff3095d742..268f2827e2 100644 --- a/doc/guides/rel_notes/release_22_03.rst +++ b/doc/guides/rel_notes/release_22_03.rst @@ -109,6 +109,12 @@ New Features * Added rte_flow support for matching GENEVE packets. * Added rte_flow support for matching eCPRI packets. +* **Updated Mellanox mlx5 driver.** + + Updated the Mellanox mlx5 driver with new features and improvements, including: + + * Support ConnectX-7 capability to schedule traffic sending on timestamp + * **Updated Wangxun ngbe driver.** * Added support for devices of custom PHY interfaces. -- 2.18.1
[dpdk-dev] [PATCH v3 2/5] ethdev: support flow elements with variable length
From: Gregory Etelson RTE flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. A new RTE flow item type with variable length pattern that does not fit the RAW item meta description could not use the RAW item. For example, the new flow item that references 64 bits PMD handler cannot be described by the RAW item. The patch allows RTE conv helper functions to process custom flow items with variable length pattern. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c | 83 --- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..100983ca59 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,67 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* allow PMD private flow item +* see 5d1bff8fe2 +* "ethdev: allow negative values in flow rule types" +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + +static size_t +rte_flow_item_flex_conv(void *buf, const void *data) +{ + struct rte_flow_item_flex *dst = buf; + const struct rte_flow_item_flex *src = data; + if (buf) { + dst->pattern = rte_memcpy + ((void *)((uintptr_t)(dst + 1)), src->pattern, +src->length); + } + return src->length; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -100,6 +154,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM_FN(FLEX, sizeof(struct rte_flow_item_flex), + rte_flow_item_flex_conv), }; /** Generate flow_action[] entry. */ @@ -107,8 +163,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -527,12 +592,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -634,12 +695,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); -
[dpdk-dev] [PATCH v3 3/5] ethdev: implement RTE flex item API
From: Gregory Etelson RTE flex item API was introduced in "ethdev: introduce configurable flexible item" patch. The API allows DPDK application to define parser for custom network header in port hardware and offload flows that will match the custom header elements. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c| 40 lib/ethdev/rte_flow_driver.h | 8 lib/ethdev/version.map | 4 3 files changed, 52 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 100983ca59..a858dc31e3 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1323,3 +1323,43 @@ rte_flow_tunnel_item_release(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_item_flex_handle * +rte_flow_flex_item_create(uint16_t port_id, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_item_flex_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->flex_item_create)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; + } + handle = ops->flex_item_create(dev, conf, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_flex_item_release(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_release)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_release(dev, handle, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 46f62c2ec2..34a5a5bcd0 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -139,6 +139,14 @@ struct rte_flow_ops { struct rte_flow_item *pmd_items, uint32_t num_of_items, struct rte_flow_error *err); + struct rte_flow_item_flex_handle *(*flex_item_create) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_conf *conf, +struct rte_flow_error *error); + int (*flex_item_release) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_handle *handle, +struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 904bce6ea1..ec3b66d7a1 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -247,6 +247,10 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_flow_flex_item_create; + rte_flow_flex_item_release; }; INTERNAL { -- 2.18.1
[dpdk-dev] [PATCH v3 1/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item confgiuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.h | 222 + 3 files changed, 254 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..3f40b8891c 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,31 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``FLEX`` +^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configuration, the pattern spec and mask are + considered by the driver as padded with trailing zeroes till the full + configured item
[dpdk-dev] [PATCH v3 0/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item confgiuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; 7. Notes: - v2: http://patches.dpdk.org/project/dpdk/patch/20211001193415.23288-2-viachesl...@nvidia.com/ - v1: http://patches.dpdk.org/project/dpdk/patch/20210922180418.20663-2-viachesl...@nvidia.com/ - RFC: http://patches.dpdk.org/project/dpdk/patch/20210806085624.16497-1-viachesl...@nvidia.com/ - v2 -> v3: - comments addressed - flex item update removed as not supported - RSS over flex item fields removed as not supported and non-complete API - tunnel mode configuration refactored - testpmd updated - documentation updated - PMD patches are removed temporarily (updating WIP, be presented in rc2) - v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (4): ethdev: support flow elements with variable length ethdev: implement RTE flex item API app/testpmd: add jansson library app/testpmd: add flex item CLI commands Viacheslav Ovsiienko (1): ethdev: introduce configurable flexible item app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 763 +++- app/test-pmd/meson.build| 5 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 19 + doc/guides/prog_guide/rte_flow.rst | 25 + doc/guides
[dpdk-dev] [PATCH v3 4/5] app/testpmd: add jansson library
From: Gregory Etelson Testpmd interactive mode provides CLI to configure application commands. Testpmd reads CLI command and parameters from STDIN, and converts input into C objects with internal parser. The patch adds jansson dependency to testpmd. With jansson, testpmd can read input in JSON format from STDIN or input file and convert it into C object using jansson library calls. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/meson.build | 5 + app/test-pmd/testpmd.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 98f3289bdf..3a8babd604 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -61,3 +61,8 @@ if dpdk_conf.has('RTE_LIB_BPF') sources += files('bpf_cmd.c') deps += 'bpf' endif +jansson_dep = dependency('jansson', required: false, method: 'pkg-config') +if jansson_dep.found() +dpdk_conf.set('RTE_HAS_JANSSON', 1) +ext_deps += jansson_dep +endif diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 5863b2f43f..876a341cf0 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -14,6 +14,9 @@ #include #include #include +#ifdef RTE_HAS_JANSSON +#include +#endif #define RTE_PORT_ALL(~(portid_t)0x0) -- 2.18.1
[dpdk-dev] [PATCH v3 5/5] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 763 +++- app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 16 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 +++ 5 files changed, 900 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index a9efd027c3..a673e6ef08 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -17822,6 +17822,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_show_fec_mode, (cmdline_parse_inst_t *)&cmd_set_fec_mode, (cmdline_parse_inst_t *)&cmd_show_capability, + (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern, + (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern, NULL, }; diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..7c817f716c 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -54,6 +54,8 @@ enum index { COMMON_PRIORITY_LEVEL, COMMON_INDIRECT_ACTION_ID, COMMON_POLICY_ID, + COMMON_FLEX_HANDLE, + COMMON_FLEX_TOKEN, /* TOP-level command. */ ADD, @@ -81,6 +83,12 @@ enum index { AGED, ISOLATE, TUNNEL, + FLEX, + + /* Flex arguments */ + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, /* Tunnel arguments. */ TUNNEL_CREATE, @@ -306,6 +314,9 @@ enum index { ITEM_POL_PORT, ITEM_POL_METER, ITEM_POL_POLICY, + ITEM_FLEX, + ITEM_FLEX_ITEM_HANDLE, + ITEM_FLEX_PATTERN_HANDLE, /* Validate/create actions. */ ACTIONS, @@ -844,6 +855,11 @@ struct buffer { struct { uint32_t policy_id; } policy;/**< Policy arguments. */ + struct { + uint16_t token; + uintptr_t uintptr; + char filename[128]; + } flex; /**< Flex arguments*/ } args; /**< Command arguments. */ }; @@ -871,6 +887,13 @@ struct parse_action_priv { .size = s, \ }) +static const enum index next_flex_item[] = { + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -1000,6 +1023,7 @@ static const enum index next_item[] = { ITEM_GENEVE_OPT, ITEM_INTEGRITY, ITEM_CONNTRACK, + ITEM_FLEX, END_SET, ZERO, }; @@ -1368,6 +1392,13 @@ static const enum index item_integrity_lv[] = { ZERO, }; +static const enum index item_flex[] = { + ITEM_FLEX_PATTERN_HANDLE, + ITEM_FLEX_ITEM_HANDLE, + ITEM_NEXT, + ZERO, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -1724,6 +1755,9 @@ static int parse_set_sample_action(struct context *, const struct token *, static int parse_set_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int +parse_flex_handle(struct context *, const struct token *, + const char *, unsigned int, void *, unsigned in
[dpdk-dev] [PATCH v3 0/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union - the byte ordering for 64-bit integer was not specified. Many fields have lesser lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented - 64-bit integer size is not enough to provide MAC and IPv6 addresses In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate commit message has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") [2] RFC: http://patches.dpdk.org/project/dpdk/patch/20210910141609.8410-1-viachesl...@nvidia.com/ [3] Deprecation notice: http://patches.dpdk.org/project/dpdk/patch/20210803085754.643180-1-or...@nvidia.com/ [4] v1 - http://patches.dpdk.org/project/dpdk/cover/20211001195223.31909-1-viachesl...@nvidia.com/ [5] v2 - http://patches.dpdk.org/project/dpdk/patch/20211010234547.1495-2-viachesl...@nvidia.com/ v2: - comments addressed - documentation updated - typos fixed - mlx5 PMD updated v3: - comments addressed - documentation updated - typos fixed Signed-off-by: Viacheslav Ovsiienko Viacheslav Ovsiienko (5): ethdev: update modify field flow action ethdev: fix missed experimental tag for modify field action app/testpmd: update modify field flow action support app/testpmd: fix hex string parser in flow commands net/mlx5: update modify field action app/test-pmd/cmdline_flow.c| 60 ++ doc/guides/prog_guide/rte_flow.rst | 24 ++- doc/guides/rel_notes/deprecation.rst | 4 -- doc/guides/rel_notes/release_21_11.rst | 7 +++ drivers/net/mlx5/mlx5_flow_dv.c| 50 - lib/ethdev/rte_flow.h | 19 ++-- 6 files changed, 116 insertions(+), 48 deletions(-) -- 2.18.1
[dpdk-dev] [PATCH v3 1/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union. - the byte ordering for 64-bit integer was not specified. Many fields have shorter lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented. - 64-bit integer size is not enough to provide IPv6 addresses. In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate deprecation notice has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Fixes: 2ba49b5f3721 ("doc: announce change to ethdev modify action data") Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 24 +++- doc/guides/rel_notes/deprecation.rst | 4 doc/guides/rel_notes/release_21_11.rst | 7 +++ lib/ethdev/rte_flow.h | 16 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..b08087511f 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -2835,6 +2835,22 @@ a packet to any other part of it. ``value`` sets an immediate value to be used as a source or points to a location of the value in memory. It is used instead of ``level`` and ``offset`` for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +The data in memory should be presented exactly in the same byte order and +length as in the relevant flow item, i.e. data for field with type +``RTE_FLOW_FIELD_MAC_DST`` should follow the conventions of ``dst`` field +in ``rte_flow_item_eth`` structure, with type ``RTE_FLOW_FIELD_IPV6_SRC`` - +``rte_flow_item_ipv6`` conventions, and so on. If the field size is larger than +16 bytes the pattern can be provided as pointer only. + +The bitfield extracted from the memory being applied as second operation +parameter is defined by action width and by the destination field offset. +Application should provide the data in immediate value memory (either as +buffer or by pointer) exactly as item field without any applied explicit offset, +and destination packet field (with specified width and bit offset) will be +replaced by immediate source bits from the same bit offset. For example, +to replace the third byte of MAC address with value 0x85, application should +specify destination width as 8, destination offset as 16, and provide immediate +value as sequence of bytes {xxx, xxx, 0x85, xxx, xxx, xxx}. .. _table_rte_flow_action_modify_field: @@ -2865,7 +2881,13 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +---+--+ | ``offset``| number of bits to skip at the beginning | +---+--+ - | ``value`` | immediate value or a pointer to this value | + | ``value`` | immediate value buffer (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_VALUE | + | | field type | + +---+--+ + | ``pvalue``| pointer to immediate value data (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_POINTER| + | | field type | +---+--+ Action: ``CONNTRACK`` diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index a2fe766d4b..dee14077a5 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -120,10 +120,6 @@ Deprecation Notices * ethdev: Announce moving from dedicated modify function for each field, to using the general ``rte_flow_modify_field`` action. -* ethdev: The struct ``rte_flow_action_modify_data`` will be modified - to support modifying fields larger than 64 bits. - In addition, documentation will be updated to clarify byte order. - * ethdev: Attribute ``shared`` of the ``struct rte_flow_action_count`` is deprecated and will be removed in DPDK 21.11. Shared counters should be managed using shared actions API (``rte_flow_shared_action_create`` etc). dif
[dpdk-dev] [PATCH v3 2/5] ethdev: fix missed experimental tag for modify field action
EXPERIMENTAL tag was missed in rte_flow_action_modify_data structure description. Fixes: 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index f14f2b..8a1eddd0b7 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -3204,6 +3204,9 @@ enum rte_flow_field_id { }; /** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * * Field description for MODIFY_FIELD action. */ struct rte_flow_action_modify_data { -- 2.18.1
[dpdk-dev] [PATCH v3 4/5] app/testpmd: fix hex string parser in flow commands
The hexadecimal string parser does not check the target field buffer size, buffer overflow happens and might cause the application failure (segmentation fault is observed usually). Fixes: 169a9fed1f4c ("app/testpmd: fix hex string parser support for flow API") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 736029c4fd..6827d9228f 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -7291,10 +7291,13 @@ parse_hex(struct context *ctx, const struct token *token, hexlen -= 2; } if (hexlen > length) - return -1; + goto error; ret = parse_hex_string(str, hex_tmp, &hexlen); if (ret < 0) goto error; + /* Check the converted binary fits into data buffer. */ + if (hexlen > size) + goto error; /* Let parse_int() fill length information first. */ ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); if (ret < 0) -- 2.18.1
[dpdk-dev] [PATCH v3 3/5] app/testpmd: update modify field flow action support
The testpmd flow create command updates provided: - modify field action supports the updated actions - pointer type added for action source field - pointer and value source field takes hex string instead of unsigned int in host endianness There are some examples of flow with update modified field action: 1. IPv6 destination address bytes 4-7 assignment: :: - > ::4455:6677:: flow create 0 egress group 1 pattern eth / ipv6 dst is :: / udp / end actions modify_field op set dst_type ipv6_dst dst_offset 32 src_type value src_value 0011223344556677 width 32 / end 2. Copy second byte of IPv4 destination address to the third byte of source address: 10.0.118.4 -> 192.168.100.1 10.0.168.4 -> 192.168.100.1 flow create 0 egress group 1 pattern eth / ipv4 / udp / end actions modify_field op set dst_type ipv4_src dst_offset 16 src_type ipv4_dst src_offset 8 width 8 / end 3. Assign METADATA value with 11223344 value from the hex string in the linear buffer. Please note, the value definition should follow host-endian, example is given for x86 (little-endian): flow create 0 egress group 1 pattern eth / ipv4 / end actions modify_field op set dst_type meta src_type pointer src_ptr 44332211 width 32 / end 4. Assign destination MAC with EA:11:0B:AD:0B:ED value: flow create 0 egress group 1 pattern eth / end actions modify_field op set dst_type mac_dst src_type value src_value EA110BAD0BED width 48 / end Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 55 + 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..736029c4fd 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -448,6 +448,7 @@ enum index { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ACTION_CONNTRACK, ACTION_CONNTRACK_UPDATE, @@ -468,6 +469,14 @@ enum index { #define ITEM_RAW_SIZE \ (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) +/** Maximum size for external pattern in struct rte_flow_action_modify_data. */ +#define ACTION_MODIFY_PATTERN_SIZE 32 + +/** Storage size for struct rte_flow_action_modify_field including pattern. */ +#define ACTION_MODIFY_SIZE \ + (sizeof(struct rte_flow_action_modify_field) + \ + ACTION_MODIFY_PATTERN_SIZE) + /** Maximum number of queue indices in struct rte_flow_action_rss. */ #define ACTION_RSS_QUEUE_NUM 128 @@ -1704,6 +1713,7 @@ static const enum index action_modify_field_src[] = { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ZERO, }; @@ -4455,8 +4465,7 @@ static const struct token token_list[] = { [ACTION_MODIFY_FIELD] = { .name = "modify_field", .help = "modify destination field with data from source field", - .priv = PRIV_ACTION(MODIFY_FIELD, - sizeof(struct rte_flow_action_modify_field)), + .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), .call = parse_vc, }, @@ -4539,11 +4548,26 @@ static const struct token token_list[] = { .name = "src_value", .help = "source immediate value", .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), - NEXT_ENTRY(COMMON_UNSIGNED)), - .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY(struct rte_flow_action_modify_field, src.value)), .call = parse_vc_conf, }, + [ACTION_MODIFY_FIELD_SRC_POINTER] = { + .name = "src_ptr", + .help = "pointer to source immediate value", + .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, + src.pvalue), +
[dpdk-dev] [PATCH v3 5/5] net/mlx5: update modify field action
Update immediate value/pointer source operand support for modify field RTE Flow action: - source operand data can be presented by byte buffer (instead of former uint64_t) or by pointer - no host byte ordering is assumed anymore for immediate data buffer (not uint64_t anymore) - no immediate value offset is expected Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- drivers/net/mlx5/mlx5_flow_dv.c | 50 +++-- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index c6370cd1d6..867f587960 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1391,7 +1391,7 @@ flow_dv_convert_action_modify_ipv6_dscp static int mlx5_flow_item_field_width(struct mlx5_priv *priv, - enum rte_flow_field_id field) + enum rte_flow_field_id field, int inherit) { switch (field) { case RTE_FLOW_FIELD_START: @@ -1442,7 +1442,8 @@ mlx5_flow_item_field_width(struct mlx5_priv *priv, return __builtin_popcount(priv->sh->dv_meta_mask); case RTE_FLOW_FIELD_POINTER: case RTE_FLOW_FIELD_VALUE: - return 64; + MLX5_ASSERT(inherit >= 0); + return inherit < 0 ? 0 : inherit; default: MLX5_ASSERT(false); } @@ -1462,7 +1463,8 @@ mlx5_flow_field_id_to_modify_info struct mlx5_priv *priv = dev->data->dev_private; uint32_t idx = 0; uint32_t off = 0; - uint64_t val = 0; + uint8_t *pval; + switch (data->field) { case RTE_FLOW_FIELD_START: /* not supported yet */ @@ -1838,32 +1840,37 @@ mlx5_flow_field_id_to_modify_info break; case RTE_FLOW_FIELD_POINTER: case RTE_FLOW_FIELD_VALUE: - if (data->field == RTE_FLOW_FIELD_POINTER) - memcpy(&val, (void *)(uintptr_t)data->value, - sizeof(uint64_t)); - else - val = data->value; + pval = data->field == RTE_FLOW_FIELD_POINTER ? + (uint8_t *)(uintptr_t)data->pvalue : + (uint8_t *)(uintptr_t)&data->value; for (idx = 0; idx < MLX5_ACT_MAX_MOD_FIELDS; idx++) { + if (!dst_width) + break; if (mask[idx]) { if (dst_width == 48) { /*special case for MAC addresses */ - value[idx] = rte_cpu_to_be_16(val); - val >>= 16; + value[idx] = rte_cpu_to_be_16 + (*(unaligned_uint16_t *)pval); + pval += sizeof(uint16_t); dst_width -= 16; } else if (dst_width > 16) { - value[idx] = rte_cpu_to_be_32(val); - val >>= 32; + value[idx] = rte_cpu_to_be_32 + (*(unaligned_uint32_t *)pval); + pval += sizeof(uint32_t); + dst_width -= RTE_MIN(32u, dst_width); } else if (dst_width > 8) { - value[idx] = rte_cpu_to_be_16(val); - val >>= 16; + value[idx] = rte_cpu_to_be_16 + (*(unaligned_uint16_t *)pval); + pval += sizeof(uint16_t); + dst_width -= RTE_MIN(16u, dst_width); } else { - value[idx] = (uint8_t)val; - val >>= 8; + value[idx] = *pval++; + dst_width -= RTE_MIN(8u, dst_width); } if (*shift) value[idx] <<= *shift; - if (!val) - break; + } else { + pval += sizeof(uint32_t); } } break; @@ -1910,8 +1917,9 @@ flow_dv_convert_action_modify_field uint32_t value[MLX5_ACT_MAX_MOD_FIELDS] = {0, 0, 0, 0, 0}; uint32_t type; uint32_t shift = 0; - uint32_t dst_width = mlx5_flow_it
[dpdk-dev] [PATCH v4 3/5] app/testpmd: update modify field flow action support
The testpmd flow create command updates provided: - modify field action supports the updated actions - pointer type added for action source field - pointer and value source field takes hex string instead of unsigned int in host endianness There are some examples of flow with update modified field action: 1. IPv6 destination address bytes 4-7 assignment: :: - > ::4455:6677:: flow create 0 egress group 1 pattern eth / ipv6 dst is :: / udp / end actions modify_field op set dst_type ipv6_dst dst_offset 32 src_type value src_value 0011223344556677 width 32 / end 2. Copy second byte of IPv4 destination address to the third byte of source address: 10.0.118.4 -> 192.168.100.1 10.0.168.4 -> 192.168.100.1 flow create 0 egress group 1 pattern eth / ipv4 / udp / end actions modify_field op set dst_type ipv4_src dst_offset 16 src_type ipv4_dst src_offset 8 width 8 / end 3. Assign METADATA value with 11223344 value from the hex string in the linear buffer. Please note, the value definition should follow host-endian, example is given for x86 (little-endian): flow create 0 egress group 1 pattern eth / ipv4 / end actions modify_field op set dst_type meta src_type pointer src_ptr 44332211 width 32 / end 4. Assign destination MAC with EA:11:0B:AD:0B:ED value: flow create 0 egress group 1 pattern eth / end actions modify_field op set dst_type mac_dst src_type value src_value EA110BAD0BED width 48 / end Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 55 + 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..736029c4fd 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -448,6 +448,7 @@ enum index { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ACTION_CONNTRACK, ACTION_CONNTRACK_UPDATE, @@ -468,6 +469,14 @@ enum index { #define ITEM_RAW_SIZE \ (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) +/** Maximum size for external pattern in struct rte_flow_action_modify_data. */ +#define ACTION_MODIFY_PATTERN_SIZE 32 + +/** Storage size for struct rte_flow_action_modify_field including pattern. */ +#define ACTION_MODIFY_SIZE \ + (sizeof(struct rte_flow_action_modify_field) + \ + ACTION_MODIFY_PATTERN_SIZE) + /** Maximum number of queue indices in struct rte_flow_action_rss. */ #define ACTION_RSS_QUEUE_NUM 128 @@ -1704,6 +1713,7 @@ static const enum index action_modify_field_src[] = { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ZERO, }; @@ -4455,8 +4465,7 @@ static const struct token token_list[] = { [ACTION_MODIFY_FIELD] = { .name = "modify_field", .help = "modify destination field with data from source field", - .priv = PRIV_ACTION(MODIFY_FIELD, - sizeof(struct rte_flow_action_modify_field)), + .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), .call = parse_vc, }, @@ -4539,11 +4548,26 @@ static const struct token token_list[] = { .name = "src_value", .help = "source immediate value", .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), - NEXT_ENTRY(COMMON_UNSIGNED)), - .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY(struct rte_flow_action_modify_field, src.value)), .call = parse_vc_conf, }, + [ACTION_MODIFY_FIELD_SRC_POINTER] = { + .name = "src_ptr", + .help = "pointer to source immediate value", + .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, + src.pvalue), +
[dpdk-dev] [PATCH v4 5/5] net/mlx5: update modify field action
Update immediate value/pointer source operand support for modify field RTE Flow action: - source operand data can be presented by byte buffer (instead of former uint64_t) or by pointer - no host byte ordering is assumed anymore for immediate data buffer (not uint64_t anymore) - no immediate value offset is expected Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_dv.c | 123 +++- 1 file changed, 42 insertions(+), 81 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index c6370cd1d6..d13e0d14e9 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1391,7 +1391,7 @@ flow_dv_convert_action_modify_ipv6_dscp static int mlx5_flow_item_field_width(struct mlx5_priv *priv, - enum rte_flow_field_id field) + enum rte_flow_field_id field, int inherit) { switch (field) { case RTE_FLOW_FIELD_START: @@ -1442,7 +1442,8 @@ mlx5_flow_item_field_width(struct mlx5_priv *priv, return __builtin_popcount(priv->sh->dv_meta_mask); case RTE_FLOW_FIELD_POINTER: case RTE_FLOW_FIELD_VALUE: - return 64; + MLX5_ASSERT(inherit >= 0); + return inherit < 0 ? 0 : inherit; default: MLX5_ASSERT(false); } @@ -1452,17 +1453,14 @@ mlx5_flow_item_field_width(struct mlx5_priv *priv, static void mlx5_flow_field_id_to_modify_info (const struct rte_flow_action_modify_data *data, -struct field_modify_info *info, -uint32_t *mask, uint32_t *value, -uint32_t width, uint32_t dst_width, -uint32_t *shift, struct rte_eth_dev *dev, -const struct rte_flow_attr *attr, -struct rte_flow_error *error) +struct field_modify_info *info, uint32_t *mask, +uint32_t width, uint32_t *shift, struct rte_eth_dev *dev, +const struct rte_flow_attr *attr, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; uint32_t idx = 0; uint32_t off = 0; - uint64_t val = 0; + switch (data->field) { case RTE_FLOW_FIELD_START: /* not supported yet */ @@ -1472,7 +1470,7 @@ mlx5_flow_field_id_to_modify_info off = data->offset > 16 ? data->offset - 16 : 0; if (mask) { if (data->offset < 16) { - info[idx] = (struct field_modify_info){2, 0, + info[idx] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_DMAC_15_0}; if (width < 16) { mask[idx] = rte_cpu_to_be_16(0x >> @@ -1486,15 +1484,15 @@ mlx5_flow_field_id_to_modify_info break; ++idx; } - info[idx] = (struct field_modify_info){4, 4 * idx, + info[idx] = (struct field_modify_info){4, 0, MLX5_MODI_OUT_DMAC_47_16}; mask[idx] = rte_cpu_to_be_32((0x >> (32 - width)) << off); } else { if (data->offset < 16) - info[idx++] = (struct field_modify_info){2, 0, + info[idx++] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_DMAC_15_0}; - info[idx] = (struct field_modify_info){4, off, + info[idx] = (struct field_modify_info){4, 0, MLX5_MODI_OUT_DMAC_47_16}; } break; @@ -1502,7 +1500,7 @@ mlx5_flow_field_id_to_modify_info off = data->offset > 16 ? data->offset - 16 : 0; if (mask) { if (data->offset < 16) { - info[idx] = (struct field_modify_info){2, 0, + info[idx] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_SMAC_15_0}; if (width < 16) { mask[idx] = rte_cpu_to_be_16(0x >> @@ -1516,15 +1514,15 @@ mlx5_flow_field_id_to_modify_info break; ++idx; } - info[idx] = (struct field_modify_info){4, 4 * idx, + info[idx] = (struct field_modify_info){4, 0,
[dpdk-dev] [PATCH v4 0/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union - the byte ordering for 64-bit integer was not specified. Many fields have lesser lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented - 64-bit integer size is not enough to provide MAC and IPv6 addresses In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate commit message has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") [2] RFC: http://patches.dpdk.org/project/dpdk/patch/20210910141609.8410-1-viachesl...@nvidia.com/ [3] Deprecation notice: http://patches.dpdk.org/project/dpdk/patch/20210803085754.643180-1-or...@nvidia.com/ [4] v1 - http://patches.dpdk.org/project/dpdk/cover/20211001195223.31909-1-viachesl...@nvidia.com/ [5] v2 - http://patches.dpdk.org/project/dpdk/patch/20211010234547.1495-2-viachesl...@nvidia.com/ [6] v3 - http://patches.dpdk.org/project/dpdk/cover/20211012080631.28504-1-viachesl...@nvidia.com/ v2: - comments addressed - documentation updated - typos fixed - mlx5 PMD updated v3: - comments addressed - documentation updated - typos fixed v4: - removed errorneously added Ack by Ori K. for mlx5 patch - mlx5 patch updated - bug fixes and cleanup Viacheslav Ovsiienko (5): ethdev: update modify field flow action ethdev: fix missed experimental tag for modify field action app/testpmd: update modify field flow action support app/testpmd: fix hex string parser in flow commands net/mlx5: update modify field action app/test-pmd/cmdline_flow.c| 60 doc/guides/prog_guide/rte_flow.rst | 24 - doc/guides/rel_notes/deprecation.rst | 4 - doc/guides/rel_notes/release_21_11.rst | 7 ++ drivers/net/mlx5/mlx5_flow_dv.c| 123 + lib/ethdev/rte_flow.h | 19 +++- 6 files changed, 129 insertions(+), 108 deletions(-) -- 2.18.1
[dpdk-dev] [PATCH v4 2/5] ethdev: fix missed experimental tag for modify field action
EXPERIMENTAL tag was missed in rte_flow_action_modify_data structure description. Fixes: 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam Acked-by: Andrew Rybchenko --- lib/ethdev/rte_flow.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index f14f2b..8a1eddd0b7 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -3204,6 +3204,9 @@ enum rte_flow_field_id { }; /** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * * Field description for MODIFY_FIELD action. */ struct rte_flow_action_modify_data { -- 2.18.1
[dpdk-dev] [PATCH v4 4/5] app/testpmd: fix hex string parser in flow commands
The hexadecimal string parser does not check the target field buffer size, buffer overflow happens and might cause the application failure (segmentation fault is observed usually). Fixes: 169a9fed1f4c ("app/testpmd: fix hex string parser support for flow API") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 736029c4fd..6827d9228f 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -7291,10 +7291,13 @@ parse_hex(struct context *ctx, const struct token *token, hexlen -= 2; } if (hexlen > length) - return -1; + goto error; ret = parse_hex_string(str, hex_tmp, &hexlen); if (ret < 0) goto error; + /* Check the converted binary fits into data buffer. */ + if (hexlen > size) + goto error; /* Let parse_int() fill length information first. */ ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); if (ret < 0) -- 2.18.1
[dpdk-dev] [PATCH v4 1/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union. - the byte ordering for 64-bit integer was not specified. Many fields have shorter lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented. - 64-bit integer size is not enough to provide IPv6 addresses. In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate deprecation notice has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Fixes: 2ba49b5f3721 ("doc: announce change to ethdev modify action data") Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam Acked-by: Andrew Rybchenko --- doc/guides/prog_guide/rte_flow.rst | 24 +++- doc/guides/rel_notes/deprecation.rst | 4 doc/guides/rel_notes/release_21_11.rst | 7 +++ lib/ethdev/rte_flow.h | 16 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..b08087511f 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -2835,6 +2835,22 @@ a packet to any other part of it. ``value`` sets an immediate value to be used as a source or points to a location of the value in memory. It is used instead of ``level`` and ``offset`` for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +The data in memory should be presented exactly in the same byte order and +length as in the relevant flow item, i.e. data for field with type +``RTE_FLOW_FIELD_MAC_DST`` should follow the conventions of ``dst`` field +in ``rte_flow_item_eth`` structure, with type ``RTE_FLOW_FIELD_IPV6_SRC`` - +``rte_flow_item_ipv6`` conventions, and so on. If the field size is larger than +16 bytes the pattern can be provided as pointer only. + +The bitfield extracted from the memory being applied as second operation +parameter is defined by action width and by the destination field offset. +Application should provide the data in immediate value memory (either as +buffer or by pointer) exactly as item field without any applied explicit offset, +and destination packet field (with specified width and bit offset) will be +replaced by immediate source bits from the same bit offset. For example, +to replace the third byte of MAC address with value 0x85, application should +specify destination width as 8, destination offset as 16, and provide immediate +value as sequence of bytes {xxx, xxx, 0x85, xxx, xxx, xxx}. .. _table_rte_flow_action_modify_field: @@ -2865,7 +2881,13 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +---+--+ | ``offset``| number of bits to skip at the beginning | +---+--+ - | ``value`` | immediate value or a pointer to this value | + | ``value`` | immediate value buffer (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_VALUE | + | | field type | + +---+--+ + | ``pvalue``| pointer to immediate value data (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_POINTER| + | | field type | +---+--+ Action: ``CONNTRACK`` diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index a2fe766d4b..dee14077a5 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -120,10 +120,6 @@ Deprecation Notices * ethdev: Announce moving from dedicated modify function for each field, to using the general ``rte_flow_modify_field`` action. -* ethdev: The struct ``rte_flow_action_modify_data`` will be modified - to support modifying fields larger than 64 bits. - In addition, documentation will be updated to clarify byte order. - * ethdev: Attribute ``shared`` of the ``struct rte_flow_action_count`` is deprecated and will be removed in DPDK 21.11. Shared counters should be managed using shared actions API (``rte_flow_shared
[dpdk-dev] [PATCH v4 3/5] ethdev: implement RTE flex item API
From: Gregory Etelson RTE flex item API was introduced in "ethdev: introduce configurable flexible item" patch. The API allows DPDK application to define parser for custom network header in port hardware and offload flows that will match the custom header elements. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c| 40 lib/ethdev/rte_flow_driver.h | 8 lib/ethdev/version.map | 4 3 files changed, 52 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 100983ca59..a858dc31e3 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1323,3 +1323,43 @@ rte_flow_tunnel_item_release(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_item_flex_handle * +rte_flow_flex_item_create(uint16_t port_id, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_item_flex_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->flex_item_create)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; + } + handle = ops->flex_item_create(dev, conf, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_flex_item_release(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_release)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_release(dev, handle, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 46f62c2ec2..34a5a5bcd0 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -139,6 +139,14 @@ struct rte_flow_ops { struct rte_flow_item *pmd_items, uint32_t num_of_items, struct rte_flow_error *err); + struct rte_flow_item_flex_handle *(*flex_item_create) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_conf *conf, +struct rte_flow_error *error); + int (*flex_item_release) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_handle *handle, +struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 904bce6ea1..ec3b66d7a1 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -247,6 +247,10 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_flow_flex_item_create; + rte_flow_flex_item_release; }; INTERNAL { -- 2.18.1
[dpdk-dev] [PATCH v4 0/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item confgiuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; 7. Notes: - v3: http://patches.dpdk.org/project/dpdk/cover/20211011181528.517-1-viachesl...@nvidia.com/ - v2: http://patches.dpdk.org/project/dpdk/patch/20211001193415.23288-2-viachesl...@nvidia.com/ - v1: http://patches.dpdk.org/project/dpdk/patch/20210922180418.20663-2-viachesl...@nvidia.com/ - RFC: http://patches.dpdk.org/project/dpdk/patch/20210806085624.16497-1-viachesl...@nvidia.com/ - v3 -> v2: - comments addressed - testpmd compilation issues fixed - typos fixed - v2 -> v3: - comments addressed - flex item update removed as not supported - RSS over flex item fields removed as not supported and non-complete API - tunnel mode configuration refactored - testpmd updated - documentation updated - PMD patches are removed temporarily (updating WIP, be presented in rc2) - v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (4): ethdev: support flow elements with variable length ethdev: implement RTE flex item API app/testpmd: add jansson library app/testpmd: add flex item CLI commands Viacheslav Ovsiienko (1): ethdev: introduce configurable flexible item app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 764 +++- app/test-pmd/meson.build
[dpdk-dev] [PATCH v4 2/5] ethdev: support flow elements with variable length
From: Gregory Etelson RTE flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. There is the new RTE Flow items with variable lengths coming - flex item). In order to handle this item (and potentially other new ones with variable pattern length) in RTE flow copy and conversion routines the helper function is introduced. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c | 83 --- 1 file changed, 70 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..100983ca59 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,67 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* allow PMD private flow item +* see 5d1bff8fe2 +* "ethdev: allow negative values in flow rule types" +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + +static size_t +rte_flow_item_flex_conv(void *buf, const void *data) +{ + struct rte_flow_item_flex *dst = buf; + const struct rte_flow_item_flex *src = data; + if (buf) { + dst->pattern = rte_memcpy + ((void *)((uintptr_t)(dst + 1)), src->pattern, +src->length); + } + return src->length; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -100,6 +154,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM_FN(FLEX, sizeof(struct rte_flow_item_flex), + rte_flow_item_flex_conv), }; /** Generate flow_action[] entry. */ @@ -107,8 +163,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -527,12 +592,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -634,12 +695,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); +
[dpdk-dev] [PATCH v4 1/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item configuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.h | 222 + 3 files changed, 254 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..495d08a6a9 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,31 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``FLEX`` +^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configuration, the pattern spec and mask are + considered by the driver as padded with trailing zeroes till the full + configured item
[dpdk-dev] [PATCH v4 5/5] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 764 +++- app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 16 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 +++ 5 files changed, 901 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index a9efd027c3..a673e6ef08 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -17822,6 +17822,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_show_fec_mode, (cmdline_parse_inst_t *)&cmd_set_fec_mode, (cmdline_parse_inst_t *)&cmd_show_capability, + (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern, + (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern, NULL, }; diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..b8dd9369b1 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -54,6 +54,8 @@ enum index { COMMON_PRIORITY_LEVEL, COMMON_INDIRECT_ACTION_ID, COMMON_POLICY_ID, + COMMON_FLEX_HANDLE, + COMMON_FLEX_TOKEN, /* TOP-level command. */ ADD, @@ -81,6 +83,12 @@ enum index { AGED, ISOLATE, TUNNEL, + FLEX, + + /* Flex arguments */ + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, /* Tunnel arguments. */ TUNNEL_CREATE, @@ -306,6 +314,9 @@ enum index { ITEM_POL_PORT, ITEM_POL_METER, ITEM_POL_POLICY, + ITEM_FLEX, + ITEM_FLEX_ITEM_HANDLE, + ITEM_FLEX_PATTERN_HANDLE, /* Validate/create actions. */ ACTIONS, @@ -844,6 +855,11 @@ struct buffer { struct { uint32_t policy_id; } policy;/**< Policy arguments. */ + struct { + uint16_t token; + uintptr_t uintptr; + char filename[128]; + } flex; /**< Flex arguments*/ } args; /**< Command arguments. */ }; @@ -871,6 +887,13 @@ struct parse_action_priv { .size = s, \ }) +static const enum index next_flex_item[] = { + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -1000,6 +1023,7 @@ static const enum index next_item[] = { ITEM_GENEVE_OPT, ITEM_INTEGRITY, ITEM_CONNTRACK, + ITEM_FLEX, END_SET, ZERO, }; @@ -1368,6 +1392,13 @@ static const enum index item_integrity_lv[] = { ZERO, }; +static const enum index item_flex[] = { + ITEM_FLEX_PATTERN_HANDLE, + ITEM_FLEX_ITEM_HANDLE, + ITEM_NEXT, + ZERO, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -1724,6 +1755,9 @@ static int parse_set_sample_action(struct context *, const struct token *, static int parse_set_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int +parse_flex_handle(struct context *, const struct token *, + const char *, unsigned int, void *, unsigned in
[dpdk-dev] [PATCH v4 4/5] app/testpmd: add jansson library
From: Gregory Etelson Testpmd interactive mode provides CLI to configure application commands. Testpmd reads CLI command and parameters from STDIN, and converts input into C objects with internal parser. The patch adds jansson dependency to testpmd. With jansson, testpmd can read input in JSON format from STDIN or input file and convert it into C object using jansson library calls. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/meson.build | 5 + app/test-pmd/testpmd.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 98f3289bdf..3a8babd604 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -61,3 +61,8 @@ if dpdk_conf.has('RTE_LIB_BPF') sources += files('bpf_cmd.c') deps += 'bpf' endif +jansson_dep = dependency('jansson', required: false, method: 'pkg-config') +if jansson_dep.found() +dpdk_conf.set('RTE_HAS_JANSSON', 1) +ext_deps += jansson_dep +endif diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 5863b2f43f..876a341cf0 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -14,6 +14,9 @@ #include #include #include +#ifdef RTE_HAS_JANSSON +#include +#endif #define RTE_PORT_ALL(~(portid_t)0x0) -- 2.18.1
[dpdk-dev] [PATCH v5 0/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item confgiuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; 7. Notes: - v4: http://patches.dpdk.org/project/dpdk/patch/20211012113235.24975-2-viachesl...@nvidia.com/ - v3: http://patches.dpdk.org/project/dpdk/cover/20211011181528.517-1-viachesl...@nvidia.com/ - v2: http://patches.dpdk.org/project/dpdk/patch/20211001193415.23288-2-viachesl...@nvidia.com/ - v1: http://patches.dpdk.org/project/dpdk/patch/20210922180418.20663-2-viachesl...@nvidia.com/ - RFC: http://patches.dpdk.org/project/dpdk/patch/20210806085624.16497-1-viachesl...@nvidia.com/ - v4 -> v5: - comments addressed - testpmd compilation issue fixed - v3 -> v4: - comments addressed - testpmd compilation issues fixed - typos fixed - v2 -> v3: - comments addressed - flex item update removed as not supported - RSS over flex item fields removed as not supported and non-complete API - tunnel mode configuration refactored - testpmd updated - documentation updated - PMD patches are removed temporarily (updating WIP, be presented in rc2) - v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (4): ethdev: support flow elements with variable length ethdev: implement RTE flex item API app/testpmd: add jansson library app/testpmd: add flex item CLI commands Viacheslav Ovsiienko (1): ethdev: introduce configurabl
[dpdk-dev] [PATCH v5 1/5] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item configuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.h | 222 + 3 files changed, 254 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..495d08a6a9 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,31 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``FLEX`` +^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configuration, the pattern spec and mask are + considered by the driver as padded with trailing zeroes till the fu
[dpdk-dev] [PATCH v5 2/5] ethdev: support flow elements with variable length
From: Gregory Etelson RTE flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. There is the new RTE Flow items with variable lengths coming - flex item. In order to handle this item (and potentially other new ones with variable pattern length) in RTE flow copy and conversion routines the helper function is introduced. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- lib/ethdev/rte_flow.c | 81 --- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..051781b440 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,65 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* Allow PMD private flow item +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + +static size_t +rte_flow_item_flex_conv(void *buf, const void *data) +{ + struct rte_flow_item_flex *dst = buf; + const struct rte_flow_item_flex *src = data; + if (buf) { + dst->pattern = rte_memcpy + ((void *)((uintptr_t)(dst + 1)), src->pattern, +src->length); + } + return src->length; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -100,6 +152,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM_FN(FLEX, sizeof(struct rte_flow_item_flex), + rte_flow_item_flex_conv), }; /** Generate flow_action[] entry. */ @@ -107,8 +161,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -527,12 +590,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -634,12 +693,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, action->conf, size, +
[dpdk-dev] [PATCH v5 3/5] ethdev: implement RTE flex item API
From: Gregory Etelson RTE flex item API was introduced in "ethdev: introduce configurable flexible item" patch. The API allows DPDK application to define parser for custom network header in port hardware and offload flows that will match the custom header elements. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c| 40 lib/ethdev/rte_flow_driver.h | 8 lib/ethdev/version.map | 4 3 files changed, 52 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 051781b440..8257ed8c97 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1321,3 +1321,43 @@ rte_flow_tunnel_item_release(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_item_flex_handle * +rte_flow_flex_item_create(uint16_t port_id, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_item_flex_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->flex_item_create)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; + } + handle = ops->flex_item_create(dev, conf, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_flex_item_release(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_release)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_release(dev, handle, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 46f62c2ec2..34a5a5bcd0 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -139,6 +139,14 @@ struct rte_flow_ops { struct rte_flow_item *pmd_items, uint32_t num_of_items, struct rte_flow_error *err); + struct rte_flow_item_flex_handle *(*flex_item_create) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_conf *conf, +struct rte_flow_error *error); + int (*flex_item_release) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_handle *handle, +struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 904bce6ea1..ec3b66d7a1 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -247,6 +247,10 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_flow_flex_item_create; + rte_flow_flex_item_release; }; INTERNAL { -- 2.18.1
[dpdk-dev] [PATCH v5 4/5] app/testpmd: add jansson library
From: Gregory Etelson Testpmd interactive mode provides CLI to configure application commands. Testpmd reads CLI command and parameters from STDIN, and converts input into C objects with internal parser. The patch adds jansson dependency to testpmd. With jansson, testpmd can read input in JSON format from STDIN or input file and convert it into C object using jansson library calls. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/meson.build | 5 + app/test-pmd/testpmd.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 98f3289bdf..3a8babd604 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -61,3 +61,8 @@ if dpdk_conf.has('RTE_LIB_BPF') sources += files('bpf_cmd.c') deps += 'bpf' endif +jansson_dep = dependency('jansson', required: false, method: 'pkg-config') +if jansson_dep.found() +dpdk_conf.set('RTE_HAS_JANSSON', 1) +ext_deps += jansson_dep +endif diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 5863b2f43f..876a341cf0 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -14,6 +14,9 @@ #include #include #include +#ifdef RTE_HAS_JANSSON +#include +#endif #define RTE_PORT_ALL(~(portid_t)0x0) -- 2.18.1
[dpdk-dev] [PATCH v5 5/5] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 764 +++- app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 16 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 +++ 5 files changed, 901 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index a9efd027c3..a673e6ef08 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -17822,6 +17822,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_show_fec_mode, (cmdline_parse_inst_t *)&cmd_set_fec_mode, (cmdline_parse_inst_t *)&cmd_show_capability, + (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern, + (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern, NULL, }; diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..f7a6febc1d 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -54,6 +54,8 @@ enum index { COMMON_PRIORITY_LEVEL, COMMON_INDIRECT_ACTION_ID, COMMON_POLICY_ID, + COMMON_FLEX_HANDLE, + COMMON_FLEX_TOKEN, /* TOP-level command. */ ADD, @@ -81,6 +83,12 @@ enum index { AGED, ISOLATE, TUNNEL, + FLEX, + + /* Flex arguments */ + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, /* Tunnel arguments. */ TUNNEL_CREATE, @@ -306,6 +314,9 @@ enum index { ITEM_POL_PORT, ITEM_POL_METER, ITEM_POL_POLICY, + ITEM_FLEX, + ITEM_FLEX_ITEM_HANDLE, + ITEM_FLEX_PATTERN_HANDLE, /* Validate/create actions. */ ACTIONS, @@ -844,6 +855,11 @@ struct buffer { struct { uint32_t policy_id; } policy;/**< Policy arguments. */ + struct { + uint16_t token; + uintptr_t uintptr; + char filename[128]; + } flex; /**< Flex arguments*/ } args; /**< Command arguments. */ }; @@ -871,6 +887,13 @@ struct parse_action_priv { .size = s, \ }) +static const enum index next_flex_item[] = { + FLEX_ITEM_INIT, + FLEX_ITEM_CREATE, + FLEX_ITEM_DESTROY, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -1000,6 +1023,7 @@ static const enum index next_item[] = { ITEM_GENEVE_OPT, ITEM_INTEGRITY, ITEM_CONNTRACK, + ITEM_FLEX, END_SET, ZERO, }; @@ -1368,6 +1392,13 @@ static const enum index item_integrity_lv[] = { ZERO, }; +static const enum index item_flex[] = { + ITEM_FLEX_PATTERN_HANDLE, + ITEM_FLEX_ITEM_HANDLE, + ITEM_NEXT, + ZERO, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -1724,6 +1755,9 @@ static int parse_set_sample_action(struct context *, const struct token *, static int parse_set_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int +parse_flex_handle(struct context *, const struct token *, + const char *, unsigned int, void *, unsigned in
[dpdk-dev] [PATCH v6 0/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union - the byte ordering for 64-bit integer was not specified. Many fields have lesser lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented - 64-bit integer size is not enough to provide MAC and IPv6 addresses In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate commit message has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") [2] RFC: http://patches.dpdk.org/project/dpdk/patch/20210910141609.8410-1-viachesl...@nvidia.com/ [3] Deprecation notice: http://patches.dpdk.org/project/dpdk/patch/20210803085754.643180-1-or...@nvidia.com/ [4] v1 - http://patches.dpdk.org/project/dpdk/cover/20211001195223.31909-1-viachesl...@nvidia.com/ [5] v2 - http://patches.dpdk.org/project/dpdk/patch/20211010234547.1495-2-viachesl...@nvidia.com/ [6] v3 - http://patches.dpdk.org/project/dpdk/cover/20211012080631.28504-1-viachesl...@nvidia.com/ [7] v4 - http://patches.dpdk.org/project/dpdk/cover/20211012104919.13145-1-viachesl...@nvidia.com/ [8] v5 - http://patches.dpdk.org/project/dpdk/patch/20211012202557.30295-2-viachesl...@nvidia.com/ v2: - comments addressed - documentation updated - typos fixed - mlx5 PMD updated v3: - comments addressed - documentation updated - typos fixed v4: - removed errorneously added Ack by Ori K. for mlx5 patch - mlx5 patch updated - bug fixes and cleanup v5: - fix compilation issue with unused variable in mlx5 v6: - fix compilation issue with unused variable in mlx5 Viacheslav Ovsiienko (5): ethdev: update modify field flow action ethdev: fix missed experimental tag for modify field action app/testpmd: update modify field flow action support app/testpmd: fix hex string parser in flow commands net/mlx5: update modify field action app/test-pmd/cmdline_flow.c| 60 doc/guides/prog_guide/rte_flow.rst | 24 - doc/guides/rel_notes/deprecation.rst | 4 - doc/guides/rel_notes/release_21_11.rst | 7 ++ drivers/net/mlx5/mlx5_flow_dv.c| 128 + lib/ethdev/rte_flow.h | 19 +++- 6 files changed, 131 insertions(+), 111 deletions(-) -- 2.18.1
[dpdk-dev] [PATCH v6 1/5] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union. - the byte ordering for 64-bit integer was not specified. Many fields have shorter lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented. - 64-bit integer size is not enough to provide IPv6 addresses. In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation Appropriate deprecation notice has been removed. [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Fixes: 2ba49b5f3721 ("doc: announce change to ethdev modify action data") Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam Acked-by: Andrew Rybchenko --- doc/guides/prog_guide/rte_flow.rst | 24 +++- doc/guides/rel_notes/deprecation.rst | 4 doc/guides/rel_notes/release_21_11.rst | 7 +++ lib/ethdev/rte_flow.h | 16 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..b08087511f 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -2835,6 +2835,22 @@ a packet to any other part of it. ``value`` sets an immediate value to be used as a source or points to a location of the value in memory. It is used instead of ``level`` and ``offset`` for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +The data in memory should be presented exactly in the same byte order and +length as in the relevant flow item, i.e. data for field with type +``RTE_FLOW_FIELD_MAC_DST`` should follow the conventions of ``dst`` field +in ``rte_flow_item_eth`` structure, with type ``RTE_FLOW_FIELD_IPV6_SRC`` - +``rte_flow_item_ipv6`` conventions, and so on. If the field size is larger than +16 bytes the pattern can be provided as pointer only. + +The bitfield extracted from the memory being applied as second operation +parameter is defined by action width and by the destination field offset. +Application should provide the data in immediate value memory (either as +buffer or by pointer) exactly as item field without any applied explicit offset, +and destination packet field (with specified width and bit offset) will be +replaced by immediate source bits from the same bit offset. For example, +to replace the third byte of MAC address with value 0x85, application should +specify destination width as 8, destination offset as 16, and provide immediate +value as sequence of bytes {xxx, xxx, 0x85, xxx, xxx, xxx}. .. _table_rte_flow_action_modify_field: @@ -2865,7 +2881,13 @@ for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +---+--+ | ``offset``| number of bits to skip at the beginning | +---+--+ - | ``value`` | immediate value or a pointer to this value | + | ``value`` | immediate value buffer (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_VALUE | + | | field type | + +---+--+ + | ``pvalue``| pointer to immediate value data (source field only, not | + | | applicable to destination) for RTE_FLOW_FIELD_POINTER| + | | field type | +---+--+ Action: ``CONNTRACK`` diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index a2fe766d4b..dee14077a5 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -120,10 +120,6 @@ Deprecation Notices * ethdev: Announce moving from dedicated modify function for each field, to using the general ``rte_flow_modify_field`` action. -* ethdev: The struct ``rte_flow_action_modify_data`` will be modified - to support modifying fields larger than 64 bits. - In addition, documentation will be updated to clarify byte order. - * ethdev: Attribute ``shared`` of the ``struct rte_flow_action_count`` is deprecated and will be removed in DPDK 21.11. Shared counters should be managed using shared actions API (``rte_flow_shared
[dpdk-dev] [PATCH v6 2/5] ethdev: fix missed experimental tag for modify field action
EXPERIMENTAL tag was missed in rte_flow_action_modify_data structure description. Fixes: 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam Acked-by: Andrew Rybchenko --- lib/ethdev/rte_flow.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index f14f2b..8a1eddd0b7 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -3204,6 +3204,9 @@ enum rte_flow_field_id { }; /** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * * Field description for MODIFY_FIELD action. */ struct rte_flow_action_modify_data { -- 2.18.1
[dpdk-dev] [PATCH v6 3/5] app/testpmd: update modify field flow action support
The testpmd flow create command updates provided: - modify field action supports the updated actions - pointer type added for action source field - pointer and value source field takes hex string instead of unsigned int in host endianness There are some examples of flow with update modified field action: 1. IPv6 destination address bytes 4-7 assignment: :: - > ::4455:6677:: flow create 0 egress group 1 pattern eth / ipv6 dst is :: / udp / end actions modify_field op set dst_type ipv6_dst dst_offset 32 src_type value src_value 0011223344556677 width 32 / end 2. Copy second byte of IPv4 destination address to the third byte of source address: 10.0.118.4 -> 192.168.100.1 10.0.168.4 -> 192.168.100.1 flow create 0 egress group 1 pattern eth / ipv4 / udp / end actions modify_field op set dst_type ipv4_src dst_offset 16 src_type ipv4_dst src_offset 8 width 8 / end 3. Assign METADATA value with 11223344 value from the hex string in the linear buffer. Please note, the value definition should follow host-endian, example is given for x86 (little-endian): flow create 0 egress group 1 pattern eth / ipv4 / end actions modify_field op set dst_type meta src_type pointer src_ptr 44332211 width 32 / end 4. Assign destination MAC with EA:11:0B:AD:0B:ED value: flow create 0 egress group 1 pattern eth / end actions modify_field op set dst_type mac_dst src_type value src_value EA110BAD0BED width 48 / end Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 55 + 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index bb22294dd3..736029c4fd 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -448,6 +448,7 @@ enum index { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ACTION_CONNTRACK, ACTION_CONNTRACK_UPDATE, @@ -468,6 +469,14 @@ enum index { #define ITEM_RAW_SIZE \ (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) +/** Maximum size for external pattern in struct rte_flow_action_modify_data. */ +#define ACTION_MODIFY_PATTERN_SIZE 32 + +/** Storage size for struct rte_flow_action_modify_field including pattern. */ +#define ACTION_MODIFY_SIZE \ + (sizeof(struct rte_flow_action_modify_field) + \ + ACTION_MODIFY_PATTERN_SIZE) + /** Maximum number of queue indices in struct rte_flow_action_rss. */ #define ACTION_RSS_QUEUE_NUM 128 @@ -1704,6 +1713,7 @@ static const enum index action_modify_field_src[] = { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ZERO, }; @@ -4455,8 +4465,7 @@ static const struct token token_list[] = { [ACTION_MODIFY_FIELD] = { .name = "modify_field", .help = "modify destination field with data from source field", - .priv = PRIV_ACTION(MODIFY_FIELD, - sizeof(struct rte_flow_action_modify_field)), + .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), .call = parse_vc, }, @@ -4539,11 +4548,26 @@ static const struct token token_list[] = { .name = "src_value", .help = "source immediate value", .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), - NEXT_ENTRY(COMMON_UNSIGNED)), - .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY(struct rte_flow_action_modify_field, src.value)), .call = parse_vc_conf, }, + [ACTION_MODIFY_FIELD_SRC_POINTER] = { + .name = "src_ptr", + .help = "pointer to source immediate value", + .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, + src.pvalue), +
[dpdk-dev] [PATCH v6 4/5] app/testpmd: fix hex string parser in flow commands
The hexadecimal string parser does not check the target field buffer size, buffer overflow happens and might cause the application failure (segmentation fault is observed usually). Fixes: 169a9fed1f4c ("app/testpmd: fix hex string parser support for flow API") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 736029c4fd..6827d9228f 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -7291,10 +7291,13 @@ parse_hex(struct context *ctx, const struct token *token, hexlen -= 2; } if (hexlen > length) - return -1; + goto error; ret = parse_hex_string(str, hex_tmp, &hexlen); if (ret < 0) goto error; + /* Check the converted binary fits into data buffer. */ + if (hexlen > size) + goto error; /* Let parse_int() fill length information first. */ ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); if (ret < 0) -- 2.18.1
[dpdk-dev] [PATCH v6 5/5] net/mlx5: update modify field action
Update immediate value/pointer source operand support for modify field RTE Flow action: - source operand data can be presented by byte buffer (instead of former uint64_t) or by pointer - no host byte ordering is assumed anymore for immediate data buffer (not uint64_t anymore) - no immediate value offset is expected (the source subfield is located at the same offset as in destination) Signed-off-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_dv.c | 128 +++- 1 file changed, 44 insertions(+), 84 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index c6370cd1d6..552b149041 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -1391,7 +1391,7 @@ flow_dv_convert_action_modify_ipv6_dscp static int mlx5_flow_item_field_width(struct mlx5_priv *priv, - enum rte_flow_field_id field) + enum rte_flow_field_id field, int inherit) { switch (field) { case RTE_FLOW_FIELD_START: @@ -1442,7 +1442,7 @@ mlx5_flow_item_field_width(struct mlx5_priv *priv, return __builtin_popcount(priv->sh->dv_meta_mask); case RTE_FLOW_FIELD_POINTER: case RTE_FLOW_FIELD_VALUE: - return 64; + return inherit < 0 ? 0 : inherit; default: MLX5_ASSERT(false); } @@ -1452,17 +1452,14 @@ mlx5_flow_item_field_width(struct mlx5_priv *priv, static void mlx5_flow_field_id_to_modify_info (const struct rte_flow_action_modify_data *data, -struct field_modify_info *info, -uint32_t *mask, uint32_t *value, -uint32_t width, uint32_t dst_width, -uint32_t *shift, struct rte_eth_dev *dev, -const struct rte_flow_attr *attr, -struct rte_flow_error *error) +struct field_modify_info *info, uint32_t *mask, +uint32_t width, uint32_t *shift, struct rte_eth_dev *dev, +const struct rte_flow_attr *attr, struct rte_flow_error *error) { struct mlx5_priv *priv = dev->data->dev_private; uint32_t idx = 0; uint32_t off = 0; - uint64_t val = 0; + switch (data->field) { case RTE_FLOW_FIELD_START: /* not supported yet */ @@ -1472,7 +1469,7 @@ mlx5_flow_field_id_to_modify_info off = data->offset > 16 ? data->offset - 16 : 0; if (mask) { if (data->offset < 16) { - info[idx] = (struct field_modify_info){2, 0, + info[idx] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_DMAC_15_0}; if (width < 16) { mask[idx] = rte_cpu_to_be_16(0x >> @@ -1486,15 +1483,15 @@ mlx5_flow_field_id_to_modify_info break; ++idx; } - info[idx] = (struct field_modify_info){4, 4 * idx, + info[idx] = (struct field_modify_info){4, 0, MLX5_MODI_OUT_DMAC_47_16}; mask[idx] = rte_cpu_to_be_32((0x >> (32 - width)) << off); } else { if (data->offset < 16) - info[idx++] = (struct field_modify_info){2, 0, + info[idx++] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_DMAC_15_0}; - info[idx] = (struct field_modify_info){4, off, + info[idx] = (struct field_modify_info){4, 0, MLX5_MODI_OUT_DMAC_47_16}; } break; @@ -1502,7 +1499,7 @@ mlx5_flow_field_id_to_modify_info off = data->offset > 16 ? data->offset - 16 : 0; if (mask) { if (data->offset < 16) { - info[idx] = (struct field_modify_info){2, 0, + info[idx] = (struct field_modify_info){2, 4, MLX5_MODI_OUT_SMAC_15_0}; if (width < 16) { mask[idx] = rte_cpu_to_be_16(0x >> @@ -1516,15 +1513,15 @@ mlx5_flow_field_id_to_modify_info break; ++idx; } - info[idx] = (struct field_modify_info){4, 4 * idx, + info[idx] = (struct field_modify_
[dpdk-dev] [PATCH v6 0/6] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item confgiuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; 7. Notes: - v5: http://patches.dpdk.org/project/dpdk/patch/20211012125433.31647-2-viachesl...@nvidia.com/ - v4: http://patches.dpdk.org/project/dpdk/patch/20211012113235.24975-2-viachesl...@nvidia.com/ - v3: http://patches.dpdk.org/project/dpdk/cover/20211011181528.517-1-viachesl...@nvidia.com/ - v2: http://patches.dpdk.org/project/dpdk/patch/20211001193415.23288-2-viachesl...@nvidia.com/ - v1: http://patches.dpdk.org/project/dpdk/patch/20210922180418.20663-2-viachesl...@nvidia.com/ - RFC: http://patches.dpdk.org/project/dpdk/patch/20210806085624.16497-1-viachesl...@nvidia.com/ - v5 -> v6: - flex item command moved to dedicated file cmd_flex_item.c - v4 -> v5: - comments addressed - testpmd compilation issue fixed - v3 -> v4: - comments addressed - testpmd compilation issues fixed - typos fixed - v2 -> v3: - comments addressed - flex item update removed as not supported - RSS over flex item fields removed as not supported and non-complete API - tunnel mode configuration refactored - testpmd updated - documentation updated - PMD patches are removed temporarily (updating WIP, be presented in rc2) - v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (5): ethdev: support flow elements with variab
[dpdk-dev] [PATCH v6 1/6] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item configuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.h | 222 + 3 files changed, 254 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 3cb014c1fa..eb472a8b77 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,31 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``FLEX`` +^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configuration, the pattern spec and mask are + considered by the driver as padded with trailing zeroes till the fu
[dpdk-dev] [PATCH v6 2/6] ethdev: support flow elements with variable length
From: Gregory Etelson RTE flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. There is the new RTE Flow items with variable lengths coming - flex item. In order to handle this item (and potentially other new ones with variable pattern length) in RTE flow copy and conversion routines the helper function is introduced. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- lib/ethdev/rte_flow.c | 81 --- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..051781b440 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,65 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* Allow PMD private flow item +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + +static size_t +rte_flow_item_flex_conv(void *buf, const void *data) +{ + struct rte_flow_item_flex *dst = buf; + const struct rte_flow_item_flex *src = data; + if (buf) { + dst->pattern = rte_memcpy + ((void *)((uintptr_t)(dst + 1)), src->pattern, +src->length); + } + return src->length; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -100,6 +152,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM_FN(FLEX, sizeof(struct rte_flow_item_flex), + rte_flow_item_flex_conv), }; /** Generate flow_action[] entry. */ @@ -107,8 +161,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -527,12 +590,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -634,12 +693,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, action->conf, size, +
[dpdk-dev] [PATCH v6 5/6] app/testpmd: add dedicated flow command parsing routine
From: Gregory Etelson testpmd flow creation is constructed from these procedures: 1. receive string with flow rule description; 2. parse input string and build flow parameters: port_id value, flow attributes, items array, actions array; 3. create a flow rule from flow rule parameters. Flow rule creation procedures are built as a pipeline. A new procedure starts immediately after successful predecessor completion. Due to this we have no dedicated routines providing intermediate results for step 1-3 above. The patch adds `flow_parse()` function call. It parses input string and provides a caller with parsed data. This is a preparation step for introducing flex item command processing. Signed-off-by: Gregory Etelson --- app/test-pmd/cmdline_flow.c | 24 app/test-pmd/testpmd.h | 5 + 2 files changed, 29 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 0b5856c7d5..4e8e3e3c29 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -7952,6 +7952,30 @@ cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, return len; } +int +flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, struct rte_flow_action **actions) +{ + int ret; + struct context saved_flow_ctx = cmd_flow_context; + + cmd_flow_context_init(&cmd_flow_context); + do { + ret = cmd_flow_parse(NULL, src, result, size); + if (ret > 0) { + src += ret; + while (isspace(*src)) + src++; + } + } while (ret > 0 && strlen(src)); + cmd_flow_context = saved_flow_ctx; + *attr = &((struct buffer *)result)->args.vc.attr; + *pattern = ((struct buffer *)result)->args.vc.pattern; + *actions = ((struct buffer *)result)->args.vc.actions; + return (ret >= 0 && !strlen(src)) ? 0 : -1; +} + /** Return number of completion entries (cmdline API). */ static int cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index fc43bf2763..c580406e99 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1027,6 +1027,11 @@ void add_tx_dynf_callback(portid_t portid); void remove_tx_dynf_callback(portid_t portid); int update_jumbo_frame_offload(portid_t portid); +extern int flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, + struct rte_flow_action **actions); + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. -- 2.18.1
[dpdk-dev] [PATCH v6 3/6] ethdev: implement RTE flex item API
From: Gregory Etelson RTE flex item API was introduced in "ethdev: introduce configurable flexible item" patch. The API allows DPDK application to define parser for custom network header in port hardware and offload flows that will match the custom header elements. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- lib/ethdev/rte_flow.c| 40 lib/ethdev/rte_flow_driver.h | 8 lib/ethdev/version.map | 2 ++ 3 files changed, 50 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 051781b440..8257ed8c97 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1321,3 +1321,43 @@ rte_flow_tunnel_item_release(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_item_flex_handle * +rte_flow_flex_item_create(uint16_t port_id, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_item_flex_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->flex_item_create)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; + } + handle = ops->flex_item_create(dev, conf, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_flex_item_release(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_release)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_release(dev, handle, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 46f62c2ec2..34a5a5bcd0 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -139,6 +139,14 @@ struct rte_flow_ops { struct rte_flow_item *pmd_items, uint32_t num_of_items, struct rte_flow_error *err); + struct rte_flow_item_flex_handle *(*flex_item_create) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_conf *conf, +struct rte_flow_error *error); + int (*flex_item_release) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_handle *handle, +struct rte_flow_error *error); }; /** diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index 29fb71f1af..6992e25046 100644 --- a/lib/ethdev/version.map +++ b/lib/ethdev/version.map @@ -248,6 +248,8 @@ EXPERIMENTAL { # added in 21.11 rte_eth_rx_metadata_negotiate; + rte_flow_flex_item_create; + rte_flow_flex_item_release; }; INTERNAL { -- 2.18.1
[dpdk-dev] [PATCH v6 4/6] app/testpmd: add jansson library
From: Gregory Etelson Testpmd interactive mode provides CLI to configure application commands. Testpmd reads CLI command and parameters from STDIN, and converts input into C objects with internal parser. The patch adds jansson dependency to testpmd. With jansson, testpmd can read input in JSON format from STDIN or input file and convert it into C object using jansson library calls. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- app/test-pmd/meson.build | 5 + app/test-pmd/testpmd.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 98f3289bdf..3a8babd604 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -61,3 +61,8 @@ if dpdk_conf.has('RTE_LIB_BPF') sources += files('bpf_cmd.c') deps += 'bpf' endif +jansson_dep = dependency('jansson', required: false, method: 'pkg-config') +if jansson_dep.found() +dpdk_conf.set('RTE_HAS_JANSSON', 1) +ext_deps += jansson_dep +endif diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index e9d9db06ce..fc43bf2763 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -14,6 +14,9 @@ #include #include #include +#ifdef RTE_HAS_JANSSON +#include +#endif #define RTE_PORT_ALL(~(portid_t)0x0) -- 2.18.1
[dpdk-dev] [PATCH v6 6/6] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmd_flex_item.c| 548 app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 223 +++- app/test-pmd/meson.build| 1 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 26 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 + 7 files changed, 919 insertions(+), 2 deletions(-) create mode 100644 app/test-pmd/cmd_flex_item.c diff --git a/app/test-pmd/cmd_flex_item.c b/app/test-pmd/cmd_flex_item.c new file mode 100644 index 00..45103e45a8 --- /dev/null +++ b/app/test-pmd/cmd_flex_item.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM]; +struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM]; + +#ifdef RTE_HAS_JANSSON +static __rte_always_inline bool +match_strkey(const char *key, const char *pattern) +{ + return strncmp(key, pattern, strlen(key)) == 0; +} + +static struct flex_item * +flex_parser_fetch(uint16_t port_id, uint16_t flex_id) +{ + if (port_id >= RTE_MAX_ETHPORTS) { + printf("Invalid port_id: %u\n", port_id); + return FLEX_PARSER_ERR; + } + if (flex_id >= FLEX_MAX_PARSERS_NUM) { + printf("Invalid flex item flex_id: %u\n", flex_id); + return FLEX_PARSER_ERR; + } + return flex_items[port_id][flex_id]; +} + +void +flex_item_destroy(portid_t port_id, uint16_t flex_id) +{ + int ret; + struct rte_flow_error error; + struct flex_item *fp = flex_parser_fetch(port_id, flex_id); + if (fp == FLEX_PARSER_ERR) { + printf("Bad parameters: port_id=%u flex_id=%u\n", + port_id, flex_id); + return; + } + if (!fp) + return; + ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error); + if (!ret) { + free(fp); + flex_items[port_id][flex_id] = NULL; + printf("port-%u: released flex item #%u\n", + port_id, flex_id); + + } else { + printf("port-%u: cannot release flex item #%u: %s\n", + port_id, flex_id, error.message); + } +} + +static int +flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel) +{ + int tun = -1; + + if (json_is_integer(jtun)) + tun = (int)json_integer_value(jtun); + else if (json_is_real(jtun)) + tun = (int)json_real_value(jtun); + else if (json_is_string(jtun)) { + const char *mode = json_string_value(jtun); + + if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE")) + tun = FLEX_TUNNEL_MODE_SINGLE; + else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER")) + tun = FLEX_TUNNEL_MODE_OUTER; + else if (match_strkey(mode, "FLEX_TUNNEL_MODE_INNER")) + tun = FLEX_TUNNEL_MODE_INNER; + else if (matc
[dpdk-dev] [PATCH v7 1/4] ethdev: support flow elements with variable length
Flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. There is the new Flow items with variable lengths coming - flex item. In order to handle this item (and potentially other new ones with variable pattern length) in flow copy and conversion routines the helper function is introduced. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- lib/ethdev/rte_flow.c | 66 ++- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 29f2b0e954..c8e12404a7 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,52 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* Allow PMD private flow item +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -109,8 +148,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -531,12 +579,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -638,12 +682,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, action->conf, size, +rte_flow_desc_action, action->type); break; } return off; -- 2.18.1
[dpdk-dev] [PATCH v7 0/4] ethdev: introduce configurable flexible item
v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (2): app/testpmd: add dedicated flow command parsing routine app/testpmd: add flex item CLI commands Viacheslav Ovsiienko (2): ethdev: support flow elements with variable length ethdev: introduce configurable flexible item app/test-pmd/cmd_flex_item.c| 548 app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 247 - app/test-pmd/meson.build| 6 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 35 ++ doc/guides/prog_guide/rte_flow.rst | 25 + doc/guides/rel_notes/release_21_11.rst | 7 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 + lib/ethdev/rte_flow.c | 121 - lib/ethdev/rte_flow.h | 225 lib/ethdev/rte_flow_driver.h| 8 + lib/ethdev/version.map | 2 + 13 files changed, 1332 insertions(+), 15 deletions(-) create mode 100644 app/test-pmd/cmd_flex_item.c -- 2.18.1
[dpdk-dev] [PATCH v7 2/4] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item configuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.c | 55 ++ lib/ethdev/rte_flow.h | 225 + lib/ethdev/rte_flow_driver.h | 8 + lib/ethdev/version.map | 2 + 6 files changed, 322 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index fa05fe0845..aeba374182 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1548,6 +1548,31 @@ This item is meant to use the same structure as `Item: PORT_REPRESENTOR`_. See also `Action: REPRESENTED_PORT`_. +Item: ``FLEX`` +^^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configurat
[dpdk-dev] [PATCH v7 3/4] app/testpmd: add dedicated flow command parsing routine
From: Gregory Etelson testpmd flow creation is constructed from these procedures: 1. receive string with flow rule description; 2. parse input string and build flow parameters: port_id value, flow attributes, items array, actions array; 3. create a flow rule from flow rule parameters. Flow rule creation procedures are built as a pipeline. A new procedure starts immediately after successful predecessor completion. Due to this we have no dedicated routines providing intermediate results for step 1-3 above. The patch adds `flow_parse()` function call. It parses input string and provides a caller with parsed data. This is a preparation step for introducing flex item command processing. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 24 app/test-pmd/testpmd.h | 5 + 2 files changed, 29 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index a90822b660..cd640b9b7a 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -8076,6 +8076,30 @@ cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, return len; } +int +flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, struct rte_flow_action **actions) +{ + int ret; + struct context saved_flow_ctx = cmd_flow_context; + + cmd_flow_context_init(&cmd_flow_context); + do { + ret = cmd_flow_parse(NULL, src, result, size); + if (ret > 0) { + src += ret; + while (isspace(*src)) + src++; + } + } while (ret > 0 && strlen(src)); + cmd_flow_context = saved_flow_ctx; + *attr = &((struct buffer *)result)->args.vc.attr; + *pattern = ((struct buffer *)result)->args.vc.pattern; + *actions = ((struct buffer *)result)->args.vc.actions; + return (ret >= 0 && !strlen(src)) ? 0 : -1; +} + /** Return number of completion entries (cmdline API). */ static int cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index dd8f27a296..81be754605 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1047,6 +1047,11 @@ void add_tx_dynf_callback(portid_t portid); void remove_tx_dynf_callback(portid_t portid); int update_mtu_from_frame_size(portid_t portid, uint32_t max_rx_pktlen); +extern int flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, + struct rte_flow_action **actions); + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. -- 2.18.1
[dpdk-dev] [PATCH v7 4/4] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. A new optional dependency on jansson library is added for testpmd. If jansson not detected the flex item functionality is disabled. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmd_flex_item.c| 548 app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 223 +++- app/test-pmd/meson.build| 6 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 30 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 + 7 files changed, 928 insertions(+), 2 deletions(-) create mode 100644 app/test-pmd/cmd_flex_item.c diff --git a/app/test-pmd/cmd_flex_item.c b/app/test-pmd/cmd_flex_item.c new file mode 100644 index 00..45103e45a8 --- /dev/null +++ b/app/test-pmd/cmd_flex_item.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM]; +struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM]; + +#ifdef RTE_HAS_JANSSON +static __rte_always_inline bool +match_strkey(const char *key, const char *pattern) +{ + return strncmp(key, pattern, strlen(key)) == 0; +} + +static struct flex_item * +flex_parser_fetch(uint16_t port_id, uint16_t flex_id) +{ + if (port_id >= RTE_MAX_ETHPORTS) { + printf("Invalid port_id: %u\n", port_id); + return FLEX_PARSER_ERR; + } + if (flex_id >= FLEX_MAX_PARSERS_NUM) { + printf("Invalid flex item flex_id: %u\n", flex_id); + return FLEX_PARSER_ERR; + } + return flex_items[port_id][flex_id]; +} + +void +flex_item_destroy(portid_t port_id, uint16_t flex_id) +{ + int ret; + struct rte_flow_error error; + struct flex_item *fp = flex_parser_fetch(port_id, flex_id); + if (fp == FLEX_PARSER_ERR) { + printf("Bad parameters: port_id=%u flex_id=%u\n", + port_id, flex_id); + return; + } + if (!fp) + return; + ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error); + if (!ret) { + free(fp); + flex_items[port_id][flex_id] = NULL; + printf("port-%u: released flex item #%u\n", + port_id, flex_id); + + } else { + printf("port-%u: cannot release flex item #%u: %s\n", + port_id, flex_id, error.message); + } +} + +static int +flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel) +{ + int tun = -1; + + if (json_is_integer(jtun)) + tun = (int)json_integer_value(jtun); + else if (json_is_real(jtun)) + tun = (int)json_real_value(jtun); + else if (json_is_string(jtun)) { + const char *mode = json_string_value(jtun); + + if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE")) + tun = FLEX_TUNNEL_MODE_SINGLE; + else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER")) + tun = FLEX_TUNNEL_MODE_OUTER; + else if (match_strke
[dpdk-dev] [PATCH v8 0/4] ethdev: introduce configurable flexible item
non-complete API - tunnel mode configuration refactored - testpmd updated - documentation updated - PMD patches are removed temporarily (updating WIP, be presented in rc2) - v1 -> v2: - testpmd CLI to handle flex item is provided - draft PMD code is introduced Signed-off-by: Viacheslav Ovsiienko Gregory Etelson (3): ethdev: support flow elements with variable length app/testpmd: add dedicated flow command parsing routine app/testpmd: add flex item CLI commands Viacheslav Ovsiienko (1): ethdev: introduce configurable flexible item app/test-pmd/cmd_flex_item.c| 548 app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 247 - app/test-pmd/meson.build| 6 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 35 ++ doc/guides/prog_guide/rte_flow.rst | 25 + doc/guides/rel_notes/release_21_11.rst | 7 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 + lib/ethdev/rte_flow.c | 121 - lib/ethdev/rte_flow.h | 225 lib/ethdev/rte_flow_driver.h| 8 + lib/ethdev/version.map | 2 + 13 files changed, 1332 insertions(+), 15 deletions(-) create mode 100644 app/test-pmd/cmd_flex_item.c -- 2.18.1
[dpdk-dev] [PATCH v8 1/4] ethdev: support flow elements with variable length
From: Gregory Etelson Flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. There is the new Flow items with variable lengths coming - flex item. In order to handle this item (and potentially other new ones with variable pattern length) in flow copy and conversion routines the helper function is introduced. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- lib/ethdev/rte_flow.c | 66 ++- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 29f2b0e954..c8e12404a7 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,52 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* Allow PMD private flow item +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -109,8 +148,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -531,12 +579,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -638,12 +682,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, action->conf, size, +rte_flow_desc_action, action->type); break; } return off; -- 2.18.1
[dpdk-dev] [PATCH v8 4/4] app/testpmd: add flex item CLI commands
From: Gregory Etelson Network port hardware is shipped with fixed number of supported network protocols. If application must work with a protocol that is not included in the port hardware by default, it can try to add the new protocol to port hardware. Flex item or flex parser is port infrastructure that allows application to add support for a custom network header and offload flows to match the header elements. Application must complete the following tasks to create a flow rule that matches custom header: 1. Create flow item object in port hardware. Application must provide custom header configuration to PMD. PMD will use that configuration to create flex item object in port hardware. 2. Create flex patterns to match. Flex pattern has a spec and a mask components, like a regular flow item. Combined together, spec and mask can target unique data sequence or a number of data sequences in the custom header. Flex patterns of the same flex item can have different lengths. Flex pattern is identified by unique handler value. 3. Create a flow rule with a flex flow item that references flow pattern. Testpmd flex CLI commands are: testpmd> flow flex_item create testpmd> set flex_pattern \ spec mask testpmd> set flex_pattern is testpmd> flow create ... \ / flex item is pattern is / ... The patch works with the jansson library API. A new optional dependency on jansson library is added for testpmd. If jansson not detected the flex item functionality is disabled. Jansson development files must be present: jansson.pc, jansson.h libjansson.[a,so] Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmd_flex_item.c| 548 app/test-pmd/cmdline.c | 2 + app/test-pmd/cmdline_flow.c | 223 +++- app/test-pmd/meson.build| 6 + app/test-pmd/testpmd.c | 2 +- app/test-pmd/testpmd.h | 30 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 119 + 7 files changed, 928 insertions(+), 2 deletions(-) create mode 100644 app/test-pmd/cmd_flex_item.c diff --git a/app/test-pmd/cmd_flex_item.c b/app/test-pmd/cmd_flex_item.c new file mode 100644 index 00..45103e45a8 --- /dev/null +++ b/app/test-pmd/cmd_flex_item.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 NVIDIA Corporation & Affiliates + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "testpmd.h" + +struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM]; +struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM]; + +#ifdef RTE_HAS_JANSSON +static __rte_always_inline bool +match_strkey(const char *key, const char *pattern) +{ + return strncmp(key, pattern, strlen(key)) == 0; +} + +static struct flex_item * +flex_parser_fetch(uint16_t port_id, uint16_t flex_id) +{ + if (port_id >= RTE_MAX_ETHPORTS) { + printf("Invalid port_id: %u\n", port_id); + return FLEX_PARSER_ERR; + } + if (flex_id >= FLEX_MAX_PARSERS_NUM) { + printf("Invalid flex item flex_id: %u\n", flex_id); + return FLEX_PARSER_ERR; + } + return flex_items[port_id][flex_id]; +} + +void +flex_item_destroy(portid_t port_id, uint16_t flex_id) +{ + int ret; + struct rte_flow_error error; + struct flex_item *fp = flex_parser_fetch(port_id, flex_id); + if (fp == FLEX_PARSER_ERR) { + printf("Bad parameters: port_id=%u flex_id=%u\n", + port_id, flex_id); + return; + } + if (!fp) + return; + ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error); + if (!ret) { + free(fp); + flex_items[port_id][flex_id] = NULL; + printf("port-%u: released flex item #%u\n", + port_id, flex_id); + + } else { + printf("port-%u: cannot release flex item #%u: %s\n", + port_id, flex_id, error.message); + } +} + +static int +flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel) +{ + int tun = -1; + + if (json_is_integer(jtun)) + tun = (int)json_integer_value(jtun); + else if (json_is_real(jtun)) + tun = (int)json_real_value(jtun); + else if (json_is_string(jtun)) { + const char *mode = json_string_value(jtun); + + if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE")) + tun = FLEX_TUNNEL_MODE_SINGLE; + else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER")) + tun = FLEX_TUNNEL_MODE_OUTER; + else if (match_strke
[dpdk-dev] [PATCH v8 2/4] ethdev: introduce configurable flexible item
t flex item as input arc, drivers should adjust the item configuration. Also, the hardware resources used by flex items to handle the packet can be limited. If there are multiple flex items that are supposed to be used within the same flow it would be nice to provide some hint for the driver that these two or more flex items are intended for simultaneous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items supposed to be provided within the same flow should be the same as well. In other words, the field hint index specifies the group of fields that can be matched simultaneously within a single flow. If hint indices are specified, the driver will try to engage not overlapping hardware resources and provide independent handling of the field groups with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .tunnel = FLEX_TUNNEL_MODE_SINGLE, .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .nb_samples = 2, .input_link[0] = &link0, .nb_inputs = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko Acked-by: Ori Kam --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_flow.c | 55 ++ lib/ethdev/rte_flow.h | 225 + lib/ethdev/rte_flow_driver.h | 8 + lib/ethdev/version.map | 2 + 6 files changed, 322 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index fa05fe0845..aeba374182 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1548,6 +1548,31 @@ This item is meant to use the same structure as `Item: PORT_REPRESENTOR`_. See also `Action: REPRESENTED_PORT`_. +Item: ``FLEX`` +^^ + +Matches with the custom network protocol header that was created +using rte_flow_flex_item_create() API. The application describes +the desired header structure, defines the header fields attributes +and header relations with preceding and following protocols and +configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configurat
[dpdk-dev] [PATCH v8 3/4] app/testpmd: add dedicated flow command parsing routine
From: Gregory Etelson testpmd flow creation is constructed from these procedures: 1. receive string with flow rule description; 2. parse input string and build flow parameters: port_id value, flow attributes, items array, actions array; 3. create a flow rule from flow rule parameters. Flow rule creation procedures are built as a pipeline. A new procedure starts immediately after successful predecessor completion. Due to this we have no dedicated routines providing intermediate results for step 1-3 above. The patch adds `flow_parse()` function call. It parses input string and provides a caller with parsed data. This is a preparation step for introducing flex item command processing. Signed-off-by: Gregory Etelson Reviewed-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 24 app/test-pmd/testpmd.h | 5 + 2 files changed, 29 insertions(+) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index a90822b660..cd640b9b7a 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -8076,6 +8076,30 @@ cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, return len; } +int +flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, struct rte_flow_action **actions) +{ + int ret; + struct context saved_flow_ctx = cmd_flow_context; + + cmd_flow_context_init(&cmd_flow_context); + do { + ret = cmd_flow_parse(NULL, src, result, size); + if (ret > 0) { + src += ret; + while (isspace(*src)) + src++; + } + } while (ret > 0 && strlen(src)); + cmd_flow_context = saved_flow_ctx; + *attr = &((struct buffer *)result)->args.vc.attr; + *pattern = ((struct buffer *)result)->args.vc.pattern; + *actions = ((struct buffer *)result)->args.vc.actions; + return (ret >= 0 && !strlen(src)) ? 0 : -1; +} + /** Return number of completion entries (cmdline API). */ static int cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index dd8f27a296..81be754605 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1047,6 +1047,11 @@ void add_tx_dynf_callback(portid_t portid); void remove_tx_dynf_callback(portid_t portid); int update_mtu_from_frame_size(portid_t portid, uint32_t max_rx_pktlen); +extern int flow_parse(const char *src, void *result, unsigned int size, + struct rte_flow_attr **attr, + struct rte_flow_item **pattern, + struct rte_flow_action **actions); + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. -- 2.18.1
[dpdk-dev] [RFC 3/3] app/testpmd: fix hex string parser in flow commands
The hexadecimal string parser does not check the target field buffer size, buffer overflow happens and might cause the application failure (segmentation fault is observed usually). Fixes: 169a9fed1f4c ("app/testpmd: fix hex string parser support for flow API") Cc: sta...@dpdk.org Signed-off-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 529ead6b2a..9e7fe1ae9f 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -7291,10 +7291,13 @@ parse_hex(struct context *ctx, const struct token *token, hexlen -= 2; } if (hexlen > length) - return -1; + goto error; ret = parse_hex_string(str, hex_tmp, &hexlen); if (ret < 0) goto error; + /* Check the converted binary fits into data buffer. */ + if (hexlen > size) + goto error; /* Let parse_int() fill length information first. */ ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); if (ret < 0) -- 2.18.1
[dpdk-dev] [RFC 2/3] app/testpmd: update modify field flow action support
The testpmd flow create command updates provided: - modify field action supports the updated actions - pointer type added for action source field - pointer and value source field takes hex string instead of unsigned int in host endianness There are some examples of flow with update modified field action: 1. IPv6 destination address bytes 4-7 assignment: :: - > ::4455:6677:: flow create 0 egress group 1 pattern eth / ipv6 dst is :: / udp / end actions modify_field op set dst_type ipv6_dst dst_offset 32 src_type value src_value 0011223344556677 width 32 / end 2. Copy second byte of IPv4 destination address to the third byte of source address: 10.0.118.4 -> 192.168.100.1 10.0.168.4 -> 192.168.100.1 flow create 0 egress group 1 pattern eth / ipv4 / udp / end actions modify_field op set dst_type ipv4_src dst_offset 16 src_type ipv4_dst src_offset 8 width 8 / end 3. Assign METADATA value with 11223344 value from the hex string in the linear buffer. Please note, the value definition should follow host-endian, example is given for x86 (little-endian): flow create 0 egress group 1 pattern eth / ipv4 / end actions modify_field op set dst_type meta src_type pointer src_ptr 44332211 width 32 / end 4. Assign destination MAC with EA:11:0B:AD:0B:ED value: flow create 0 egress group 1 pattern eth / end actions modify_field op set dst_type mac_dst src_type value src_value EA110BAD0BED width 48 / end Signed-off-by: Viacheslav Ovsiienko --- app/test-pmd/cmdline_flow.c | 55 + 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 6cd99bf37f..529ead6b2a 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -448,6 +448,7 @@ enum index { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ACTION_CONNTRACK, ACTION_CONNTRACK_UPDATE, @@ -468,6 +469,14 @@ enum index { #define ITEM_RAW_SIZE \ (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) +/** Maximum size for external pattern in struct rte_flow_action_modify_data. */ +#define ACTION_MODIFY_PATTERN_SIZE 32 + +/** Storage size for struct rte_flow_action_modify_field including pattern. */ +#define ACTION_MODIFY_SIZE \ + (sizeof(struct rte_flow_action_modify_field) + \ + ACTION_MODIFY_PATTERN_SIZE) + /** Maximum number of queue indices in struct rte_flow_action_rss. */ #define ACTION_RSS_QUEUE_NUM 128 @@ -1704,6 +1713,7 @@ static const enum index action_modify_field_src[] = { ACTION_MODIFY_FIELD_SRC_LEVEL, ACTION_MODIFY_FIELD_SRC_OFFSET, ACTION_MODIFY_FIELD_SRC_VALUE, + ACTION_MODIFY_FIELD_SRC_POINTER, ACTION_MODIFY_FIELD_WIDTH, ZERO, }; @@ -4455,8 +4465,7 @@ static const struct token token_list[] = { [ACTION_MODIFY_FIELD] = { .name = "modify_field", .help = "modify destination field with data from source field", - .priv = PRIV_ACTION(MODIFY_FIELD, - sizeof(struct rte_flow_action_modify_field)), + .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), .call = parse_vc, }, @@ -4539,11 +4548,26 @@ static const struct token token_list[] = { .name = "src_value", .help = "source immediate value", .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), - NEXT_ENTRY(COMMON_UNSIGNED)), - .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY_ARB(0, 0), +ARGS_ENTRY(struct rte_flow_action_modify_field, src.value)), .call = parse_vc_conf, }, + [ACTION_MODIFY_FIELD_SRC_POINTER] = { + .name = "src_ptr", + .help = "pointer to source immediate value", + .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), +NEXT_ENTRY(COMMON_HEX)), + .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, + src.pvalue), +ARGS_ENTRY_ARB(0, 0), +
[dpdk-dev] [RFC 1/3] ethdev: update modify field flow action
The generic modify field flow action introduced in [1] has some issues related to the immediate source operand: - immediate source can be presented either as an unsigned 64-bit integer or pointer to data pattern in memory. There was no explicit pointer field defined in the union - the byte ordering for 64-bit integer was not specified. Many fields have lesser lengths and byte ordering is crucial. - how the bit offset is applied to the immediate source field was not defined and documented - 64-bit integer size is not enough to provide MAC and IPv6 addresses In order to cover the issues and exclude any ambiguities the following is done: - introduce the explicit pointer field in rte_flow_action_modify_data structure - replace the 64-bit unsigned integer with 16-byte array - update the modify field flow action documentation [1] commit 73b68f4c54a0 ("ethdev: introduce generic modify flow action") Signed-off-by: Viacheslav Ovsiienko --- doc/guides/prog_guide/rte_flow.rst | 8 doc/guides/rel_notes/release_21_11.rst | 7 +++ lib/ethdev/rte_flow.h | 15 --- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..a54760a7b4 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -2835,6 +2835,14 @@ a packet to any other part of it. ``value`` sets an immediate value to be used as a source or points to a location of the value in memory. It is used instead of ``level`` and ``offset`` for ``RTE_FLOW_FIELD_VALUE`` and ``RTE_FLOW_FIELD_POINTER`` respectively. +The data in memory should be presented exactly in the same byte order and +length as in the relevant flow item, i.e. data for field with type +RTE_FLOW_FIELD_MAC_DST should follow the conventions of dst field +in rte_flow_item_eth structure, with type RTE_FLOW_FIELD_IPV6_SRC - +rte_flow_item_ipv6 conventions, and so on. The bitfield exatracted from the +memory being applied as second operation parameter is defined by width and +the destination field offset. If the field size is large than 16 bytes the +pattern can be provided as pointer only. .. _table_rte_flow_action_modify_field: diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index d707a554ef..fdeba27e14 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -84,6 +84,10 @@ API Changes Also, make sure to start the actual text at the margin. === +* ethdev: ``rte_flow_action_modify_data`` structure udpdated, immediate data + array is extended, data pointer field is explicitly added to union, the + action behavior is defined in more strict fashion and documentation uddated. + ABI Changes --- @@ -101,6 +105,9 @@ ABI Changes === +* ethdev: ``rte_flow_action_modify_data`` structure udpdated. + + Known Issues diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 70f455d47d..50e6f34579 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -3204,6 +3204,9 @@ enum rte_flow_field_id { }; /** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * * Field description for MODIFY_FIELD action. */ struct rte_flow_action_modify_data { @@ -3217,10 +3220,16 @@ struct rte_flow_action_modify_data { uint32_t offset; }; /** -* Immediate value for RTE_FLOW_FIELD_VALUE or -* memory address for RTE_FLOW_FIELD_POINTER. +* Immediate value for RTE_FLOW_FIELD_VALUE, presented in the +* same byte order and length as in relevant rte_flow_item_xxx. */ - uint64_t value; + uint8_t value[16]; + /* +* Memory address for RTE_FLOW_FIELD_POINTER, memory layout +* should be the same as for relevant field in the +* rte_flow_item_xxx structure. +*/ + void *pvalue; }; }; -- 2.18.1
[dpdk-dev] [PATCH 0/3] ethdev: introduce configurable flexible item
ous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items should not overlap (be unique per field). For this case, the driver will try to engage not overlapping hardware resources and provide independent handling of the fields with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* header length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* Skip three dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .sample_num = 2, .input_link[0] = &link0, .input_num = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; 7. Notes: - testpmd and mlx5 PMD parts are coming soon - RFC: http://patches.dpdk.org/project/dpdk/patch/20210806085624.16497-1-viachesl...@nvidia.com/ Gregory Etelson (2): ethdev: support flow elements with variable length ethdev: implement RTE flex item API Viacheslav Ovsiienko (1): ethdev: introduce configurable flexible item doc/guides/prog_guide/rte_flow.rst | 24 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_ethdev.h| 1 + lib/ethdev/rte_flow.c | 141 +-- lib/ethdev/rte_flow.h | 228 + lib/ethdev/rte_flow_driver.h | 13 ++ lib/ethdev/version.map | 5 + 7 files changed, 406 insertions(+), 13 deletions(-) -- 2.18.1
[dpdk-dev] [PATCH 2/3] ethdev: support flow elements with variable length
From: Gregory Etelson RTE flow API provides RAW item type for packet patterns of variable length. The RAW item structure has fixed size members that describe the variable pattern length and methods to process it. A new RTE flow item type with variable length pattern that does not fit the RAW item meta description could not use the RAW item. For example, the new flow item that references 64 bits PMD handler cannot be described by the RAW item. The patch allows RTE conv helper functions to process custom flow items with variable length pattern. Signed-off-by: Gregory Etelson --- lib/ethdev/rte_flow.c | 68 ++- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..fe199eaeb3 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -30,13 +30,54 @@ uint64_t rte_flow_dynf_metadata_mask; struct rte_flow_desc_data { const char *name; size_t size; + size_t (*desc_fn)(void *dst, const void *src); }; +/** + * + * @param buf + * Destination memory. + * @param data + * Source memory + * @param size + * Requested copy size + * @param desc + * rte_flow_desc_item - for flow item conversion. + * rte_flow_desc_action - for flow action conversion. + * @param type + * Offset into the desc param or negative value for private flow elements. + */ +static inline size_t +rte_flow_conv_copy(void *buf, const void *data, const size_t size, + const struct rte_flow_desc_data *desc, int type) +{ + /** +* allow PMD private flow item +* see 5d1bff8fe2 +* "ethdev: allow negative values in flow rule types" +*/ + size_t sz = type >= 0 ? desc[type].size : sizeof(void *); + if (buf == NULL || data == NULL) + return 0; + rte_memcpy(buf, data, (size > sz ? sz : size)); + if (desc[type].desc_fn) + sz += desc[type].desc_fn(size > 0 ? buf : NULL, data); + return sz; +} + /** Generate flow_item[] entry. */ #define MK_FLOW_ITEM(t, s) \ [RTE_FLOW_ITEM_TYPE_ ## t] = { \ .name = # t, \ - .size = s, \ + .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ITEM_FN(t, s, fn) \ + [RTE_FLOW_ITEM_TYPE_ ## t] = {\ + .name = # t, \ + .size = s, \ + .desc_fn = fn, \ } /** Information about known flow pattern items. */ @@ -107,8 +148,17 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { [RTE_FLOW_ACTION_TYPE_ ## t] = { \ .name = # t, \ .size = s, \ + .desc_fn = NULL,\ + } + +#define MK_FLOW_ACTION_FN(t, fn) \ + [RTE_FLOW_ACTION_TYPE_ ## t] = { \ + .name = # t, \ + .size = 0, \ + .desc_fn = fn,\ } + /** Information about known flow actions. */ static const struct rte_flow_desc_data rte_flow_desc_action[] = { MK_FLOW_ACTION(END, 0), @@ -527,12 +577,8 @@ rte_flow_conv_item_spec(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow item -*/ - off = (int)item->type >= 0 ? - rte_flow_desc_item[item->type].size : sizeof(void *); - rte_memcpy(buf, data, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, data, size, +rte_flow_desc_item, item->type); break; } return off; @@ -634,12 +680,8 @@ rte_flow_conv_action_conf(void *buf, const size_t size, } break; default: - /** -* allow PMD private flow action -*/ - off = (int)action->type >= 0 ? - rte_flow_desc_action[action->type].size : sizeof(void *); - rte_memcpy(buf, action->conf, (size > off ? off : size)); + off = rte_flow_conv_copy(buf, action->conf, size, +rte_flow_desc_action, action->type); break; } return off; -- 2.18.1
[dpdk-dev] [PATCH 1/3] ethdev: introduce configurable flexible item
ous usage. The fields of items should be assigned with hint indices and these indices from two or more flex items should not overlap (be unique per field). For this case, the driver will try to engage not overlapping hardware resources and provide independent handling of the fields with unique indices. If the hint index is zero the driver assigns resources on its own. 6. Example of New Protocol Handling Let's suppose we have the requirements to handle the new tunnel protocol that follows UDP header with destination port 0xFADE and is followed by MAC header. Let the new protocol header format be like this: struct new_protocol_header { rte_be32 header_length; /* length in dwords, including options */ rte_be32 specific0; /* some protocol data, no intention */ rte_be32 specific1; /* to match in flows on these fields */ rte_be32 crucial; /* data of interest, match is needed */ rte_be32 options[0];/* optional protocol data, variable length */ }; The supposed flex item configuration: struct rte_flow_item_flex_field field0 = { .field_mode = FIELD_MODE_DUMMY, /* Affects match pattern only */ .field_size = 96,/* 3 dwords from the beginning */ }; struct rte_flow_item_flex_field field1 = { .field_mode = FIELD_MODE_FIXED, .field_size = 32, /* Field size is one dword */ .field_base = 96, /* Skip three dwords from the beginning */ }; struct rte_flow_item_udp spec0 = { .hdr = { .dst_port = RTE_BE16(0xFADE), } }; struct rte_flow_item_udp mask0 = { .hdr = { .dst_port = RTE_BE16(0x), } }; struct rte_flow_item_flex_link link0 = { .item = { .type = RTE_FLOW_ITEM_TYPE_UDP, .spec = &spec0, .mask = &mask0, }; struct rte_flow_item_flex_conf conf = { .next_header = { .field_mode = FIELD_MODE_OFFSET, .field_base = 0, .offset_base = 0, .offset_mask = 0x, .offset_shift = 2/* Expressed in dwords, shift left by 2 */ }, .sample = { &field0, &field1, }, .sample_num = 2, .input_link[0] = &link0, .input_num = 1 }; Let's suppose we have created the flex item successfully, and PMD returned the handle 0x123456789A. We can use the following item pattern to match the crucial field in the packet with value 0x00112233: struct new_protocol_header spec_pattern = { .crucial = RTE_BE32(0x00112233), }; struct new_protocol_header mask_pattern = { .crucial = RTE_BE32(0x), }; struct rte_flow_item_flex spec_flex = { .handle = 0x123456789A .length = sizeiof(struct new_protocol_header), .pattern = &spec_pattern, }; struct rte_flow_item_flex mask_flex = { .length = sizeof(struct new_protocol_header), .pattern = &mask_pattern, }; struct rte_flow_item item_to_match = { .type = RTE_FLOW_ITEM_TYPE_FLEX, .spec = &spec_flex, .mask = &mask_flex, }; Signed-off-by: Viacheslav Ovsiienko --- doc/guides/prog_guide/rte_flow.rst | 24 +++ doc/guides/rel_notes/release_21_11.rst | 7 + lib/ethdev/rte_ethdev.h| 1 + lib/ethdev/rte_flow.h | 228 + 4 files changed, 260 insertions(+) diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 2b42d5ec8c..628f30cea7 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,30 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``FLEX`` +^ + +Matches with the network protocol header of preliminary configured format. +The application describes the desired header structure, defines the header +fields attributes and header relations with preceding and following +protocols and configures the ethernet devices accordingly via +rte_flow_flex_item_create() routine. + +- ``handle``: the flex item handle returned by the PMD on successful + rte_flow_flex_item_create() call. The item handle is unique within + the device port, mask for this field is ignored. +- ``length``: match pattern length in bytes. If the length does not cover + all fields defined in item configuration, the pattern spec and mask are + supposed to be appended with zeroes till the full configured item length. +- ``pattern``: pattern to match. The protocol header fields are considered + as bit fields, all offsets and widths are expressed in bits. The pattern + is the buffer containing the bit concatenation of all the fields presented + at item configuration time, in the same order and same amount. The most + regular way is to define all the header fields in the flex item configuration + and directly use the header structure as pattern template, i.e. application + just can fill the header structures with desired
[dpdk-dev] [PATCH 3/3] ethdev: implement RTE flex item API
From: Gregory Etelson RTE flex item API was introduced in "ethdev: introduce configurable flexible item" patch. The API allows DPDK application to define parser for custom network header in port hardware and offload flows that will match the custom header elements. Signed-off-by: Gregory Etelson --- lib/ethdev/rte_flow.c| 73 lib/ethdev/rte_flow_driver.h | 13 +++ lib/ethdev/version.map | 5 +++ 3 files changed, 91 insertions(+) diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index fe199eaeb3..74f74d6009 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -80,6 +80,19 @@ rte_flow_conv_copy(void *buf, const void *data, const size_t size, .desc_fn = fn, \ } +static size_t +rte_flow_item_flex_conv(void *buf, const void *data) +{ + struct rte_flow_item_flex *dst = buf; + const struct rte_flow_item_flex *src = data; + if (buf) { + dst->pattern = rte_memcpy + ((void *)((uintptr_t)(dst + 1)), src->pattern, +src->length); + } + return src->length; +} + /** Information about known flow pattern items. */ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(END, 0), @@ -141,6 +154,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM_FN(FLEX, sizeof(struct rte_flow_item_flex), + rte_flow_item_flex_conv), }; /** Generate flow_action[] entry. */ @@ -1308,3 +1323,61 @@ rte_flow_tunnel_item_release(uint16_t port_id, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, rte_strerror(ENOTSUP)); } + +struct rte_flow_item_flex_handle * +rte_flow_flex_item_create(uint16_t port_id, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + struct rte_flow_item_flex_handle *handle; + + if (unlikely(!ops)) + return NULL; + if (unlikely(!ops->flex_item_create)) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + return NULL; + } + handle = ops->flex_item_create(dev, conf, error); + if (handle == NULL) + flow_err(port_id, -rte_errno, error); + return handle; +} + +int +rte_flow_flex_item_release(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_release)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_release(dev, handle, error); + return flow_err(port_id, ret, error); +} + +int +rte_flow_flex_item_update(uint16_t port_id, + const struct rte_flow_item_flex_handle *handle, + const struct rte_flow_item_flex_conf *conf, + struct rte_flow_error *error) +{ + int ret; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); + + if (unlikely(!ops || !ops->flex_item_update)) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, rte_strerror(ENOTSUP)); + ret = ops->flex_item_update(dev, handle, conf, error); + return flow_err(port_id, ret, error); +} diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h index 46f62c2ec2..aed2ac03ad 100644 --- a/lib/ethdev/rte_flow_driver.h +++ b/lib/ethdev/rte_flow_driver.h @@ -139,6 +139,19 @@ struct rte_flow_ops { struct rte_flow_item *pmd_items, uint32_t num_of_items, struct rte_flow_error *err); + struct rte_flow_item_flex_handle *(*flex_item_create) + (struct rte_eth_dev *dev, +const struct rte_flow_item_flex_conf *conf, +struct rte_flow_error *error); + int (*flex_item_release) + (struct rte_eth_dev *d