Skip to content

DPDK rte_flow traffic drop filter v2#13891

Closed
adaki4 wants to merge 2 commits into
OISF:mainfrom
adaki4:dpdk-rte-flow-drop-filter-v2
Closed

DPDK rte_flow traffic drop filter v2#13891
adaki4 wants to merge 2 commits into
OISF:mainfrom
adaki4:dpdk-rte-flow-drop-filter-v2

Conversation

@adaki4

@adaki4 adaki4 commented Sep 23, 2025

Copy link
Copy Markdown
Contributor

Followup of #12848

Changes:

v2:

  • integrated feedback from previous PR
  • integrated feedback related to this feature from draft PR #13760
  • rebased
  • removed unused macros
  • added an explanation for the chosen syntax used for this feature and an expanded PR description

Ticket: #7629

Motivation

This feature brings a new approach to filter unwanted network traffic in hardware in Suricata's DPDK runmode, even before it reaches Suricata. The main benefit is the ability to offload the processing of unwanted traffic from the software, thus reducing the load on both the PCIe bus and the CPU and increasing Suricata throughput. This is achieved via DPDK's rte_flow API, which provides flow rules that define the behaviour of matched flows in the hardware.

The rules and their relationships work similarly to Suricata rules, as the individual pattern parts inside one rule are connected with an AND operation, and the whole rules are connected with an OR operation. For example, if a rule in dpdk-testpmd syntax looks like flow create 0 ingress pattern eth / ipv4 src is 192.11.11.12 / tcp src is 10 / end actions drop / end, then matching pattern parts (eth, ipv4, and tcp) are combined with an AND operation. If there is another rule with a different pattern, then the first rule and the second rule would be connected with an OR operation, meaning that the incoming traffic will either match the first rule, match the second rule or it will be passed to Suricata.

Explored options

Rule syntax

dpdk-testpmd-like syntax

dpdk-testpmd syntax offers a wide range of different patterns and adjustments, which are well documented in the DPDK documentation. This means that the drop-filter is limited only by the capabilities of the used NIC. Another advantage is that Suricata operators can easily test and adjust the rules they want to apply in the dpdk-testpmd application, with the possibility of copying the tested patterns into suricata.yaml.

The whole rule, as could be applied in dpdk-testpmd application, would, for example, look like flow create 0 ingress pattern eth / ipv4 src is 199.11.23.5 / tcp src is 42 / end actions drop end / end. However, only the pattern part is important when defining rte_flow rules for Suricata, so only pattern eth / ipv4 src is 199.11.23.5 / tcp src is 42 / end would be present in suricata.yaml.

This example shows how the rules are defined in suricata.yaml:

drop-filter:

    - rule: 'pattern eth / ipv4 src is 199.11.23.5 / tcp src is 42 / end'

    - rule: 'pattern eth / vlan vid is 15'

If supported by the NIC, this syntax also offers the ability to adjust the matched range (of IP addresses, ports, …) with two keywords, mask and last. For example, rules including these keywords could look as follows:

drop-filter:

    - rule: 'pattern eth / ipv4 src is 199.11.23.0 src mask 255.255.255.0 / tcp src is 42 / end'

    - rule: 'pattern eth / ipv4 src is 192.11.23.10 src last 192.11.11.20 / tcp / end' 

BPF syntax

One of the reasons why I did not choose the BPF syntax is that both BPF and rte_flow offer multiple distinct features that the other does not. For example, BPF syntax provides the capability to use an OR operand inside the pattern (tcp dst port 80 or 8000), which would require two distinct rte_flow rules. Another difference is the lack of negation operand and exact-byte reading in rte_flow rules.

A disadvantage of BPF in this case is the lack of an existing parser to convert BPF syntax into rte_flow rules. In contrast, the dpdk-testpmd syntax already has a usable parser implementation that transforms the dpdk-testpmd string rules into rte_flow rules. With some modifications, it is suitable for our use case.

Simple filter

Another considered option to define what traffic should be filtered is to declare a simple list of IP addresses and ports, which will then be parsed into rte_flow rules. However, this way we lose a substantial part of the available matching power, as we can match only specific flows and we can not utilize the various supported protocols, such as matching on VLAN or other encapsulation protocols.

This method is not implemented, but could serve as an alternative/support mode for the dpdk-testpmd rule-based filter. It could be present in an exclusive mode, meaning only one of the options will be available at a time, or it could work as an additional way to declare what traffic to discard.

A concept of how such a filter could be defined in suricata.yaml:

drop-filter:

    - rule: ip src 199.1.2.5 and ip dst 10.10.1.1 and tcp src 80

    - rule: ip src 200.1.2.0/24 and ip dst 10.10.1.1 and tcp src 80

Allow-filter

The allow-filter was expected to work as the exact opposite of the drop-filter, with Suricata receiving only traffic defined by rte_flow rules. This filter would behave similarly to a BPF program that passes only specified traffic and drops everything else.

