[PATCH 1/9] ethdev: sharing indirect actions between ports

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2023-02-06 Thread Viacheslav Ovsiienko
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

2021-04-17 Thread Viacheslav Ovsiienko
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

2021-04-21 Thread Viacheslav Ovsiienko
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

2021-04-28 Thread Viacheslav Ovsiienko
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

2021-04-28 Thread Viacheslav Ovsiienko
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.

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-04-29 Thread Viacheslav Ovsiienko
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

2021-06-19 Thread Viacheslav Ovsiienko
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

2021-06-19 Thread Viacheslav Ovsiienko
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

2021-06-19 Thread Viacheslav Ovsiienko
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

2021-06-19 Thread Viacheslav Ovsiienko
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

2021-06-22 Thread Viacheslav Ovsiienko
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

2021-07-01 Thread Viacheslav Ovsiienko
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

2021-07-01 Thread Viacheslav Ovsiienko
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

2021-07-01 Thread Viacheslav Ovsiienko
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

2021-07-07 Thread Viacheslav Ovsiienko
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

2021-07-07 Thread Viacheslav Ovsiienko
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

2021-04-05 Thread Viacheslav Ovsiienko
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

2021-04-05 Thread Viacheslav Ovsiienko
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

2021-04-07 Thread Viacheslav Ovsiienko
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

2022-02-03 Thread Viacheslav Ovsiienko
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

2022-02-03 Thread Viacheslav Ovsiienko
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

2022-02-14 Thread Viacheslav Ovsiienko
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

2022-02-14 Thread Viacheslav Ovsiienko
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

2022-02-14 Thread Viacheslav Ovsiienko
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

2022-02-14 Thread Viacheslav Ovsiienko
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

2022-02-14 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-11 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-12 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-13 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-18 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
 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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
 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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-10-20 Thread Viacheslav Ovsiienko
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

2021-09-10 Thread Viacheslav Ovsiienko
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

2021-09-10 Thread Viacheslav Ovsiienko
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

2021-09-10 Thread Viacheslav Ovsiienko
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

2021-09-22 Thread Viacheslav Ovsiienko
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

2021-09-22 Thread Viacheslav Ovsiienko
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

2021-09-22 Thread Viacheslav Ovsiienko
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

2021-09-22 Thread Viacheslav Ovsiienko
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

  1   2   3   4   5   6   7   8   9   10   >