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 <[email protected]>
---
 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

Reply via email to