8. Flow Filtering Sample Application

The flow filtering sample application provides a simple example of creating flow rules.

It serves as a demonstration of the fundamental components of flow rules.

It demonstrates how to create rules and configure them, using both template and non template API.

8.1. Compiling the Application

To compile the sample application see Compiling the Sample Applications.

The application is located in the flow_filtering sub-directory.

8.2. Running the Application

To run the example in a linux environment:

dpdk-flow_filtering -n <number of channels> -a <pci_dev>,dv_flow_en=<1|2> -- [--[non-]template]

where,

--[non-]template

Specify whether to use the template API (default is template API).

For more details on template API please refer to Flow templates.

Refer to DPDK Getting Started Guide for general information on running applications and the Environment Abstraction Layer (EAL) options.

8.3. Structure

The example is built from 2 main files:

  • main.c: Contains the application logic, including initializations and the main loop.

  • flow_skeleton.c: Implements the creation of flow rules.

Additionally, the snippets directory includes code snippets showcasing various features that can override the basic flow_skeleton.c implementation.

8.4. Application Flow

8.4.1. Initialization

Begin by setting up the Environment Abstraction Layer (EAL) using rte_eal_init(). This function initializes EAL with arguments argc and argv, returning the number of parsed arguments:

ret = rte_eal_init(argc, argv);
if (ret < 0)
	rte_exit(EXIT_FAILURE, ":: invalid EAL arguments\n");

Allocate a memory pool for managing mbufs used within the application:

mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", 4096, 128, 0,
					RTE_MBUF_DEFAULT_BUF_SIZE,
					rte_socket_id());

Initialize the ports using the user-defined init_port() function, configuring Ethernet ports with default settings, including both Rx and Tx queues for a single port:

init_port();

For template API, the flow API requires preallocating resources. The function rte_flow_configure() should be called after configuring the Ethernet device and before creating any flow rules to set up flow queues for asynchronous operations.

ret = rte_eth_dev_stop(port_id);
if (ret < 0)
	rte_exit(EXIT_FAILURE,
		"rte_eth_dev_stop:err=%d, port=%u\n",
		ret, port_id);

configure_port_template(port_id);
ret = rte_eth_dev_start(port_id);
if (ret < 0)
	rte_exit(EXIT_FAILURE,
		"rte_eth_dev_start:err=%d, port=%u\n",
		ret, port_id);

8.4.2. Creating the Flow Rule

This section is the core of the flow filtering functionality involves creating flow rules. The flow rules are created using two primary approaches: template API and non-template API. Both template and non-template API configure flow rules using attributes (like ingress or egress), pattern items (for matching packet data), and actions (for operations on matched packets). However, template API extend this by introducing pattern templates and actions templates, which define reusable matching criteria and action lists, respectively. These templates are then combined in a template table to optimize resource allocation and management. In contrast, non-template API handle each rule individually without such shared templates.

This is handled by the generate_flow_skeleton() function in flow_skeleton.c.

flow = generate_flow_skeleton(port_id, &error, use_template_api);

This part of the code defines necessary data structures, as well as configures action and pattern structures for the rule. Common for both template and non-template API.

struct rte_flow_action actions[MAX_ACTION_NUM] = {0};
struct rte_flow_item patterns[MAX_PATTERN_NUM] = {0};

/* Replace this function call with
 * snippet_*_create_actions() function from the snippets directory
 */
snippet_ipv4_flow_create_actions(actions);

/* Replace this function call with
 * snippet_*_create_patterns() function from the snippets directory
 */
snippet_ipv4_flow_create_patterns(patterns);

For template API, this part of the code creates the necessary template tables and finally create the rule.

if (use_template_api)
	return create_flow_template(port_id, &ops_attr, patterns, actions, error);

For non-template API, validate the rule and create it.

return create_flow_non_template(port_id, &attr, patterns, actions, error);

8.4.3. Main Loop Execution

Launch the main_loop() function from main.c, which reading the packets from all queues and printing for each packet the destination queue:

ret = main_loop();

8.4.4. Exiting the Application

To terminate the application, use Ctrl-C. This action closes the port and device using rte_eth_dev_stop and rte_eth_dev_close.

8.5. Flow API Snippets

The snippets directory offers additional customization options through code snippets. These snippets cover various aspects of flow configuration, allowing developers to reuse them.

These snippets are categorized by usage and can be copied, pasted, and modified as needed. They are maintained and compiled alongside other examples, ensuring up-to-date functionality.

8.6. Using Snippets

Developers can customize flow rules by modifying flow_skeleton.c and utilizing functions from snippets directory. For example, within snippet_match_ipv4_flow.c, developers can find the functions:

  • snippet_ipv4_flow_create_actions() for defining actions,

  • snippet_ipv4_flow_create_patterns() for setting packet matching patterns,

  • snippet_ipv4_flow_create_table() for creating the patterns and actions template table.

These functions can simply be called in the appropriate place in flow_skeleton.c to change the default created flow.