[PATCH v3 08/19] net/ixgbe: reimplement ntuple parser

Medvedkin, Vladimir vladimir.medvedkin at intel.com
Sat Sep 19 18:11:01 CEST 2026


On 9/16/2026 1:18 PM, Anatoly Burakov wrote:
> Use the new flow graph API and the common parsing framework to implement
> flow parser for ntuple.
>
> The 5tuple filter tracking infrastructure is moved completely inside the
> new engine and is removed from the rest of the driver.
>
> Signed-off-by: Anatoly Burakov<anatoly.burakov at intel.com>
> ---
<snip>
> +static const struct flow_graph ixgbe_ntuple_graph = {
> +	.nodes = (struct flow_graph_node[]) {
> +		[IXGBE_NTUPLE_NODE_START] = {
> +			.name = "START",
> +		},
> +		[IXGBE_NTUPLE_NODE_ETH] = {
> +			.name = "ETH",
> +			.type = RTE_FLOW_ITEM_TYPE_ETH,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_EMPTY,
legacy code accepts patterns with non null spec/mask containing all 
zeros. Same for VLAN.
> +		},
> +		[IXGBE_NTUPLE_NODE_VLAN] = {
> +			.name = "VLAN",
> +			.type = RTE_FLOW_ITEM_TYPE_VLAN,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_EMPTY,
> +		},
> +		[IXGBE_NTUPLE_NODE_IPV4] = {
> +			.name = "IPV4",
> +			.type = RTE_FLOW_ITEM_TYPE_IPV4,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_SPEC_MASK,
mask was optional
> +			.validate = ixgbe_validate_ntuple_ipv4,
> +			.process = ixgbe_process_ntuple_ipv4,
> +		},
> +		[IXGBE_NTUPLE_NODE_TCP] = {
> +			.name = "TCP",
> +			.type = RTE_FLOW_ITEM_TYPE_TCP,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_SPEC_MASK,
> +			.validate = ixgbe_validate_ntuple_tcp,
> +			.process = ixgbe_process_ntuple_tcp,
> +		},
> +		[IXGBE_NTUPLE_NODE_UDP] = {
> +			.name = "UDP",
> +			.type = RTE_FLOW_ITEM_TYPE_UDP,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_SPEC_MASK,
spec and mask was optional
> +			.validate = ixgbe_validate_ntuple_udp,
> +			.process = ixgbe_process_ntuple_udp,
> +		},
> +		[IXGBE_NTUPLE_NODE_SCTP] = {
> +			.name = "SCTP",
> +			.type = RTE_FLOW_ITEM_TYPE_SCTP,
> +			.constraints = FLOW_GRAPH_NODE_EXPECT_SPEC_MASK,
> +			.validate = ixgbe_validate_ntuple_sctp,
> +			.process = ixgbe_process_ntuple_sctp,
> +		},
> +		[IXGBE_NTUPLE_NODE_END] = {
> +			.name = "END",
> +			.type = RTE_FLOW_ITEM_TYPE_END,
> +		},
> +	},
<snip>
> +	priority = RTE_MIN(IXGBE_MAX_N_TUPLE_PRIO - 1, (uint16_t)attr->priority);
> +	priority = IXGBE_MAX_N_TUPLE_PRIO - 1 - priority;
> +	priority += IXGBE_MIN_N_TUPLE_PRIO;
> +	ntuple_ctx->ntuple.priority = priority;

priority = RTE_MIN(IXGBE_MAX_N_TUPLE_PRIO, 
RTE_MAX(IXGBE_MIN_N_TUPLE_PRIO, attr->priority))

otherwise priority 0 maps to 7

> +
> +	/* fixed value for ixgbe */
> +	ntuple_ctx->ntuple.flags = RTE_5TUPLE_FLAGS;
> +
> +	return 0;
> +}
> +
> +static enum ixgbe_5tuple_protocol
> +convert_protocol_type(uint8_t protocol_value)
> +{
> +	if (protocol_value == IPPROTO_TCP)
> +		return IXGBE_FILTER_PROTOCOL_TCP;
> +	else if (protocol_value == IPPROTO_UDP)
> +		return IXGBE_FILTER_PROTOCOL_UDP;
> +	else if (protocol_value == IPPROTO_SCTP)
> +		return IXGBE_FILTER_PROTOCOL_SCTP;
> +	else
> +		return IXGBE_FILTER_PROTOCOL_NONE;
> +}
> +
> +static int
> +ixgbe_flow_ntuple_ctx_to_flow(const struct ci_flow_engine_ctx *ctx,
> +		struct ci_flow *flow,
> +		struct rte_flow_error *error __rte_unused)
> +{
> +	const struct ixgbe_ntuple_ctx *ntuple_ctx = (const struct ixgbe_ntuple_ctx *)ctx;
> +	struct ixgbe_ntuple_flow *ntuple_flow = (struct ixgbe_ntuple_flow *)flow;
> +	const struct rte_eth_ntuple_filter *ntuple = &ntuple_ctx->ntuple;
> +	struct ixgbe_5tuple_filter_info *key = &ntuple_flow->key;
> +
> +	/* mask shape (0 or all-ones) is already guaranteed by the graph */
> +	memset(key, 0, sizeof(*key));
> +
> +	key->dst_ip_mask = ntuple->dst_ip_mask == 0;
> +	key->dst_ip = ntuple->dst_ip;
I'm not sure we need to copy from the flow if the corresponding mask is 
set. For example, in ixgbe_process_ntuple_ipv4(), dst_ip is copied from 
an item independently of the mask. Thus, a user may install two or more 
semantically identical rules with different values in masked-out fields 
and consume all available filters.
> +	key->src_ip_mask = ntuple->src_ip_mask == 0;
> +	key->src_ip = ntuple->src_ip;
> +	key->dst_port_mask = ntuple->dst_port_mask == 0;
> +	key->dst_port = ntuple->dst_port;
> +	key->src_port_mask = ntuple->src_port_mask == 0;
> +	key->src_port = ntuple->src_port;
> +	key->proto_mask = ntuple->proto_mask == 0;
> +	key->proto = convert_protocol_type(ntuple->proto);
> +	key->priority = (uint8_t)ntuple->priority;
> +
> +	ntuple_flow->queue = ntuple->queue;
> +
> +	return 0;
> +}
<snip>

-- 
Regards,
Vladimir



More information about the dev mailing list