net/ice/base: improve flow director masking
[dpdk.git] / drivers / net / ice / base / ice_flow.c
index 6782dfa..370ad9b 100644 (file)
 #define ICE_FLOW_FLD_SZ_GTP_TEID       4
 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID   2
 
-/* Protocol header fields are extracted at the word boundaries as word-sized
- * values. Specify the displacement value of some non-word-aligned fields needed
- * to compute the offset of words containing the fields in the corresponding
- * protocol headers. Displacement values are expressed in number of bits.
- */
-#define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP        (-4)
-#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP        ((-2) * BITS_PER_BYTE)
-#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
-
 /* Describe properties of a protocol header field */
 struct ice_flow_field_info {
        enum ice_flow_seg_hdr hdr;
@@ -67,18 +58,29 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
-       /* IPv4 */
-       /* ICE_FLOW_FIELD_IDX_IP_DSCP */
-       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
-       /* ICE_FLOW_FIELD_IDX_IP_TTL */
-       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
-       /* ICE_FLOW_FIELD_IDX_IP_PROT */
-       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
+       /* IPv4 / IPv6 */
+       /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
+                             0x00fc),
+       /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
+                             0x0ff0),
+       /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
+                             ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
+       /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
+                             ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
+       /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
+                             ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
+       /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
+                             ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
        /* ICE_FLOW_FIELD_IDX_IPV4_SA */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV4_DA */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
-       /* IPv6 */
        /* ICE_FLOW_FIELD_IDX_IPV6_SA */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV6_DA */
