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