This filter could be implemented via DPDK's isolated mode, which restricts the NIC to accept only traffic defined via some rte_flow rule. Unfortunately, this filter would currently work only on Mellanox NICs (among the ones we tested), as isolated mode is not supported on Intel NICs.

If this hypothetical allow-filter were implemented, it could serve as an alternative/exclusive mode to the drop-filter, as its implicit behavior is to drop all unwanted traffic.

NIC limitations and more detailed description

Limitations of supported NICs, as well as a more expanded description of the feature, can be found in the file /doc/userguide/capture-hardware/dpdk.rst.

Added pattern based drop-filter.
Supported patterns are listed in "util-dpdk-rte-flow-pattern.c" in
"enum index next_item[]" and their corresponding attributes
in "enum index item_<pattern>[]".

The syntax of the pattern used in suricata.yaml is taken
from test-pmd application.
Other attributes, such as actions, are omitted, and only
pattern is accepted, e.g., a valid entry in suricata.yaml is:
"pattern eth / ipv4 src is 192.168.11.12 / end".

The user needs to validate the pattern used for a specific driver first,
otherwise, Suricata shuts down if the pattern is unsupported.
Source for supported patterns with different drivers:
https://doc.dpdk.org/guides/nics/overview.html

More patterns can be added in the future if needed. This new entry
needs to be specified in the `enum index`. This pattern then needs to be
present in `enum index next_item[]` and its corresponding attributes in
`enum index item_<pattern>[]`. Also, new entry needs to be provided to
`struct token token_list[]` with appropriate attributes.

The feature was tested on NIC drivers mlx5, ice, i40e, and ixgbe.

mlx5 accepts multiple rules with different patterns and various
corresponding specifications of pattern items. The driver does not have
any additional restrictions on the pattern.

ice does not support broad patterns; some pattern item has to have
specification, e.g., pattern "eth / ipv4 / end" raises an error but
"eth / ipv4 src is x / end" or "eth / ipv4 / tcp src is x" works fine.

i40e does not support different item sets on the same pattern item type,
e.g., if the first rule has the pattern `eth / ipv4 src is x / end`,
then if any other rule contains an ipv4 pattern type, it needs to have
exclusively attribute src.

ixgbe does not support this feature.

Ticket: 7629
Added counter for packets filtered by the drop filter.
These statistics are only available on mlx5 and ice drivers.
Additionally, ice driver supports gathering statistic only when any
of the rules does not contain range of any kind (mask on IP address,
last on ports etc.). These statistics are available in eve.json under
"dpdk.rte_flow_filtered".

Ticket: 7629

@lukashino lukashino left a comment

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.

First pass is in. Well done, the code looks much better now!

-----------------------------

Drop filter can improve the performance of Suricata by filtering
used-predefined flows directly in the Network interface card. The user can

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.

/used-predefined flows/user-predefined traffic patterns/

-----------------------------

Drop filter can improve the performance of Suricata by filtering
used-predefined flows directly in the Network interface card. The user can

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.

also, since NIC is mentioned previously, you could either use acronym (NIC) or lowercase the "Network".


Drop filter can improve the performance of Suricata by filtering
used-predefined flows directly in the Network interface card. The user can
specify unwanted flows before the start of Suricata. These flows are not going to be

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.

Generally, I would avoid mentioning "flows" and focus more on the traffic patterns (or a more suitable term).
Potentially "traffic filter expression/rule"

Comment thread src/runmode-dpdk.c
iconf->pkt_mempools = NULL;
}

ldev_instance->dpdk_vars = iconf->pkt_mempools;

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 should have been moved out of this commit.

* \param items parsed items used when creating rte_flow rules
* \return 0 on success, -1 on error
*/
int ParsePattern(

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.

If we move forward with this approach, this is definitely a must-have candidate for unit tests.

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.

items_data_buffer could be a static variable to save function arguments in ParsePattern

Comment thread src/util-dpdk-rte-flow.c
{
if (strcmp(driver_name, "net_ice") == 0) {
if (iceDeviceRteFlowPatternError(items) == true) {
char msg[] = "Driver specific errmsg: ice driver does not support broad patterns";

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.

I would suggest changing this to %s: ice driver ... where %s would be the PCIe address of the current interface.

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.

Generally, the whole error messaging in this part seems overly complicated. I think you could just issue an error (even if multiple) here directly, or what was the intention?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The goal was to combine both reasons for error into one error message, which is why I am not logging the error in the DriverSpecificErrorMessage() but returning the error string and logging in RteFlowRulesCreate(). I can change it to two distinct error messages.

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.

Ok, I see, you can leave it as is now. Thanks.

@adaki4

adaki4 commented Sep 25, 2025

Copy link
Copy Markdown
Contributor Author

Continues in #13903

@adaki4 adaki4 closed this Sep 25, 2025
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.

2 participants