@@ -141,9 +143,9 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
  * Packet types for packets with an Outer/First/Single MAC header
  */
 static const u32 ice_ptypes_mac_ofos[] = {
-       0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
-       0x000B0F0F, 0x00003000, 0x00000000, 0x00000000,
+       0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
+       0x0000077E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00003000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -165,9 +167,9 @@ static const u32 ice_ptypes_macvlan_il[] = {
 
 /* Packet types for packets with an Outer/First/Single IPv4 header */
 static const u32 ice_ptypes_ipv4_ofos[] = {
-       0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
+       0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x0003000F, 0x000FC000, 0x00000000, 0x00000000,
+       0x00000000, 0x000FC000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -177,9 +179,9 @@ static const u32 ice_ptypes_ipv4_ofos[] = {
 
 /* Packet types for packets with an Innermost/Last IPv4 header */
 static const u32 ice_ptypes_ipv4_il[] = {
-       0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
-       0x0007700E, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x000FF800, 0x00000000,
+       0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
+       0x0000000E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x001FF800, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -189,9 +191,9 @@ static const u32 ice_ptypes_ipv4_il[] = {
 
 /* Packet types for packets with an Outer/First/Single IPv6 header */
 static const u32 ice_ptypes_ipv6_ofos[] = {
-       0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
-       0x00080F00, 0x03F00000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x77000000, 0x10002000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x03F00000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -201,8 +203,8 @@ static const u32 ice_ptypes_ipv6_ofos[] = {
 
 /* Packet types for packets with an Innermost/Last IPv6 header */
 static const u32 ice_ptypes_ipv6_il[] = {
-       0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
-       0x03B80770, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
+       0x00000770, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -227,8 +229,8 @@ static const u32 ice_ptypes_arp_of[] = {
  * packets with inner UDP.
  */
 static const u32 ice_ptypes_udp_il[] = {
-       0x81000000, 0x20204040, 0x04081010, 0x80810102,
-       0x00204040, 0x00000000, 0x00000000, 0x00000000,
+       0x81000000, 0x20204040, 0x04000010, 0x80810102,
+       0x00000040, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00410000, 0x10842000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -239,8 +241,8 @@ static const u32 ice_ptypes_udp_il[] = {
 
 /* Packet types for packets with an Innermost/Last TCP header */
 static const u32 ice_ptypes_tcp_il[] = {
-       0x04000000, 0x80810102, 0x10204040, 0x02040408,
-       0x00810102, 0x00000000, 0x00000000, 0x00000000,
+       0x04000000, 0x80810102, 0x10000040, 0x02040408,
+       0x00000102, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00820000, 0x21084000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -251,8 +253,8 @@ static const u32 ice_ptypes_tcp_il[] = {
 
 /* Packet types for packets with an Innermost/Last SCTP header */
 static const u32 ice_ptypes_sctp_il[] = {
-       0x08000000, 0x01020204, 0x20408081, 0x04080810,
-       0x01020204, 0x00000000, 0x00000000, 0x00000000,
+       0x08000000, 0x01020204, 0x20000081, 0x04080810,
+       0x00000204, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x01040000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -275,8 +277,8 @@ static const u32 ice_ptypes_icmp_of[] = {
 
 /* Packet types for packets with an Innermost/Last ICMP header */
 static const u32 ice_ptypes_icmp_il[] = {
-       0x00000000, 0x02040408, 0x40810102, 0x08101020,
-       0x02040408, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x02040408, 0x40000102, 0x08101020,
+       0x00000408, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x42108000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -287,8 +289,8 @@ static const u32 ice_ptypes_icmp_il[] = {
 
 /* Packet types for packets with an Outermost/First GRE header */
 static const u32 ice_ptypes_gre_of[] = {
-       0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
+       0x0000017E, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -299,8 +301,8 @@ static const u32 ice_ptypes_gre_of[] = {
 
 /* Packet types for packets with an Innermost/Last MAC header */
 static const u32 ice_ptypes_mac_il[] = {
-       0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
-       0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -608,6 +610,7 @@ ice_flow_xtract_pkt_flags(struct ice_hw *hw,
  * @params: information about the flow to be processed
  * @seg: packet segment index of the field to be extracted
  * @fld: ID of field to be extracted
+ * @match: bitfield of all fields
  *
  * This function determines the protocol ID, offset, and size of the given
  * field. It then allocates one or more extraction sequence entries for the
@@ -615,13 +618,14 @@ ice_flow_xtract_pkt_flags(struct ice_hw *hw,
  */
 static enum ice_status
 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
-                   u8 seg, enum ice_flow_field fld)
+                   u8 seg, enum ice_flow_field fld, u64 match)
 {
        enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
        enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
        u8 fv_words = hw->blk[params->blk].es.fvw;
        struct ice_flow_fld_info *flds;
        u16 cnt, ese_bits, i;
+       u16 sib_mask = 0;
        s16 adj = 0;
        u16 mask;
        u16 off;
@@ -638,35 +642,49 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        case ICE_FLOW_FIELD_IDX_ETH_TYPE:
                prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
                break;
-       case ICE_FLOW_FIELD_IDX_IP_DSCP:
-               if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
-                       adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
-               /* Fall through */
-       case ICE_FLOW_FIELD_IDX_IP_TTL:
-       case ICE_FLOW_FIELD_IDX_IP_PROT:
-               /* Some fields are located at different offsets in IPv4 and
-                * IPv6
+       case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
+               prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
+               prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV4_TTL:
+       case ICE_FLOW_FIELD_IDX_IPV4_PROT:
+               prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
+
+               /* TTL and PROT share the same extraction seq. entry.
+                * Each is considered a sibling to the other in terms of sharing
+                * the same extraction sequence entry.
                 */
-               if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
-                       prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
-                               ICE_PROT_IPV4_IL;
-                       /* TTL and PROT share the same extraction seq. entry.
-                        * Each is considered a sibling to the other in term
-                        * sharing the same extraction sequence entry.
-                        */
-                       if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
-                               sib = ICE_FLOW_FIELD_IDX_IP_PROT;
-                       else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
-                               sib = ICE_FLOW_FIELD_IDX_IP_TTL;
-               } else if (params->prof->segs[seg].hdrs &
-                          ICE_FLOW_SEG_HDR_IPV6) {
-                       prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
-                               ICE_PROT_IPV6_IL;
-                       if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
-                               adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
-                       else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
-                               adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
-               }
+               if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
+                       sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
+               else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
+                       sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
+
+               /* If the sibling field is also included, that field's
+                * mask needs to be included.
+                */
+               if (match & BIT(sib))
+                       sib_mask = ice_flds_info[sib].mask;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV6_TTL:
+       case ICE_FLOW_FIELD_IDX_IPV6_PROT:
+               prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
+
+               /* TTL and PROT share the same extraction seq. entry.
+                * Each is considered a sibling to the other in terms of sharing
+                * the same extraction sequence entry.
+                */
+               if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
+                       sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
+               else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
+                       sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
+
+               /* If the sibling field is also included, that field's
+                * mask needs to be included.
+                */
+               if (match & BIT(sib))
+                       sib_mask = ice_flds_info[sib].mask;
                break;
        case ICE_FLOW_FIELD_IDX_IPV4_SA:
        case ICE_FLOW_FIELD_IDX_IPV4_DA:
@@ -733,6 +751,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
                ICE_FLOW_FV_EXTRACT_SZ;
        flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
        flds[fld].xtrct.idx = params->es_cnt;
+       flds[fld].xtrct.mask = ice_flds_info[fld].mask;
 
        /* Adjust the next field-entry index after accommodating the number of
         * entries this field consumes
@@ -742,7 +761,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
 
        /* Fill in the extraction sequence entries needed for this field */
        off = flds[fld].xtrct.off;
-       mask = ice_flds_info[fld].mask;
+       mask = flds[fld].xtrct.mask;
        for (i = 0; i < cnt; i++) {
                /* Only consume an extraction sequence entry if there is no
                 * sibling field associated with this field or the sibling entry
@@ -767,7 +786,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
 
                        params->es[idx].prot_id = prot_id;
                        params->es[idx].off = off;
-                       params->mask[idx] = mask;
+                       params->mask[idx] = mask | sib_mask;
                        params->es_cnt++;
                }
 
@@ -885,7 +904,8 @@ ice_flow_create_xtrct_seq(struct ice_hw *hw,
 
                        if (match & bit) {
                                status = ice_flow_xtract_fld
-                                       (hw, params, i, (enum ice_flow_field)j);
+                                       (hw, params, i, (enum ice_flow_field)j,
+                                        match);
                                if (status)
                                        return status;
                                match &= ~bit;
@@ -2185,12 +2205,14 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        struct ice_flow_prof *prof;
        enum ice_status status;
 
-       segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
+       segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
+                                                     sizeof(*segs));
        if (!segs)
                return ICE_ERR_NO_MEMORY;
 
        /* Construct the packet segment info from the hashed fields */
-       status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
+       status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
+                                          addl_hdrs);
        if (status)
                goto out;