[PATCH 3/7] net/ice: fix L2TPv2 inner segment header setup
Shaiq Wani
shaiq.wani at intel.com
Mon Apr 27 04:31:11 CEST 2026
ice_fdir_input_set_hdrs() sets identical headers on both outer and
inner segments and groups all PPP variants into a single fall-through,
so the HW cannot distinguish inner IPv4 from IPv6 or TCP from UDP.
Add a seg_idx parameter and expand each L2TPv2/PPP ptype into its own
case with per-segment header selection. Also ensure the inner segment
headers are always programmed even when no inner fields are extracted,
so ptype-only narrowing works correctly.
Fixes: 733640dae75e ("net/ice: support L2TPv2 flow pattern matching")
Signed-off-by: Shaiq Wani <shaiq.wani at intel.com>
---
drivers/net/intel/ice/ice_fdir_filter.c | 160 +++++++++++++++++++++---
1 file changed, 145 insertions(+), 15 deletions(-)
diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c
index 5ee9edc442..a0cddaeaef 100644
--- a/drivers/net/intel/ice/ice_fdir_filter.c
+++ b/drivers/net/intel/ice/ice_fdir_filter.c
@@ -1022,7 +1022,8 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
}
static void
-ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
+ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg,
+ int seg_idx)
{
switch (flow) {
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
@@ -1130,16 +1131,77 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
ICE_FLOW_SEG_HDR_IPV_OTHER);
break;
case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4:
- case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_UDP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
+ case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV4_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6:
- case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_UDP:
- ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
- ICE_FLOW_SEG_HDR_PPP |
- ICE_FLOW_SEG_HDR_IPV6 |
- ICE_FLOW_SEG_HDR_IPV_OTHER);
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
+ case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV2_PPP_IPV6_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2:
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_CONTROL:
@@ -1148,16 +1210,77 @@ ice_fdir_input_set_hdrs(enum ice_fltr_ptype flow, struct ice_flow_seg_info *seg)
ICE_FLOW_SEG_HDR_IPV_OTHER);
break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4:
- case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_UDP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
+ case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV4_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6:
- case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_UDP:
- ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
- ICE_FLOW_SEG_HDR_PPP |
- ICE_FLOW_SEG_HDR_IPV4 |
- ICE_FLOW_SEG_HDR_IPV_OTHER);
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ break;
+ case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV2_PPP_IPV6_TCP:
+ if (seg_idx == 0)
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV2 |
+ ICE_FLOW_SEG_HDR_PPP |
+ ICE_FLOW_SEG_HDR_IPV4 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
+ else
+ ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
+ ICE_FLOW_SEG_HDR_IPV6 |
+ ICE_FLOW_SEG_HDR_IPV_OTHER);
break;
default:
@@ -1192,15 +1315,22 @@ ice_fdir_input_set_conf(struct ice_pf *pf, enum ice_fltr_ptype flow,
for (k = 0; k <= ICE_FD_HW_SEG_TUN; k++) {
seg = &seg_tun[k];
input_set = (k == ICE_FD_HW_SEG_TUN) ? inner_input_set : outer_input_set;
- if (input_set == 0)
+ if (input_set == 0) {
+ /* For tunnel inner segment, always set headers for
+ * correct ptype narrowing even if no fields extracted.
+ */
+ if (k == ICE_FD_HW_SEG_TUN &&
+ ice_fdir_is_tunnel_profile(ttype))
+ ice_fdir_input_set_hdrs(flow, seg, k);
continue;
+ }
for (i = 0; i < ICE_FLOW_FIELD_IDX_MAX; i++)
field[i] = ICE_FLOW_FIELD_IDX_MAX;
ice_fdir_input_set_parse(input_set, field);
- ice_fdir_input_set_hdrs(flow, seg);
+ ice_fdir_input_set_hdrs(flow, seg, k);
for (i = 0; field[i] != ICE_FLOW_FIELD_IDX_MAX; i++) {
ice_flow_set_fld(seg, field[i],
--
2.43.0
More information about the dev
mailing list