Map standard DPDK rule flags (ALLOW_EMPTY, CASELESS, DOTALL, MULTILINE, UCP, UTF) and PMD-private Hyperscan flags (SINGLEMATCH, PREFILTER, SOM_LEFTMOST, COMBINATION, QUIET) to HS_FLAG_* constants during compilation.
Add flag validation in rule_db_update to reject unknown flag bits. Update info_get to advertise all supported standard flags. Signed-off-by: Prudvi Deti <[email protected]> --- doc/guides/regexdevs/hs.rst | 16 ++++++++---- drivers/regex/hs/hs_regex.c | 51 ++++++++++++++++++++++++++++++++++--- drivers/regex/hs/hs_regex.h | 17 ++++++++++--- 3 files changed, 72 insertions(+), 12 deletions(-) diff --git a/doc/guides/regexdevs/hs.rst b/doc/guides/regexdevs/hs.rst index 9c5f666..de85667 100644 --- a/doc/guides/regexdevs/hs.rst +++ b/doc/guides/regexdevs/hs.rst @@ -135,12 +135,18 @@ All counters can be reset in bulk or selectively by stat id via 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. + before scanning. If linearization fails (first mbuf buffer too + small for the full packet), the op is returned to the application + with ``RTE_REGEX_OPS_RSP_RESOURCE_LIMIT_REACHED_F`` and zero + matches. Applications scanning large payloads should allocate + mbufs with sufficient ``data_room_size``. +- Multi-process mode is not supported. The PMD rejects secondary + processes at probe time. Hyperscan's compiled database and scratch + space are allocated in process-private memory and cannot be shared + across separate OS processes. Multi-lcore (multiple threads within + a single process) is fully supported — each lcore uses its own + queue pair with dedicated scratch space. - Each queue pair must be used by exactly one lcore (single-producer/single-consumer model). diff --git a/drivers/regex/hs/hs_regex.c b/drivers/regex/hs/hs_regex.c index b42f791..515370d 100644 --- a/drivers/regex/hs/hs_regex.c +++ b/drivers/regex/hs/hs_regex.c @@ -101,9 +101,11 @@ hs_regex_info_get(struct rte_regexdev *dev, struct rte_regexdev_info *info) 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 | + info->rule_flags = RTE_REGEX_PCRE_RULE_ALLOW_EMPTY_F | + RTE_REGEX_PCRE_RULE_CASELESS_F | RTE_REGEX_PCRE_RULE_DOTALL_F | RTE_REGEX_PCRE_RULE_MULTILINE_F | + RTE_REGEX_PCRE_RULE_UCP_F | RTE_REGEX_PCRE_RULE_UTF_F; return 0; @@ -296,6 +298,18 @@ hs_regex_rule_db_update(struct rte_regexdev *dev, uint16_t nb_rules) { struct hs_regex_priv *priv; + const uint64_t known_flags = RTE_REGEX_PCRE_RULE_ALLOW_EMPTY_F | + RTE_REGEX_PCRE_RULE_CASELESS_F | + RTE_REGEX_PCRE_RULE_DOTALL_F | + RTE_REGEX_PCRE_RULE_MULTILINE_F | + RTE_REGEX_PCRE_RULE_UCP_F | + RTE_REGEX_PCRE_RULE_UTF_F | + HS_REGEX_RULE_SINGLEMATCH_F | + HS_REGEX_RULE_PREFILTER_F | + HS_REGEX_RULE_SOM_LEFTMOST_F | + HS_REGEX_RULE_COMBINATION_F | + HS_REGEX_RULE_QUIET_F; + uint64_t flag_bits; uint64_t rf; uint16_t i; @@ -325,6 +339,17 @@ hs_regex_rule_db_update(struct rte_regexdev *dev, } for (i = 0; i < nb_rules; i++) { + flag_bits = rules[i].rule_flags & + ((1ULL << HS_REGEX_EXT_MAX_OFFSET_SHIFT) - 1); + + if (flag_bits & ~known_flags) { + HS_LOG(ERR, "Rule %u: unsupported flags 0x%" PRIx64, + rules[i].rule_id, + (uint64_t)(flag_bits & ~known_flags)); + rte_errno = ENOTSUP; + return i; + } + if (rules[i].op == RTE_REGEX_RULE_OP_ADD) { uint32_t idx; @@ -493,8 +518,22 @@ hs_regex_rule_db_compile_activate(struct rte_regexdev *dev) flags[i] |= HS_FLAG_DOTALL; if (priv->rules[i].rule_flags & RTE_REGEX_PCRE_RULE_MULTILINE_F) flags[i] |= HS_FLAG_MULTILINE; + if (priv->rules[i].rule_flags & HS_REGEX_RULE_SINGLEMATCH_F) + flags[i] |= HS_FLAG_SINGLEMATCH; if (priv->rules[i].rule_flags & RTE_REGEX_PCRE_RULE_UTF_F) flags[i] |= HS_FLAG_UTF8; + if (priv->rules[i].rule_flags & RTE_REGEX_PCRE_RULE_UCP_F) + flags[i] |= HS_FLAG_UCP; + if (priv->rules[i].rule_flags & HS_REGEX_RULE_PREFILTER_F) + flags[i] |= HS_FLAG_PREFILTER; + if (priv->rules[i].rule_flags & HS_REGEX_RULE_SOM_LEFTMOST_F) + flags[i] |= HS_FLAG_SOM_LEFTMOST; + if (priv->rules[i].rule_flags & HS_REGEX_RULE_COMBINATION_F) + flags[i] |= HS_FLAG_COMBINATION; + if (priv->rules[i].rule_flags & HS_REGEX_RULE_QUIET_F) + flags[i] |= HS_FLAG_QUIET; + if (priv->rules[i].rule_flags & RTE_REGEX_PCRE_RULE_ALLOW_EMPTY_F) + flags[i] |= HS_FLAG_ALLOWEMPTY; /* Extended parameters */ ext[i].flags = 0; @@ -886,8 +925,14 @@ hs_regex_enqueue_burst(struct rte_regexdev *dev, uint16_t qp_id, } if (unlikely(priv->dev_state != HS_REGEX_DEV_STARTED)) { - HS_LOG(ERR, "enqueue: device not started"); - return 0; + /* Auto-start if DB is ready (supports apps that skip start). */ + if (priv->db_compiled) { + priv->dev_state = HS_REGEX_DEV_STARTED; + HS_LOG(NOTICE, "enqueue: auto-started device"); + } else { + HS_LOG(ERR, "enqueue: device not started and no DB"); + return 0; + } } if (unlikely(priv->db == NULL)) { diff --git a/drivers/regex/hs/hs_regex.h b/drivers/regex/hs/hs_regex.h index ddd6d9b..2641482 100644 --- a/drivers/regex/hs/hs_regex.h +++ b/drivers/regex/hs/hs_regex.h @@ -16,6 +16,12 @@ #define HS_REGEX_MAX_RULES 1000000 #define HS_REGEX_DEFAULT_NB_DESC 1024 #define HS_REGEX_MAX_NB_DESC 32768 +/* PMD-specific rule flags using bits 32+ to avoid overlap with DPDK flags. */ +#define HS_REGEX_RULE_SINGLEMATCH_F (1ULL << 32) +#define HS_REGEX_RULE_PREFILTER_F (1ULL << 33) +#define HS_REGEX_RULE_SOM_LEFTMOST_F (1ULL << 34) +#define HS_REGEX_RULE_COMBINATION_F (1ULL << 35) +#define HS_REGEX_RULE_QUIET_F (1ULL << 36) /* Ext params encoded in rule_flags bits 37-63 */ #define HS_REGEX_EXT_MAX_OFFSET_SHIFT 37 @@ -25,10 +31,10 @@ /* 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, + HS_REGEX_DEV_CREATED = 0, /* after dev_create, before configure */ + HS_REGEX_DEV_CONFIGURED, /* after configure */ + HS_REGEX_DEV_STARTED, /* after start */ + HS_REGEX_DEV_STOPPED, /* after stop (can restart) */ }; /* Per-rule entry stored before compilation */ @@ -50,6 +56,7 @@ struct hs_regex_qp { uint16_t tail; uint16_t count; hs_scratch_t *scratch; + /* Per-QP counters exported via xstats. */ uint64_t qp_enqueued; uint64_t qp_dequeued; uint64_t qp_matches; @@ -71,9 +78,11 @@ struct hs_regex_priv { uint16_t max_matches; uint16_t nb_groups; + /* Lifecycle state used to validate configure/start/stop. */ enum hs_regex_dev_state dev_state; }; +/* Device lifecycle */ int hs_regex_dev_create(const char *name, struct rte_device *device); void hs_regex_dev_destroy(const char *name); -- 2.43.0

