[PATCH v3 17/19] net/i40e: reimplement tunnel parsers

Medvedkin, Vladimir vladimir.medvedkin at intel.com
Sat Sep 19 18:14:18 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 tunnel filters: QinQ, VXLAN, NVGRE, MPLS, GTP, and L4.
>
> As a result of transitioning to more formalized validation, some
> checks have become more stringent:
>
> - VLAN TCI mask is now required to be fully masked (all-ones); previously
>    the mask was only checked for eth_proto and any non-zero vlan_tci mask
>    value was silently accepted
>
> In addition to using the new graph infrastructure, some of the checks were
> made more stringent and/or more correct. In particular:
>
> - old code did not check for whether fields other than ports are masked
>    (they are now rejected)
> - old code did not check for whether src/ports are fully masked (masks
>    other than full are now rejected)
> - old code used spec to decide which port to copy (as a result, it was not
>    possible to match port 0 - this is now allowed)
>
> Tunnel engine now also share a refcounted global state, and track all
> flows and do deduplication inside the engine.
>
> Signed-off-by: Anatoly Burakov<anatoly.burakov at intel.com>
> ---
<snip>
> +static int
> +i40e_tunnel_node_vlan_validate(const void *ctx __rte_unused, const struct rte_flow_item *item,
> +		struct rte_flow_error *error)
> +{
> +	const struct rte_flow_item_vlan *vlan_mask = item->mask;
> +
> +	/* matching eth proto not supported */
> +	if (vlan_mask->hdr.eth_proto) {
> +		return rte_flow_error_set(error, EINVAL,
> +				RTE_FLOW_ERROR_TYPE_ITEM, item,
> +				"Invalid VLAN mask");
> +	}
> +
> +	/* VLAN TCI must be fully masked */
> +	if (!CI_FIELD_IS_MASKED(&vlan_mask->hdr.vlan_tci)) {
isn't VLAN TCI optional?
> +		return rte_flow_error_set(error, EINVAL,
> +				RTE_FLOW_ERROR_TYPE_ITEM, item,
> +				"Invalid VLAN mask");
> +	}
> +
> +	return 0;
> +}
> +
<snip>
> +static int
> +i40e_tunnel_node_tcp_process(void *ctx, const struct rte_flow_item *item,
> +		struct rte_flow_error *error __rte_unused)
> +{
> +	struct i40e_tunnel_ctx *tunnel_ctx = ctx;
> +	struct i40e_tunnel_filter_conf *tunnel_filter = &tunnel_ctx->filter;
> +	const struct rte_flow_item_tcp *tcp_spec = item->spec;
> +	const struct rte_flow_item_tcp *tcp_mask = item->mask;
> +
> +	if (tcp_mask->hdr.src_port) {
> +		tunnel_filter->l4_port_type = I40E_L4_PORT_TYPE_SRC;
> +		tunnel_filter->tenant_id = rte_be_to_cpu_32(tcp_spec->hdr.src_port);
nit: just as a thought for future improvement: here and for some other 
protocols, use rte_be_to_cpu_16 instead of _32 and fix 
i40e_tunnel_filter_convert_conf?
> +	} else if (tcp_mask->hdr.dst_port) {
> +		tunnel_filter->l4_port_type = I40E_L4_PORT_TYPE_DST;
> +		tunnel_filter->tenant_id = rte_be_to_cpu_32(tcp_spec->hdr.dst_port);
> +	}
> +	tunnel_filter->tunnel_type = I40E_CLOUD_TYPE_TCP;
> +
> +	return 0;
> +}
> +
<snip>

-- 
Regards,
Vladimir



More information about the dev mailing list