Skip to content

lib: set: support port ranges in set elements#570

Open
ChatchawanIllyes wants to merge 1 commit into
facebook:mainfrom
ChatchawanIllyes:fix/set-port-ranges
Open

lib: set: support port ranges in set elements#570
ChatchawanIllyes wants to merge 1 commit into
facebook:mainfrom
ChatchawanIllyes:fix/set-port-ranges

Conversation

@ChatchawanIllyes

Copy link
Copy Markdown

Summary

Implements port ranges in set elements (#562).

bf_set_add_elem_raw() now recognises range syntax (START-END) in a set
element's components and expands it into individual set elements. For example:

(tcp.dport) in { 11; 22; 33-44 }

produces a set containing { 11, 22, 33, 34, …, 44 } (14 elements).

Range detection reuses the BF_MATCHER_RANGE parsing that already backs the
standalone range matcher operator — a component is treated as a range only
when the token contains a - and the component's matcher type registers
BF_MATCHER_RANGE ops. This scopes the feature to the matcher types that
already support ranges (ports today) without hardcoding anything port-specific,
and non-range / multi-component parsing is unchanged.

Behaviour

  • Each value in [start, end] is expanded into its own element and inserted
    into the set's hashset, deduplicated like any other element.
  • Expanded values are re-parsed through the existing single-value
    (BF_MATCHER_IN) path, so their in-memory representation is byte-identical to
    an element written as a plain value.
  • Range bounds are validated by the existing _bf_parse_l4_port_range():
    both bounds must be valid decimal ports <= 65535, and start <= end.
    44-33, 33-, and -44 are rejected.

Scope / limitations

A couple of things are intentionally left out to keep this a minimal, focused
change — flagging them for maintainer input:

  • Printing is unchanged. Expanded ranges are printed element-by-element,
    not re-factored back into a START-END range. This is the open question
    raised in Port range in sets #562; happy to add range factorization on ruleset get in a
    follow-up if that's the preferred direction.
  • One ranged component per element. A set element with more than one ranged
    component (e.g. (tcp.sport, tcp.dport) in { 1-2, 3-4 }) returns -EINVAL
    rather than performing a Cartesian expansion. This avoids surprising blow-up
    in element count; can revisit if Cartesian expansion is wanted.

A note on element separators

The issue's example is written as { 11, 22, 33-44 }, but bpfilter separates
set elements with ; and components within an element with ,
(e.g. { 80; 443 } vs (ip4.daddr, tcp.sport) in { 1.2.3.4, 80 }). So the
range form is { 11; 22; 33-44 }. This PR does not change the grammar, so the
comma-separated form from the issue's example still parses as multiple
components. If treating , as an element separator for single-component sets
is desired, that's a separate grammar change and I'm glad to take it on
separately.

Tests

Added unit tests in tests/unit/libbpfilter/set.c:

  • single-component range expansion ({11; 22; 33-44} → 14 elements)
  • range boundaries (0-1, degenerate 65535-65535)
  • invalid ranges (44-33, 33-, -44)
  • a range in one component of a two-component key ({1.2.3.4, 80-82} → 3)
  • ranges in both components of an element (rejected)

All unit.libbpfilter.set tests pass (28/28).

bf_set_add_elem_raw() now detects range syntax (START-END) in a set
element's components and expands it into individual elements, reusing
the existing BF_MATCHER_RANGE parsing already used for standalone range
matchers. Only one ranged component per element is supported; sets with
ranges in multiple components of the same element return an error.

Printing behavior for expanded ranges is intentionally left unchanged
(elements print individually, not re-factored into a range) pending
maintainer input on the open question raised in the issue.

Fixes facebook#562
@meta-cla

meta-cla Bot commented Jul 18, 2026

Copy link
Copy Markdown

Hi @ChatchawanIllyes!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla meta-cla Bot added the cla signed label Jul 18, 2026
@meta-cla

meta-cla Bot commented Jul 18, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@qdeslandes

Copy link
Copy Markdown
Contributor

Hi, could you please disclose if/how much AI has been used for this work? Thank you.

@ChatchawanIllyes

Copy link
Copy Markdown
Author

Hi, could you please disclose if/how much AI has been used for this work? Thank you.

Hey there, only used AI for two things: drafting the unit tests in tests/unit/libbpfilter/set.c, and writing up the PR description.

I reviewed both, and ran the test suite locally (unit.libbpfilter.set, 28/28) to confirm the cases and checked the tests actually cover what they say they do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants