Skip to content

af-packet: respect vlan.use-for-tracking in eBPF bypass#15469

Open
ssam18 wants to merge 6 commits into
OISF:mainfrom
ssam18:fix/issue-8242-vlan-mask-ebpf-bypass-v3
Open

af-packet: respect vlan.use-for-tracking in eBPF bypass#15469
ssam18 wants to merge 6 commits into
OISF:mainfrom
ssam18:fix/issue-8242-vlan-mask-ebpf-bypass-v3

Conversation

@ssam18

@ssam18 ssam18 commented May 28, 2026

Copy link
Copy Markdown
Contributor

Make sure these boxes are checked accordingly before submitting your Pull Request. Thank you.

Contribution style:

Our Contribution agreements:

Changes (if applicable):

Link to ticket: https://redmine.openinfosecfoundation.org/issues/8242

Supersedes #15458 (opened as a fresh PR per @catenacyber's request).

SV_BRANCH=OISF/suricata-verify#3113

Describe changes

AFPBypassCallback and AFPXDPBypassCallback in src/source-af-packet.c now AND p->vlan_id[N] with g_vlan_mask before writing it into the eBPF flow_table_v4 / flow_table_v6 map keys, so the bypass key reflects the active vlan.use-for-tracking configuration instead of always including the raw VLAN id. Without this, vlan.use-for-tracking: no is silently ignored on the bypass path: tracked flows write keys with the VLAN id present, but the matching ingress lookup writes with the VLAN id zeroed, so the bypass never matches and the flow is reprocessed each packet.

CI / SV coverage

This PR includes two commits from #15415, picked with @catenacyber's agreement, so SV coverage actually runs:

  • 2e37d88 (catenacyber) ci: add new xdp build with live tests: adds the ubuntu-xdp job to .github/workflows/builds.yml that runs suricata-verify/run.py --live --debug-failed (no equivalent job exists on main today).
  • 762d2d7 (catenacyber) test: new afpacket max-packets feature: adds the AFPACKET_TEST_REPLAY compile-time feature (all changes #ifdef-guarded; only the new ubuntu-xdp job sets -DAFPACKET_TEST_REPLAY, so other builds are byte-identical), used by the SV live test in suricata-verify#3113 to stop Suricata cleanly after the replay.

The matching SV PR suricata-verify#3113 that replays three VLAN-tagged UDP packets on the same 5-tuple through a dummy interface and asserts the bypass path engages with vlan.use-for-tracking: no.

ssam18 and others added 4 commits May 20, 2026 11:43
AFPBypassCallback and AFPXDPBypassCallback populate the flow_table_v4 and flow_table_v6 eBPF maps using p->vlan_id[N] directly. When the matching xdp_filter.c program is built with VLAN_TRACKING=0 (i.e. vlan.use-for-tracking is false in suricata.yaml), the kernel side writes vlan0 and vlan1 as 0 on every map lookup, so userspace inserts that carry the real VLAN id never match and per-flow bypass counters stay at zero.

Apply g_vlan_mask to each vlan_id assignment, matching the masking
pattern already used by flow-hash.c. When vlan.use-for-tracking is
true, g_vlan_mask is 0xffff and behaviour is unchanged.

Original patch by John Graat on Redmine ticket 8242. Rebased to
current main and dropped the now-removed vlan2 field.
Ticket: 8242
for SV to run tests based on the presence of this feature
so as to run ebpf live tests
Ticket: 7674

Allows a compile-time option AFPACKET_TEST_REPLAY, that allows
to set a configuration max-packets per afpacket interface,
after which the PktAcqLoop stops.

This allows suricata-verify tests to run with tcpreplay,
and know when to stop
Comment thread src/source-af-packet.c
#endif

#ifdef AFPACKET_TEST_REPLAY
uint32_t max_packets;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here explaining what it is, and the meaning of the special meaning of the 0 value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be on me I guess

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this

Comment thread src/source-af-packet.c Outdated
StatsCounterIncr(&ptv->tv->stats, ptv->capture_afp_poll_data);
r = AFPReadFunc(ptv);
#ifdef AFPACKET_TEST_REPLAY
if (ptv->max_packets > 0 && ptv->pkts >= ptv->max_packets) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would expect a simple explanation here as well

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, this is comparing a uint64_t and uint32_t, should we cast max_packets to u64?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we cast max_packets to u64?

Only when we want to have SV test with more than U32_MAX packets

- run: tar xf prep/suricata-verify.tar.gz
- run: ./autogen.sh
- run: CFLAGS="${DEFAULT_CFLAGS}" ./configure --enable-warnings --enable-unittests --enable-ebpf --enable-ebpf-build
- run: CFLAGS="${DEFAULT_CFLAGS} -DAFPACKET_TEST_REPLAY" ./configure --enable-warnings --enable-unittests --enable-ebpf --enable-ebpf-build

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we add configure options to define macros. Not sure how I feel about it here though. Opinions?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some context :

The goal here is to run SV tests with tcpreplay
So, we need a way for Suricata to know that it should stop
This is a test feature

So, I think it is ok this way, but if you want a configure option, I can do it this way

ssam18 added 2 commits May 28, 2026 17:57
ptv->pkts is uint64_t and ptv->max_packets is uint32_t; cast the
latter so the comparison is unsigned and same-width, addressing
@victorjulien's review comment on OISF#15469.
Mirror the doc comment from the AFPThreadVars copy onto the config
struct field, since they hold the same value (config -> per-thread
copy at init).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants