Add a new software regex Poll Mode Driver based on Intel Hyperscan. This patch provides the minimal vdev skeleton: probe, remove, device registration, and info_get.
Build is gated by meson dependency check on libhs via pkg-config. Only supported on 64-bit platforms. Includes documentation, MAINTAINERS entry, feature matrix, and release notes. Signed-off-by: Prudvi Deti <[email protected]> --- .mailmap | 1 + MAINTAINERS | 6 + doc/guides/regexdevs/features/hs.ini | 8 ++ doc/guides/regexdevs/hs.rst | 143 +++++++++++++++++++ doc/guides/regexdevs/index.rst | 1 + doc/guides/rel_notes/release_26_11.rst | 7 + drivers/regex/hs/hs_regex.c | 186 +++++++++++++++++++++++++ drivers/regex/hs/hs_regex.h | 69 +++++++++ drivers/regex/hs/meson.build | 19 +++ drivers/regex/meson.build | 1 + 10 files changed, 441 insertions(+) create mode 100644 doc/guides/regexdevs/features/hs.ini create mode 100644 doc/guides/regexdevs/hs.rst create mode 100644 drivers/regex/hs/hs_regex.c create mode 100644 drivers/regex/hs/hs_regex.h create mode 100644 drivers/regex/hs/meson.build diff --git a/.mailmap b/.mailmap index fcb3d1b..8a8a6e4 100644 --- a/.mailmap +++ b/.mailmap @@ -1336,6 +1336,7 @@ Pravin Pathak <[email protected]> <[email protected]> Prince Takkar <[email protected]> Priyalee Kushwaha <[email protected]> Priyanka Jain <[email protected]> +Prudvi Deti <[email protected]> Przemek Kitszel <[email protected]> Przemyslaw Ciesielski <[email protected]> Przemyslaw Czesnowicz <[email protected]> diff --git a/MAINTAINERS b/MAINTAINERS index e99a65d..e29af50 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1433,6 +1433,12 @@ F: drivers/regex/cn9k/ F: doc/guides/regexdevs/cn9k.rst F: doc/guides/regexdevs/features/cn9k.ini +Intel Hyperscan +M: Prudvi Deti <[email protected]> +F: drivers/regex/hs/ +F: doc/guides/regexdevs/hs.rst +F: doc/guides/regexdevs/features/hs.ini + NVIDIA mlx5 M: Ori Kam <[email protected]> F: drivers/regex/mlx5/ diff --git a/doc/guides/regexdevs/features/hs.ini b/doc/guides/regexdevs/features/hs.ini new file mode 100644 index 0000000..58cf4a2 --- /dev/null +++ b/doc/guides/regexdevs/features/hs.ini @@ -0,0 +1,8 @@ +; +; Supported features of the 'hs' RegEx driver. +; +; Refer to default.ini for the full list of available driver features. +; +[Features] +Run time compilation = Y +x86 = Y diff --git a/doc/guides/regexdevs/hs.rst b/doc/guides/regexdevs/hs.rst new file mode 100644 index 0000000..e94466a --- /dev/null +++ b/doc/guides/regexdevs/hs.rst @@ -0,0 +1,143 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2026 Intel Corporation + +Hyperscan RegEx PMD +=================== + +The Hyperscan RegEx PMD (**librte_regex_hs**) provides a poll mode +regexdev driver backed by Intel's +`Hyperscan <https://github.com/intel/hyperscan>`_ regular expression +library. It is a software-only virtual device (vdev) PMD that +implements the ``rte_regexdev`` API using Hyperscan block mode scanning. + +Features +-------- + +- Software-only virtual device (no hardware dependency) +- Runtime pattern compilation via ``hs_compile_ext_multi()`` +- Serialized database import/export +- Per-queue-pair scratch space for lock-free parallel scanning +- 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`` +- Per-rule extended match parameters (minimum/maximum start offset) +- Per-queue-pair statistics via xstats + +In the RegEx driver feature matrix, this PMD reports: + +- ``Run time compilation`` +- ``x86`` + +Supported Regex Rule Flags (Hyperscan Mapping) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Standard DPDK flags (advertised via ``info->rule_flags``): + +- ``RTE_REGEX_PCRE_RULE_ALLOW_EMPTY_F`` (maps to ``HS_FLAG_ALLOWEMPTY``) +- ``RTE_REGEX_PCRE_RULE_CASELESS_F`` (maps to ``HS_FLAG_CASELESS``) +- ``RTE_REGEX_PCRE_RULE_DOTALL_F`` (maps to ``HS_FLAG_DOTALL``) +- ``RTE_REGEX_PCRE_RULE_MULTILINE_F`` (maps to ``HS_FLAG_MULTILINE``) +- ``RTE_REGEX_PCRE_RULE_UCP_F`` (maps to ``HS_FLAG_UCP``) +- ``RTE_REGEX_PCRE_RULE_UTF_F`` (maps to ``HS_FLAG_UTF8``) + +PMD-private flags (accepted in ``rule_flags`` but not advertised; +defined in ``drivers/regex/hs/hs_regex.h``): + +- ``HS_REGEX_RULE_SINGLEMATCH_F`` (bit 32, maps to ``HS_FLAG_SINGLEMATCH``) +- ``HS_REGEX_RULE_PREFILTER_F`` (bit 33, maps to ``HS_FLAG_PREFILTER``) +- ``HS_REGEX_RULE_SOM_LEFTMOST_F`` (bit 34, maps to ``HS_FLAG_SOM_LEFTMOST``) +- ``HS_REGEX_RULE_COMBINATION_F`` (bit 35, maps to ``HS_FLAG_COMBINATION``) +- ``HS_REGEX_RULE_QUIET_F`` (bit 36, maps to ``HS_FLAG_QUIET``) + +Unknown flag bits are rejected with an error during ``rule_db_update``. + +Extended Match Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Per-rule minimum and maximum start offset constraints (Hyperscan +``hs_expr_ext_t``) can be encoded in the upper bits of ``rule_flags``: + +- Bits 37-49 (13 bits, mask ``0x1FFF``): maximum start offset, + mapped to ``HS_EXT_FLAG_MAX_OFFSET``. +- Bits 50-63 (14 bits, mask ``0x3FFF``): minimum start offset, + mapped to ``HS_EXT_FLAG_MIN_OFFSET``. + +A value of 0 leaves the corresponding constraint disabled. These +constraints are applied via ``hs_compile_ext_multi()`` during +``rule_db_compile_activate``. + +Prerequisites +------------- + +The Hyperscan library must be installed and discoverable via +``pkg-config``. On Ubuntu/Debian:: + + sudo apt install libhyperscan-dev + +On Fedora/RHEL:: + + sudo dnf install hyperscan-devel + +The PMD is built automatically when ``libhs`` is found by the meson +build system. It is only supported on 64-bit platforms. + +Device Setup +------------ + +The Hyperscan PMD is a virtual device. Create it with the EAL +``--vdev`` option:: + + dpdk-app --vdev regex_hs -- ... + +Or programmatically with ``rte_vdev_init()``:: + + rte_vdev_init("regex_hs", NULL); + +Device Lifecycle +~~~~~~~~~~~~~~~~ + +.. code-block:: c + + rte_regexdev_configure(dev, &cfg); + rte_regexdev_queue_pair_setup(dev, qp_id, &qp_conf); + rte_regexdev_rule_db_update(dev, rules, nb_rules); + rte_regexdev_rule_db_compile_activate(dev); + rte_regexdev_start(dev); + + /* data path */ + rte_regexdev_enqueue_burst(dev, qp, ops, n); + rte_regexdev_dequeue_burst(dev, qp, results, n); + + rte_regexdev_stop(dev); + rte_regexdev_close(dev); + +Alternatively, a pre-compiled serialized database can be loaded +during ``rte_regexdev_configure()`` via ``cfg.rule_db`` and +``cfg.rule_db_len``, or at any time via ``rte_regexdev_rule_db_import()``. + +Statistics +~~~~~~~~~~ + +Extended statistics are reported per queue pair, with names of the +form ``qp<N>_enqueued``, ``qp<N>_dequeued``, and ``qp<N>_matches``. +All counters can be reset in bulk or selectively by stat id via +``rte_regexdev_xstats_reset()``. + +Limitations +----------- + +- Scanning is synchronous: ``enqueue_burst`` blocks until + ``hs_scan()`` completes for each operation. +- Multi-segment mbufs are linearized (``rte_pktmbuf_linearize()``) + before scanning; linearization failure marks the op with + ``RTE_REGEX_OPS_RSP_RESOURCE_LIMIT_REACHED_F``. +- Multi-process mode is not supported. +- Each queue pair must be used by exactly one lcore + (single-producer/single-consumer model). + +Debugging Options +----------------- + +Enable PMD debug logging with:: + + --log-level='pmd.regex.hs,8' diff --git a/doc/guides/regexdevs/index.rst b/doc/guides/regexdevs/index.rst index 4f928f9..bf4ca10 100644 --- a/doc/guides/regexdevs/index.rst +++ b/doc/guides/regexdevs/index.rst @@ -13,4 +13,5 @@ which can be used from an application through RegEx API. features_overview cn9k + hs mlx5 diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst index c8cc862..31afd5e 100644 --- a/doc/guides/rel_notes/release_26_11.rst +++ b/doc/guides/rel_notes/release_26_11.rst @@ -56,6 +56,13 @@ New Features ======================================================= +* **Added Hyperscan regex PMD.** + + Added a software regex PMD (``regex_hs``) based on Intel Hyperscan + library. This virtual device PMD implements the regexdev API using + Hyperscan block mode scanning and supports runtime pattern compilation. + + Removed Items ------------- diff --git a/drivers/regex/hs/hs_regex.c b/drivers/regex/hs/hs_regex.c new file mode 100644 index 0000000..393283b --- /dev/null +++ b/drivers/regex/hs/hs_regex.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2026 Intel Corporation + * + * Intel Hyperscan PMD for DPDK rte_regexdev + * + * This Poll Mode Driver wraps Intel Hyperscan behind the standard DPDK + * regex device API (rte_regexdev). Applications use the enqueue/dequeue + * burst interface with Hyperscan as the matching engine. + * + * Key design: + * - Synchronous scan in enqueue (hs_scan blocks until done) + * - Per-queue-pair scratch space for lock-free parallel scanning + * - HS_MODE_BLOCK: each buffer scanned independently + * - Runtime compilation via hs_compile_ext_multi() + * - Serialized database import/export via hs_deserialize_database() + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_log.h> +#include <rte_errno.h> +#include <bus_vdev_driver.h> +#include <rte_regexdev.h> +#include <rte_regexdev_core.h> +#include <rte_regexdev_driver.h> +#include <rte_mbuf.h> + +#include <hs/hs.h> + +#include "hs_regex.h" + +RTE_LOG_REGISTER_DEFAULT(hs_regex_logtype, NOTICE); +#define RTE_LOGTYPE_HS_REGEX hs_regex_logtype + +#define HS_LOG(level, ...) \ + RTE_LOG_LINE(level, HS_REGEX, __VA_ARGS__) + +/* Device Info */ +static int +hs_regex_info_get(struct rte_regexdev *dev __rte_unused, + struct rte_regexdev_info *info) +{ + info->driver_name = HS_REGEX_DRIVER_NAME; + info->dev = NULL; + info->max_matches = UINT16_MAX; + info->max_queue_pairs = HS_REGEX_MAX_QUEUE_PAIRS; + info->max_payload_size = UINT16_MAX; + info->max_rules_per_group = HS_REGEX_MAX_RULES; + info->max_groups = HS_REGEX_MAX_GROUPS; + info->regexdev_capa = RTE_REGEXDEV_CAPA_RUNTIME_COMPILATION_F; + info->rule_flags = RTE_REGEX_PCRE_RULE_CASELESS_F | + RTE_REGEX_PCRE_RULE_DOTALL_F | + RTE_REGEX_PCRE_RULE_MULTILINE_F | + RTE_REGEX_PCRE_RULE_UTF_F; + + return 0; +} + +/* Fast path stubs replaced by real implementations in later patches. */ + +static uint16_t +hs_regex_enqueue_burst(struct rte_regexdev *dev __rte_unused, + uint16_t qp_id __rte_unused, + struct rte_regex_ops **ops __rte_unused, + uint16_t nb_ops __rte_unused) +{ + return 0; +} + +static uint16_t +hs_regex_dequeue_burst(struct rte_regexdev *dev __rte_unused, + uint16_t qp_id __rte_unused, + struct rte_regex_ops **ops __rte_unused, + uint16_t nb_ops __rte_unused) +{ + return 0; +} + +static const struct rte_regexdev_ops hs_regexdev_ops = { + .dev_info_get = hs_regex_info_get, +}; + +/* Device Lifecycle */ + +int +hs_regex_dev_create(const char *name, struct rte_device *device) +{ + struct hs_regex_priv *priv; + struct rte_regexdev *dev; + + if (name == NULL || device == NULL) + return -EINVAL; + + HS_LOG(INFO, "Creating Hyperscan regex device: %s", name); + + dev = rte_regexdev_register(name); + if (!dev) { + HS_LOG(ERR, "Failed to register regex device %s", name); + return -EINVAL; + } + + priv = rte_zmalloc("hs_regex_priv", sizeof(*priv), + RTE_CACHE_LINE_SIZE); + if (!priv) { + rte_regexdev_unregister(dev); + return -ENOMEM; + } + + dev->dev_ops = &hs_regexdev_ops; + dev->enqueue = hs_regex_enqueue_burst; + dev->dequeue = hs_regex_dequeue_burst; + dev->device = device; + dev->data->dev_private = priv; + dev->state = RTE_REGEXDEV_READY; + + HS_LOG(INFO, "Hyperscan regex PMD created (dev_id=%u, hs=%s)", + dev->data->dev_id, hs_version()); + return dev->data->dev_id; +} + +void +hs_regex_dev_destroy(const char *name) +{ + struct rte_regexdev *dev; + struct hs_regex_priv *priv; + + if (name == NULL) + return; + + dev = rte_regexdev_get_device_by_name(name); + if (!dev) + return; + + priv = dev->data->dev_private; + if (priv) { + rte_free(priv); + dev->data->dev_private = NULL; + } + + rte_regexdev_unregister(dev); + HS_LOG(INFO, "Hyperscan regex PMD destroyed: %s", name); +} + +static int +hs_regex_probe(struct rte_vdev_device *vdev) +{ + const char *name; + int ret; + + name = rte_vdev_device_name(vdev); + if (name == NULL) + return -EINVAL; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { + HS_LOG(ERR, "Multi-process not supported for %s", name); + return -EINVAL; + } + + ret = hs_regex_dev_create(name, &vdev->device); + return ret < 0 ? ret : 0; +} + +static int +hs_regex_remove(struct rte_vdev_device *vdev) +{ + const char *name; + + name = rte_vdev_device_name(vdev); + if (name == NULL) + return -EINVAL; + + hs_regex_dev_destroy(name); + return 0; +} + +static struct rte_vdev_driver hs_regex_pmd_drv = { + .probe = hs_regex_probe, + .remove = hs_regex_remove, +}; + +RTE_PMD_REGISTER_VDEV(regex_hs, hs_regex_pmd_drv); +RTE_PMD_REGISTER_PARAM_STRING(regex_hs, ""); diff --git a/drivers/regex/hs/hs_regex.h b/drivers/regex/hs/hs_regex.h new file mode 100644 index 0000000..be4c2e9 --- /dev/null +++ b/drivers/regex/hs/hs_regex.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2026 Intel Corporation + */ + +#ifndef HS_REGEX_H +#define HS_REGEX_H + +#include <rte_regexdev.h> +#include <hs/hs.h> + +#define HS_REGEX_DRIVER_NAME "regex_hs" +#define HS_REGEX_INITIAL_RULES_CAP 64 +#define HS_REGEX_MAX_QUEUE_PAIRS 64 +#define HS_REGEX_MAX_GROUPS 64 +#define HS_REGEX_MAX_RULES 1000000 +#define HS_REGEX_DEFAULT_NB_DESC 1024 +#define HS_REGEX_MAX_NB_DESC 32768 + +/* Device lifecycle state machine. */ +enum hs_regex_dev_state { + HS_REGEX_DEV_CREATED = 0, + HS_REGEX_DEV_CONFIGURED, + HS_REGEX_DEV_STARTED, + HS_REGEX_DEV_STOPPED, +}; + +/* Per-rule entry stored before compilation */ +struct hs_regex_rule { + char *pattern; + uint32_t rule_id; + uint16_t group_id; + uint64_t rule_flags; +}; + +/* Queue pair */ +struct hs_regex_qp { + struct rte_regex_ops **ops; + uint16_t nb_desc; + uint16_t head; + uint16_t tail; + uint16_t count; + hs_scratch_t *scratch; + uint64_t qp_enqueued; + uint64_t qp_dequeued; + uint64_t qp_matches; +}; + +/* Per-device private data */ +struct hs_regex_priv { + struct hs_regex_rule *rules; + uint32_t nb_rules; + uint32_t rules_cap; + + hs_database_t *db; + int db_compiled; + + struct hs_regex_qp *qps; + uint16_t nb_queue_pairs; + + uint16_t max_matches; + uint16_t nb_groups; + + enum hs_regex_dev_state dev_state; +}; + +int hs_regex_dev_create(const char *name, struct rte_device *device); +void hs_regex_dev_destroy(const char *name); + +#endif /* HS_REGEX_H */ diff --git a/drivers/regex/hs/meson.build b/drivers/regex/hs/meson.build new file mode 100644 index 0000000..5c855f4 --- /dev/null +++ b/drivers/regex/hs/meson.build @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 Intel Corporation + +if not dpdk_conf.get('RTE_ARCH_64') + build = false + reason = 'only supported on 64-bit platforms' + subdir_done() +endif + +hs_dep = dependency('libhs', required: false) +if not hs_dep.found() + build = false + reason = 'missing dependency, "libhs"' + subdir_done() +endif + +sources = files('hs_regex.c') +deps += ['bus_vdev', 'hash'] +ext_deps += hs_dep diff --git a/drivers/regex/meson.build b/drivers/regex/meson.build index ff2a8fe..d5a378b 100644 --- a/drivers/regex/meson.build +++ b/drivers/regex/meson.build @@ -2,6 +2,7 @@ # Copyright 2020 Mellanox Technologies, Ltd drivers = [ + 'hs', 'mlx5', 'cn9k', ] -- 2.43.0

