Background
----------

Multiple efforts over the past few cycles have tried to make
testpmd's flow rule grammar reusable from outside testpmd.
External applications that need rte_flow want a documented way
to turn human-written rules into the rte_flow_attr/item/action
arrays accepted by rte_flow_create().

The most recent attempt is Lukas Sismis's series, currently at
v12:

  http://patches.dpdk.org/project/dpdk/list/?series=37384

That series factors testpmd's existing cmdline_flow.c into a
library and updates testpmd to consume it.  It works, but
inherits two properties of cmdline_flow.c that I think are worth
avoiding in a reusable library:

  - Coupling to librte_cmdline.  Even after the v12 split into
    a "simple" part and a "cmdline" part, the parser is still
    organized around testpmd's command interpreter, and v12 has
    cmdline depending on ethdev to break a previous circular
    dependency.  A library used by daemons, control planes, or
    unit tests should not need that.

  - Ad-hoc grammar.  cmdline_flow.c implements parsing per-token
    in long dispatch logic; the grammar emerges from the code
    rather than being stated, and adding a new flow item
    requires touching the parser.

This RFC explores a different shape and is posted to ask the
list which one is preferred before more work goes into either.

I started a new green-field library for parsing flow rules
(with AI assistance for the boilerplate).  It is young but
passes tests and reviews clean under the project's AI review
guidelines.

This series
-----------

lib/flow_compile -- a small new library providing the same
service via a pcap_compile()-style API:

    char errbuf[RTE_FLOW_COMPILE_ERRBUF_SIZE];
    struct rte_flow_compile *fc = rte_flow_compile(rule, errbuf);
    if (fc == NULL)
            fail(errbuf);            /* "line:col: message" */

    rte_flow_compile_create(port_id, fc, &flow_error);
    rte_flow_compile_free(fc);

Design properties:

  - Flex lexer plus bison grammar.  Both are reentrant
    (%option reentrant, %define api.pure full), so multiple
    compilations may run concurrently and the parser holds no
    static mutable state.  The grammar itself is short
    (~200 lines) because all per-type knowledge lives in
    descriptor tables, not in productions.

  - Parser is driven entirely by descriptor tables of items and
    actions.  Adding a new flow item is a table edit, not a
    grammar change.  A custom-setter hook on each field is the
    escape valve for layouts that don't fit a plain byte range
    (bitfields, indirect arrays).

  - Dependencies: rte_ethdev (for rte_flow.h) and rte_net (for
    MAC parsing).  No librte_cmdline.  Flex and bison are
    required at build time to regenerate the lexer and parser;
    if either tool is missing the library is silently skipped
    via meson's has_flex_bison check, the same pattern other
    DPDK components use for optional generators.

  - Per-allocation rte_zmalloc for spec/mask/last/conf payloads;
    rte_flow_compile_free() walks the pattern and action arrays
    and releases every non-NULL slot before freeing the arrays.
    Parse-error paths use the same walker, so partially
    constructed rules clean up uniformly.  ASan/LSan run clean
    on the autotest, including the failure cases.

The grammar follows testpmd's syntax closely so familiar rules
carry over:

    ingress pattern eth / ipv4 src is 10.0.0.1 / end
    actions queue index 3 / count / end

and is documented as a formal BNF in the programmer's guide
chapter (patch 2).

Initial coverage: eth, vlan, ipv4, ipv6, tcp, udp, vxlan,
port_id, port_representor, represented_port items; drop,
passthru, queue, mark, jump, count, port_id and representor
variants, of_pop_vlan, vxlan_decap actions.  Variable-conf
items and actions (RSS, RAW) need custom setters and are
deferred to a follow-up.

What this RFC is *not*
----------------------

Not a replacement for cmdline_flow.c in testpmd.  If the shape
here is acceptable, the next step is a separate series adding a
"flow compile <port> <rule>" command in testpmd alongside the
existing parser, so users can adopt the library incrementally
without breaking scripts that depend on the current syntax.

What I'd like feedback on
-------------------------

1. API shape.  pcap_compile-style (one string -> opaque object ->
   arrays) versus the three-call attr/pattern/actions form
   Sismis's v12 exposes.  What does your application actually
   want?

2. Library placement.  Stand-alone at lib/flow_compile/ versus
   addition to lib/ethdev.  This series treats it as a
   control-path parser layered on top of ethdev rather than
   part of ethdev itself; v12 places its parser inside ethdev.

3. Table-driven extension model.  Is "to add a new flow item,
   add a row to the descriptor table" the right contract?
   Should the tables live alongside each rte_flow_item_*
   definition in rte_flow.h, or in their own file as here?

4. Build-tool dependency.  Flex and bison are not currently
   required to build DPDK.  Adding a library that needs them
   (with a clean has_flex_bison fallback so the rest of DPDK
   still builds without them) is the cleanest way I see to get
   a real grammar. If this gets used by testpmd then
   what is now an optional dependency would get hardened in.

5. Convergence.  If this design is preferred, I'm happy to
   coordinate with Lukas to fold in the testpmd-side changes
   from his series.

6. Readability. AI generated code like this tends to be
   either opaque or too verbose for humans. Often have to
   nudge it into submission.


Stephen Hemminger (4):
  config: add support for using flex and bison
  flow_compile: introduce textual flow rule compiler
  doc: add programmer's guide for flow rule compiler
  test/flow_compile: add unit tests for flow rule compiler

 MAINTAINERS                                |   7 +
 app/test/meson.build                       |   1 +
 app/test/test_flow_compile.c               | 255 ++++++++++
 config/meson.build                         |  23 +
 doc/guides/prog_guide/flow_compile_lib.rst | 302 ++++++++++++
 doc/guides/prog_guide/index.rst            |   1 +
 doc/guides/rel_notes/release_26_07.rst     |   6 +
 lib/flow_compile/flow_compile.l            | 227 +++++++++
 lib/flow_compile/flow_compile.y            | 311 +++++++++++++
 lib/flow_compile/flow_compile_priv.h       | 127 +++++
 lib/flow_compile/flow_compile_setters.c    | 516 +++++++++++++++++++++
 lib/flow_compile/flow_compile_tables.c     | 243 ++++++++++
 lib/flow_compile/meson.build               |  22 +
 lib/flow_compile/rte_flow_compile.h        | 158 +++++++
 lib/flow_compile/rte_flow_compile_api.c    | 160 +++++++
 lib/meson.build                            |   1 +
 16 files changed, 2360 insertions(+)
 create mode 100644 app/test/test_flow_compile.c
 create mode 100644 doc/guides/prog_guide/flow_compile_lib.rst
 create mode 100644 lib/flow_compile/flow_compile.l
 create mode 100644 lib/flow_compile/flow_compile.y
 create mode 100644 lib/flow_compile/flow_compile_priv.h
 create mode 100644 lib/flow_compile/flow_compile_setters.c
 create mode 100644 lib/flow_compile/flow_compile_tables.c
 create mode 100644 lib/flow_compile/meson.build
 create mode 100644 lib/flow_compile/rte_flow_compile.h
 create mode 100644 lib/flow_compile/rte_flow_compile_api.c

-- 
2.53.0

Reply via email to