Add xstats support with three per-QP counters: enqueued, dequeued,
and matches. Implement xstats_names_get, xstats_get, and
xstats_reset with support for bulk and selective reset by stat id.

Signed-off-by: Prudvi Deti <[email protected]>
---
 doc/guides/regexdevs/hs.rst |   9 ++
 drivers/regex/hs/hs_regex.c | 159 ++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/doc/guides/regexdevs/hs.rst b/doc/guides/regexdevs/hs.rst
index e94466a..9c5f666 100644
--- a/doc/guides/regexdevs/hs.rst
+++ b/doc/guides/regexdevs/hs.rst
@@ -20,7 +20,16 @@ Features
 - Up to 64 queue pairs, each with up to 32768 descriptors
 - Up to 1,000,000 rules per device, with O(1) duplicate rule_id
   detection backed by ``rte_hash``
+- Up to 65,535 matches per scan operation (API field width limit);
+  cumulative totals are tracked via per-queue-pair xstats
 - Per-rule extended match parameters (minimum/maximum start offset)
+- Hyperscan block-mode engine supports scan buffers up to 4 GB
+  (library capability)
+- Through the current ``rte_regexdev`` API, this PMD advertises
+  ``max_payload_size = 65,535`` bytes (``uint16_t`` field width), so
+  ``dpdk-test-regex`` validation is limited to about 64 KB per op
+- Hyperscan uses x86 vectorized instructions (SSSE3/AVX2/AVX-512)
+  for high throughput
 - Per-queue-pair statistics via xstats
 
 In the RegEx driver feature matrix, this PMD reports:
diff --git a/drivers/regex/hs/hs_regex.c b/drivers/regex/hs/hs_regex.c
index e84259e..7841a83 100644
--- a/drivers/regex/hs/hs_regex.c
+++ b/drivers/regex/hs/hs_regex.c
@@ -849,6 +849,161 @@ hs_regex_dequeue_burst(struct rte_regexdev *dev, uint16_t 
qp_id,
        return i;
 }
 
+/* xstats: per-QP statistics */
+
+/* 3 stats per QP: enqueued, dequeued, matches */
+#define HS_XSTATS_PER_QP 3
+
+static const char * const hs_xstat_suffixes[HS_XSTATS_PER_QP] = {
+       "enqueued", "dequeued", "matches"
+};
+
+static int
+hs_regex_xstats_names_get(struct rte_regexdev *dev,
+                         struct rte_regexdev_xstats_map *xstats_map)
+{
+       struct hs_regex_priv *priv;
+       uint16_t nqp;
+       int total;
+       int idx = 0;
+       uint16_t q;
+       int s;
+
+       if (dev == NULL)
+               return -EINVAL;
+
+       priv = dev->data->dev_private;
+       if (priv == NULL)
+               return -EINVAL;
+
+       nqp = priv->nb_queue_pairs;
+       total = nqp * HS_XSTATS_PER_QP;
+
+       if (!xstats_map)
+               return total;
+
+       for (q = 0; q < nqp; q++) {
+               for (s = 0; s < HS_XSTATS_PER_QP; s++) {
+                       snprintf(xstats_map[idx].name,
+                                sizeof(xstats_map[idx].name),
+                                "qp%u_%s", q, hs_xstat_suffixes[s]);
+                       xstats_map[idx].id = idx;
+                       idx++;
+               }
+       }
+       return total;
+}
+
+static int
+hs_regex_xstats_get(struct rte_regexdev *dev,
+                   const uint16_t *ids, uint64_t *values,
+                   uint16_t nb_values)
+{
+       struct hs_regex_priv *priv;
+       uint16_t nqp;
+       int total;
+       uint16_t id, qp_idx, stat_idx;
+       uint16_t i;
+
+       if (dev == NULL)
+               return -EINVAL;
+
+       priv = dev->data->dev_private;
+       if (priv == NULL)
+               return -EINVAL;
+
+       nqp = priv->nb_queue_pairs;
+       total = nqp * HS_XSTATS_PER_QP;
+
+       if (!ids || !values)
+               return total;
+
+       if (priv->qps == NULL)
+               total = 0;
+
+       for (i = 0; i < nb_values; i++) {
+               id = ids[i];
+
+               if (id >= (uint16_t)total) {
+                       values[i] = 0;
+                       continue;
+               }
+
+               qp_idx = id / HS_XSTATS_PER_QP;
+               stat_idx = id % HS_XSTATS_PER_QP;
+
+               switch (stat_idx) {
+               case 0:
+                       values[i] = priv->qps[qp_idx].qp_enqueued;
+                       break;
+               case 1:
+                       values[i] = priv->qps[qp_idx].qp_dequeued;
+                       break;
+               case 2:
+                       values[i] = priv->qps[qp_idx].qp_matches;
+                       break;
+               }
+       }
+       return nb_values;
+}
+
+static int
+hs_regex_xstats_reset(struct rte_regexdev *dev,
+                     const uint16_t *ids, uint16_t nb_ids)
+{
+       struct hs_regex_priv *priv;
+       uint16_t nqp;
+       int total;
+       uint16_t q, i;
+       uint16_t id, qp_idx, stat_idx;
+
+       if (dev == NULL)
+               return -EINVAL;
+
+       priv = dev->data->dev_private;
+       if (priv == NULL)
+               return -EINVAL;
+
+       nqp = priv->nb_queue_pairs;
+       total = nqp * HS_XSTATS_PER_QP;
+
+       if (priv->qps == NULL)
+               return 0;
+
+       if (!ids || nb_ids == 0) {
+               /* Reset all stats */
+               for (q = 0; q < nqp; q++) {
+                       priv->qps[q].qp_enqueued = 0;
+                       priv->qps[q].qp_dequeued = 0;
+                       priv->qps[q].qp_matches = 0;
+               }
+       } else {
+               /* Reset specific stats by id */
+               for (i = 0; i < nb_ids; i++) {
+                       id = ids[i];
+
+                       if (id >= (uint16_t)total)
+                               continue;
+
+                       qp_idx = id / HS_XSTATS_PER_QP;
+                       stat_idx = id % HS_XSTATS_PER_QP;
+
+                       switch (stat_idx) {
+                       case 0:
+                               priv->qps[qp_idx].qp_enqueued = 0;
+                               break;
+                       case 1:
+                               priv->qps[qp_idx].qp_dequeued = 0;
+                               break;
+                       case 2:
+                               priv->qps[qp_idx].qp_matches = 0;
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
 /* Operations table */
 static const struct rte_regexdev_ops hs_regexdev_ops = {
        .dev_info_get = hs_regex_info_get,
@@ -858,6 +1013,10 @@ static const struct rte_regexdev_ops hs_regexdev_ops = {
        .dev_rule_db_compile_activate = hs_regex_rule_db_compile_activate,
        .dev_db_import = hs_regex_rule_db_import,
        .dev_db_export = hs_regex_rule_db_export,
+       .dev_xstats_names_get = hs_regex_xstats_names_get,
+       .dev_xstats_get = hs_regex_xstats_get,
+       .dev_xstats_by_name_get = NULL,
+       .dev_xstats_reset = hs_regex_xstats_reset,
 };
 
 /* Device Lifecycle */
-- 
2.43.0

Reply via email to