1c90ed40cSTony Nguyen // SPDX-License-Identifier: GPL-2.0 2c90ed40cSTony Nguyen /* Copyright (c) 2019, Intel Corporation. */ 3c90ed40cSTony Nguyen 4c90ed40cSTony Nguyen #include "ice_common.h" 5c90ed40cSTony Nguyen #include "ice_flow.h" 6c90ed40cSTony Nguyen 7c90ed40cSTony Nguyen /* Describe properties of a protocol header field */ 8c90ed40cSTony Nguyen struct ice_flow_field_info { 9c90ed40cSTony Nguyen enum ice_flow_seg_hdr hdr; 10c90ed40cSTony Nguyen s16 off; /* Offset from start of a protocol header, in bits */ 11c90ed40cSTony Nguyen u16 size; /* Size of fields in bits */ 12b199dddbSQi Zhang u16 mask; /* 16-bit mask for field */ 13c90ed40cSTony Nguyen }; 14c90ed40cSTony Nguyen 15c90ed40cSTony Nguyen #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 16c90ed40cSTony Nguyen .hdr = _hdr, \ 17c90ed40cSTony Nguyen .off = (_offset_bytes) * BITS_PER_BYTE, \ 18c90ed40cSTony Nguyen .size = (_size_bytes) * BITS_PER_BYTE, \ 19b199dddbSQi Zhang .mask = 0, \ 20b199dddbSQi Zhang } 21b199dddbSQi Zhang 22b199dddbSQi Zhang #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \ 23b199dddbSQi Zhang .hdr = _hdr, \ 24b199dddbSQi Zhang .off = (_offset_bytes) * BITS_PER_BYTE, \ 25b199dddbSQi Zhang .size = (_size_bytes) * BITS_PER_BYTE, \ 26b199dddbSQi Zhang .mask = _mask, \ 27c90ed40cSTony Nguyen } 28c90ed40cSTony Nguyen 29c90ed40cSTony Nguyen /* Table containing properties of supported protocol header fields */ 30c90ed40cSTony Nguyen static const 31c90ed40cSTony Nguyen struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 32390bd141SQi Zhang /* Ether */ 33390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ETH_DA */ 34390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 35390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ETH_SA */ 36390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 37390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_S_VLAN */ 38390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)), 39390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_C_VLAN */ 40390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)), 41390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 42390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)), 43c90ed40cSTony Nguyen /* IPv4 / IPv6 */ 44b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 45b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc), 46b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 47b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0), 48b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 49b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00), 50b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 51b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff), 52b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 53b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff), 54b199dddbSQi Zhang /* ICE_FLOW_FIELD_IDX_IPV6_PROT */ 55b199dddbSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00), 56c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 57c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)), 58c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 59c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)), 60c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 61c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)), 62c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 63c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)), 64c90ed40cSTony Nguyen /* Transport */ 65c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 66c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)), 67c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 68c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)), 69c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 70c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)), 71c90ed40cSTony Nguyen /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 72c90ed40cSTony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)), 731c01c8c6SMd Fahad Iqbal Polash /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 741c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)), 751c01c8c6SMd Fahad Iqbal Polash /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 761c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)), 77390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 78390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1), 79390bd141SQi Zhang /* ARP */ 80390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 81390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)), 82390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 83390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)), 84390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 85390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 86390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 87390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 88390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ARP_OP */ 89390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)), 90390bd141SQi Zhang /* ICMP */ 91390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 92390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1), 93390bd141SQi Zhang /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 94390bd141SQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1), 95a4e82a81STony Nguyen /* GRE */ 96a4e82a81STony Nguyen /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 97a4e82a81STony Nguyen ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, 98a4e82a81STony Nguyen sizeof_field(struct gre_full_hdr, key)), 990577313eSQi Zhang /* GTP */ 1000577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPC_TEID */ 1010577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)), 1020577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */ 1030577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)), 1040577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */ 1050577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)), 1060577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */ 1070577313eSQi Zhang ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16), 1080577313eSQi Zhang 0x3f00), 1090577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */ 1100577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)), 1110577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */ 1120577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)), 1130577313eSQi Zhang /* PPPoE */ 1140577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */ 1150577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)), 1160577313eSQi Zhang /* PFCP */ 1170577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_PFCP_SEID */ 1180577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)), 1190577313eSQi Zhang /* L2TPv3 */ 1200577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */ 1210577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)), 1220577313eSQi Zhang /* ESP */ 1230577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_ESP_SPI */ 1240577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)), 1250577313eSQi Zhang /* AH */ 1260577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_AH_SPI */ 1270577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)), 1280577313eSQi Zhang /* NAT_T_ESP */ 1290577313eSQi Zhang /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */ 1300577313eSQi Zhang ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)), 131c90ed40cSTony Nguyen }; 132c90ed40cSTony Nguyen 13331ad4e4eSTony Nguyen /* Bitmaps indicating relevant packet types for a particular protocol header 13431ad4e4eSTony Nguyen * 135390bd141SQi Zhang * Packet types for packets with an Outer/First/Single MAC header 13631ad4e4eSTony Nguyen */ 137390bd141SQi Zhang static const u32 ice_ptypes_mac_ofos[] = { 138390bd141SQi Zhang 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 139390bd141SQi Zhang 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 140390bd141SQi Zhang 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000, 141390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 142390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 143390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 144390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 145390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 146390bd141SQi Zhang }; 147390bd141SQi Zhang 148390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC VLAN header */ 149390bd141SQi Zhang static const u32 ice_ptypes_macvlan_il[] = { 150390bd141SQi Zhang 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 151390bd141SQi Zhang 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 152390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 153390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 154390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 155390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 156390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 157390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 158390bd141SQi Zhang }; 159390bd141SQi Zhang 160390bd141SQi Zhang /* Packet types for packets with an Outer/First/Single IPv4 header */ 16131ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_ofos[] = { 16231ad4e4eSTony Nguyen 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, 1630577313eSQi Zhang 0x00000000, 0x00000155, 0x00000000, 0x00000000, 1640577313eSQi Zhang 0x00000000, 0x000FC000, 0x00000000, 0x00000000, 16531ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16631ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16731ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16831ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16931ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17031ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17231ad4e4eSTony Nguyen }; 17331ad4e4eSTony Nguyen 17431ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv4 header */ 17531ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv4_il[] = { 17631ad4e4eSTony Nguyen 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 17731ad4e4eSTony Nguyen 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 1780577313eSQi Zhang 0x00000000, 0x00000000, 0x001FF800, 0x00000000, 17931ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18031ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18231ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18331ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 18431ad4e4eSTony Nguyen }; 18531ad4e4eSTony Nguyen 18631ad4e4eSTony Nguyen /* Packet types for packets with an Outer/First/Single IPv6 header */ 18731ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_ofos[] = { 18831ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x77000000, 0x10002000, 1890577313eSQi Zhang 0x00000000, 0x000002AA, 0x00000000, 0x00000000, 1900577313eSQi Zhang 0x00000000, 0x03F00000, 0x00000000, 0x00000000, 19131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19231ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19331ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19431ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19531ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19631ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19731ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19831ad4e4eSTony Nguyen }; 19931ad4e4eSTony Nguyen 20031ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last IPv6 header */ 20131ad4e4eSTony Nguyen static const u32 ice_ptypes_ipv6_il[] = { 20231ad4e4eSTony Nguyen 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 20331ad4e4eSTony Nguyen 0x00000770, 0x00000000, 0x00000000, 0x00000000, 2040577313eSQi Zhang 0x00000000, 0x00000000, 0x7FE00000, 0x00000000, 20531ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20631ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20731ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20831ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20931ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21031ad4e4eSTony Nguyen }; 21131ad4e4eSTony Nguyen 212051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */ 213051d2b5cSDan Nowlin static const u32 ice_ipv4_ofos_no_l4[] = { 214051d2b5cSDan Nowlin 0x10C00000, 0x04000800, 0x00000000, 0x00000000, 215051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 216051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 217051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 218051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 219051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 220051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 221051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 222051d2b5cSDan Nowlin }; 223051d2b5cSDan Nowlin 224390bd141SQi Zhang /* Packet types for packets with an Outermost/First ARP header */ 225390bd141SQi Zhang static const u32 ice_ptypes_arp_of[] = { 226390bd141SQi Zhang 0x00000800, 0x00000000, 0x00000000, 0x00000000, 227390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 228390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 229390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 230390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 231390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 232390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 233390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 234390bd141SQi Zhang }; 235390bd141SQi Zhang 236051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 237051d2b5cSDan Nowlin static const u32 ice_ipv4_il_no_l4[] = { 238051d2b5cSDan Nowlin 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 239051d2b5cSDan Nowlin 0x00000008, 0x00000000, 0x00000000, 0x00000000, 240051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 241051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 242051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 243051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 244051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 245051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 246051d2b5cSDan Nowlin }; 247051d2b5cSDan Nowlin 248051d2b5cSDan Nowlin /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */ 249051d2b5cSDan Nowlin static const u32 ice_ipv6_ofos_no_l4[] = { 250051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x43000000, 0x10002000, 251051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 252051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 253051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 254051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 255051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 256051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 257051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 258051d2b5cSDan Nowlin }; 259051d2b5cSDan Nowlin 260051d2b5cSDan Nowlin /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 261051d2b5cSDan Nowlin static const u32 ice_ipv6_il_no_l4[] = { 262051d2b5cSDan Nowlin 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 263051d2b5cSDan Nowlin 0x00000430, 0x00000000, 0x00000000, 0x00000000, 264051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 265051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 266051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 267051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 268051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 269051d2b5cSDan Nowlin 0x00000000, 0x00000000, 0x00000000, 0x00000000, 270051d2b5cSDan Nowlin }; 271051d2b5cSDan Nowlin 27231ad4e4eSTony Nguyen /* UDP Packet types for non-tunneled packets or tunneled 27331ad4e4eSTony Nguyen * packets with inner UDP. 27431ad4e4eSTony Nguyen */ 27531ad4e4eSTony Nguyen static const u32 ice_ptypes_udp_il[] = { 27631ad4e4eSTony Nguyen 0x81000000, 0x20204040, 0x04000010, 0x80810102, 27731ad4e4eSTony Nguyen 0x00000040, 0x00000000, 0x00000000, 0x00000000, 2780577313eSQi Zhang 0x00000000, 0x00410000, 0x90842000, 0x00000007, 27931ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28031ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28231ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28331ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 28431ad4e4eSTony Nguyen }; 28531ad4e4eSTony Nguyen 28631ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last TCP header */ 28731ad4e4eSTony Nguyen static const u32 ice_ptypes_tcp_il[] = { 28831ad4e4eSTony Nguyen 0x04000000, 0x80810102, 0x10000040, 0x02040408, 28931ad4e4eSTony Nguyen 0x00000102, 0x00000000, 0x00000000, 0x00000000, 2900577313eSQi Zhang 0x00000000, 0x00820000, 0x21084000, 0x00000000, 29131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29231ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29331ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29431ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29531ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29631ad4e4eSTony Nguyen }; 29731ad4e4eSTony Nguyen 29831ad4e4eSTony Nguyen /* Packet types for packets with an Innermost/Last SCTP header */ 29931ad4e4eSTony Nguyen static const u32 ice_ptypes_sctp_il[] = { 30031ad4e4eSTony Nguyen 0x08000000, 0x01020204, 0x20000081, 0x04080810, 30131ad4e4eSTony Nguyen 0x00000204, 0x00000000, 0x00000000, 0x00000000, 3020577313eSQi Zhang 0x00000000, 0x01040000, 0x00000000, 0x00000000, 30331ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30431ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30531ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30631ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30731ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 308390bd141SQi Zhang }; 309390bd141SQi Zhang 310390bd141SQi Zhang /* Packet types for packets with an Outermost/First ICMP header */ 311390bd141SQi Zhang static const u32 ice_ptypes_icmp_of[] = { 312390bd141SQi Zhang 0x10000000, 0x00000000, 0x00000000, 0x00000000, 313390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 314390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 315390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 316390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 317390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 318390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 319390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 320390bd141SQi Zhang }; 321390bd141SQi Zhang 322390bd141SQi Zhang /* Packet types for packets with an Innermost/Last ICMP header */ 323390bd141SQi Zhang static const u32 ice_ptypes_icmp_il[] = { 324390bd141SQi Zhang 0x00000000, 0x02040408, 0x40000102, 0x08101020, 325390bd141SQi Zhang 0x00000408, 0x00000000, 0x00000000, 0x00000000, 326390bd141SQi Zhang 0x00000000, 0x00000000, 0x42108000, 0x00000000, 327390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 328390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 329390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 330390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33131ad4e4eSTony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33231ad4e4eSTony Nguyen }; 33331ad4e4eSTony Nguyen 334a4e82a81STony Nguyen /* Packet types for packets with an Outermost/First GRE header */ 335a4e82a81STony Nguyen static const u32 ice_ptypes_gre_of[] = { 336a4e82a81STony Nguyen 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, 337a4e82a81STony Nguyen 0x0000017E, 0x00000000, 0x00000000, 0x00000000, 338a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 339a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 340a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 341a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 342a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 343a4e82a81STony Nguyen 0x00000000, 0x00000000, 0x00000000, 0x00000000, 344a4e82a81STony Nguyen }; 345a4e82a81STony Nguyen 346390bd141SQi Zhang /* Packet types for packets with an Innermost/Last MAC header */ 347390bd141SQi Zhang static const u32 ice_ptypes_mac_il[] = { 348390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 349390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 350390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 351390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 352390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 353390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 354390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 355390bd141SQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 356390bd141SQi Zhang }; 357390bd141SQi Zhang 3580577313eSQi Zhang /* Packet types for GTPC */ 3590577313eSQi Zhang static const u32 ice_ptypes_gtpc[] = { 3600577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3610577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3620577313eSQi Zhang 0x00000000, 0x00000000, 0x00000180, 0x00000000, 3630577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3640577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3650577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3660577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3670577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3680577313eSQi Zhang }; 3690577313eSQi Zhang 3700577313eSQi Zhang /* Packet types for GTPC with TEID */ 3710577313eSQi Zhang static const u32 ice_ptypes_gtpc_tid[] = { 3720577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3730577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3740577313eSQi Zhang 0x00000000, 0x00000000, 0x00000060, 0x00000000, 3750577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3760577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3770577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3780577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3790577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 3800577313eSQi Zhang }; 3810577313eSQi Zhang 382*cbad5db8SQi Zhang /* Packet types for GTPU */ 383*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = { 384*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 385*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 386*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 387*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 388*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 389*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 390*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 391*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 392*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 393*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 394*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 395*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 396*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 397*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 398*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 399*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 400*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 401*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 402*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 403*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 404*cbad5db8SQi Zhang }; 405*cbad5db8SQi Zhang 406*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_down[] = { 407*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 408*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 409*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 410*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 411*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 412*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 413*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 414*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 415*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 416*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 417*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 418*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 419*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 420*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 421*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 422*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 423*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 424*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 425*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 426*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 427*cbad5db8SQi Zhang }; 428*cbad5db8SQi Zhang 429*cbad5db8SQi Zhang static const struct ice_ptype_attributes ice_attr_gtpu_up[] = { 430*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 431*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 432*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 433*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 434*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 435*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 436*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 437*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 438*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 439*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 440*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 441*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 442*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 443*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 444*cbad5db8SQi Zhang { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 445*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 446*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 447*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 448*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 449*cbad5db8SQi Zhang { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 450*cbad5db8SQi Zhang }; 451*cbad5db8SQi Zhang 4520577313eSQi Zhang static const u32 ice_ptypes_gtpu[] = { 4530577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4540577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4550577313eSQi Zhang 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000, 4560577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4570577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4580577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4590577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4600577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4610577313eSQi Zhang }; 4620577313eSQi Zhang 4630577313eSQi Zhang /* Packet types for PPPoE */ 4640577313eSQi Zhang static const u32 ice_ptypes_pppoe[] = { 4650577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4660577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4670577313eSQi Zhang 0x00000000, 0x03ffe000, 0x00000000, 0x00000000, 4680577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4690577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4700577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4710577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4720577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4730577313eSQi Zhang }; 4740577313eSQi Zhang 4750577313eSQi Zhang /* Packet types for packets with PFCP NODE header */ 4760577313eSQi Zhang static const u32 ice_ptypes_pfcp_node[] = { 4770577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4780577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4790577313eSQi Zhang 0x00000000, 0x00000000, 0x80000000, 0x00000002, 4800577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4810577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4820577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4830577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4840577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4850577313eSQi Zhang }; 4860577313eSQi Zhang 4870577313eSQi Zhang /* Packet types for packets with PFCP SESSION header */ 4880577313eSQi Zhang static const u32 ice_ptypes_pfcp_session[] = { 4890577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4900577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4910577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000005, 4920577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4930577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4940577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4950577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4960577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 4970577313eSQi Zhang }; 4980577313eSQi Zhang 4990577313eSQi Zhang /* Packet types for L2TPv3 */ 5000577313eSQi Zhang static const u32 ice_ptypes_l2tpv3[] = { 5010577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5020577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5030577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000300, 5040577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5050577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5060577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5070577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5080577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5090577313eSQi Zhang }; 5100577313eSQi Zhang 5110577313eSQi Zhang /* Packet types for ESP */ 5120577313eSQi Zhang static const u32 ice_ptypes_esp[] = { 5130577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5140577313eSQi Zhang 0x00000000, 0x00000003, 0x00000000, 0x00000000, 5150577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5160577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5170577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5180577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5190577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5200577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5210577313eSQi Zhang }; 5220577313eSQi Zhang 5230577313eSQi Zhang /* Packet types for AH */ 5240577313eSQi Zhang static const u32 ice_ptypes_ah[] = { 5250577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5260577313eSQi Zhang 0x00000000, 0x0000000C, 0x00000000, 0x00000000, 5270577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5280577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5290577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5300577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5310577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5320577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5330577313eSQi Zhang }; 5340577313eSQi Zhang 5350577313eSQi Zhang /* Packet types for packets with NAT_T ESP header */ 5360577313eSQi Zhang static const u32 ice_ptypes_nat_t_esp[] = { 5370577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5380577313eSQi Zhang 0x00000000, 0x00000030, 0x00000000, 0x00000000, 5390577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5400577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5410577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5420577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5430577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5440577313eSQi Zhang 0x00000000, 0x00000000, 0x00000000, 0x00000000, 5450577313eSQi Zhang }; 5460577313eSQi Zhang 54731ad4e4eSTony Nguyen /* Manage parameters and info. used during the creation of a flow profile */ 54831ad4e4eSTony Nguyen struct ice_flow_prof_params { 54931ad4e4eSTony Nguyen enum ice_block blk; 55031ad4e4eSTony Nguyen u16 entry_length; /* # of bytes formatted entry will require */ 55131ad4e4eSTony Nguyen u8 es_cnt; 55231ad4e4eSTony Nguyen struct ice_flow_prof *prof; 55331ad4e4eSTony Nguyen 55431ad4e4eSTony Nguyen /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 55531ad4e4eSTony Nguyen * This will give us the direction flags. 55631ad4e4eSTony Nguyen */ 55731ad4e4eSTony Nguyen struct ice_fv_word es[ICE_MAX_FV_WORDS]; 558*cbad5db8SQi Zhang /* attributes can be used to add attributes to a particular PTYPE */ 559*cbad5db8SQi Zhang const struct ice_ptype_attributes *attr; 560*cbad5db8SQi Zhang u16 attr_cnt; 561b199dddbSQi Zhang 562b199dddbSQi Zhang u16 mask[ICE_MAX_FV_WORDS]; 56331ad4e4eSTony Nguyen DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); 56431ad4e4eSTony Nguyen }; 56531ad4e4eSTony Nguyen 5660577313eSQi Zhang #define ICE_FLOW_RSS_HDRS_INNER_MASK \ 5670577313eSQi Zhang (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \ 5680577313eSQi Zhang ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \ 5690577313eSQi Zhang ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \ 5700577313eSQi Zhang ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \ 5710577313eSQi Zhang ICE_FLOW_SEG_HDR_NAT_T_ESP) 5720577313eSQi Zhang 5730577313eSQi Zhang #define ICE_FLOW_SEG_HDRS_L2_MASK \ 5740577313eSQi Zhang (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 57531ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L3_MASK \ 576390bd141SQi Zhang (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) 57731ad4e4eSTony Nguyen #define ICE_FLOW_SEG_HDRS_L4_MASK \ 578390bd141SQi Zhang (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 579390bd141SQi Zhang ICE_FLOW_SEG_HDR_SCTP) 58031ad4e4eSTony Nguyen 58131ad4e4eSTony Nguyen /** 58231ad4e4eSTony Nguyen * ice_flow_val_hdrs - validates packet segments for valid protocol headers 58331ad4e4eSTony Nguyen * @segs: array of one or more packet segments that describe the flow 58431ad4e4eSTony Nguyen * @segs_cnt: number of packet segments provided 58531ad4e4eSTony Nguyen */ 58631ad4e4eSTony Nguyen static enum ice_status 58731ad4e4eSTony Nguyen ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 58831ad4e4eSTony Nguyen { 58931ad4e4eSTony Nguyen u8 i; 59031ad4e4eSTony Nguyen 59131ad4e4eSTony Nguyen for (i = 0; i < segs_cnt; i++) { 59231ad4e4eSTony Nguyen /* Multiple L3 headers */ 59331ad4e4eSTony Nguyen if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 59431ad4e4eSTony Nguyen !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 59531ad4e4eSTony Nguyen return ICE_ERR_PARAM; 59631ad4e4eSTony Nguyen 59731ad4e4eSTony Nguyen /* Multiple L4 headers */ 59831ad4e4eSTony Nguyen if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 59931ad4e4eSTony Nguyen !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 60031ad4e4eSTony Nguyen return ICE_ERR_PARAM; 60131ad4e4eSTony Nguyen } 60231ad4e4eSTony Nguyen 60331ad4e4eSTony Nguyen return 0; 60431ad4e4eSTony Nguyen } 60531ad4e4eSTony Nguyen 6062c57ffcbSHenry Tieman /* Sizes of fixed known protocol headers without header options */ 6072c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_MAC 14 608390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2) 6092c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV4 20 6102c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_IPV6 40 611390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ARP 28 612390bd141SQi Zhang #define ICE_FLOW_PROT_HDR_SZ_ICMP 8 6132c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_TCP 20 6142c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_UDP 8 6152c57ffcbSHenry Tieman #define ICE_FLOW_PROT_HDR_SZ_SCTP 12 6162c57ffcbSHenry Tieman 6172c57ffcbSHenry Tieman /** 6182c57ffcbSHenry Tieman * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers 6192c57ffcbSHenry Tieman * @params: information about the flow to be processed 6202c57ffcbSHenry Tieman * @seg: index of packet segment whose header size is to be determined 6212c57ffcbSHenry Tieman */ 6222c57ffcbSHenry Tieman static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg) 6232c57ffcbSHenry Tieman { 624390bd141SQi Zhang u16 sz; 625390bd141SQi Zhang 626390bd141SQi Zhang /* L2 headers */ 627390bd141SQi Zhang sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ? 628390bd141SQi Zhang ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC; 6292c57ffcbSHenry Tieman 6302c57ffcbSHenry Tieman /* L3 headers */ 6312c57ffcbSHenry Tieman if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) 6322c57ffcbSHenry Tieman sz += ICE_FLOW_PROT_HDR_SZ_IPV4; 6332c57ffcbSHenry Tieman else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) 6342c57ffcbSHenry Tieman sz += ICE_FLOW_PROT_HDR_SZ_IPV6; 635390bd141SQi Zhang else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP) 636390bd141SQi Zhang sz += ICE_FLOW_PROT_HDR_SZ_ARP; 637390bd141SQi Zhang else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK) 638390bd141SQi Zhang /* An L3 header is required if L4 is specified */ 639390bd141SQi Zhang return 0; 6402c57ffcbSHenry Tieman 6412c57ffcbSHenry Tieman /* L4 headers */ 642390bd141SQi Zhang if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP) 643390bd141SQi Zhang sz += ICE_FLOW_PROT_HDR_SZ_ICMP; 644390bd141SQi Zhang else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP) 6452c57ffcbSHenry Tieman sz += ICE_FLOW_PROT_HDR_SZ_TCP; 6462c57ffcbSHenry Tieman else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP) 6472c57ffcbSHenry Tieman sz += ICE_FLOW_PROT_HDR_SZ_UDP; 6482c57ffcbSHenry Tieman else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP) 6492c57ffcbSHenry Tieman sz += ICE_FLOW_PROT_HDR_SZ_SCTP; 6502c57ffcbSHenry Tieman 6512c57ffcbSHenry Tieman return sz; 6522c57ffcbSHenry Tieman } 6532c57ffcbSHenry Tieman 65431ad4e4eSTony Nguyen /** 65531ad4e4eSTony Nguyen * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 65631ad4e4eSTony Nguyen * @params: information about the flow to be processed 65731ad4e4eSTony Nguyen * 65831ad4e4eSTony Nguyen * This function identifies the packet types associated with the protocol 65931ad4e4eSTony Nguyen * headers being present in packet segments of the specified flow profile. 66031ad4e4eSTony Nguyen */ 66131ad4e4eSTony Nguyen static enum ice_status 66231ad4e4eSTony Nguyen ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 66331ad4e4eSTony Nguyen { 66431ad4e4eSTony Nguyen struct ice_flow_prof *prof; 66531ad4e4eSTony Nguyen u8 i; 66631ad4e4eSTony Nguyen 66731ad4e4eSTony Nguyen memset(params->ptypes, 0xff, sizeof(params->ptypes)); 66831ad4e4eSTony Nguyen 66931ad4e4eSTony Nguyen prof = params->prof; 67031ad4e4eSTony Nguyen 67131ad4e4eSTony Nguyen for (i = 0; i < params->prof->segs_cnt; i++) { 67231ad4e4eSTony Nguyen const unsigned long *src; 67331ad4e4eSTony Nguyen u32 hdrs; 67431ad4e4eSTony Nguyen 67531ad4e4eSTony Nguyen hdrs = prof->segs[i].hdrs; 67631ad4e4eSTony Nguyen 677390bd141SQi Zhang if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 678390bd141SQi Zhang src = !i ? (const unsigned long *)ice_ptypes_mac_ofos : 679390bd141SQi Zhang (const unsigned long *)ice_ptypes_mac_il; 680390bd141SQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 681390bd141SQi Zhang ICE_FLOW_PTYPE_MAX); 682390bd141SQi Zhang } 683390bd141SQi Zhang 684390bd141SQi Zhang if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 685390bd141SQi Zhang src = (const unsigned long *)ice_ptypes_macvlan_il; 686390bd141SQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 687390bd141SQi Zhang ICE_FLOW_PTYPE_MAX); 688390bd141SQi Zhang } 689390bd141SQi Zhang 690390bd141SQi Zhang if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 691390bd141SQi Zhang bitmap_and(params->ptypes, params->ptypes, 692390bd141SQi Zhang (const unsigned long *)ice_ptypes_arp_of, 693390bd141SQi Zhang ICE_FLOW_PTYPE_MAX); 694390bd141SQi Zhang } 695051d2b5cSDan Nowlin if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 696051d2b5cSDan Nowlin !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) { 697051d2b5cSDan Nowlin src = !i ? (const unsigned long *)ice_ipv4_ofos_no_l4 : 698051d2b5cSDan Nowlin (const unsigned long *)ice_ipv4_il_no_l4; 699051d2b5cSDan Nowlin bitmap_and(params->ptypes, params->ptypes, src, 700051d2b5cSDan Nowlin ICE_FLOW_PTYPE_MAX); 701051d2b5cSDan Nowlin } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 70231ad4e4eSTony Nguyen src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos : 70331ad4e4eSTony Nguyen (const unsigned long *)ice_ptypes_ipv4_il; 70431ad4e4eSTony Nguyen bitmap_and(params->ptypes, params->ptypes, src, 70531ad4e4eSTony Nguyen ICE_FLOW_PTYPE_MAX); 706051d2b5cSDan Nowlin } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 707051d2b5cSDan Nowlin !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) { 708051d2b5cSDan Nowlin src = !i ? (const unsigned long *)ice_ipv6_ofos_no_l4 : 709051d2b5cSDan Nowlin (const unsigned long *)ice_ipv6_il_no_l4; 710051d2b5cSDan Nowlin bitmap_and(params->ptypes, params->ptypes, src, 711051d2b5cSDan Nowlin ICE_FLOW_PTYPE_MAX); 71231ad4e4eSTony Nguyen } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 71331ad4e4eSTony Nguyen src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos : 71431ad4e4eSTony Nguyen (const unsigned long *)ice_ptypes_ipv6_il; 71531ad4e4eSTony Nguyen bitmap_and(params->ptypes, params->ptypes, src, 71631ad4e4eSTony Nguyen ICE_FLOW_PTYPE_MAX); 71731ad4e4eSTony Nguyen } 71831ad4e4eSTony Nguyen 7190577313eSQi Zhang if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) { 7200577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pppoe; 7210577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7220577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7230577313eSQi Zhang } else { 7240577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pppoe; 7250577313eSQi Zhang bitmap_andnot(params->ptypes, params->ptypes, src, 7260577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7270577313eSQi Zhang } 7280577313eSQi Zhang 72931ad4e4eSTony Nguyen if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 73031ad4e4eSTony Nguyen src = (const unsigned long *)ice_ptypes_udp_il; 73131ad4e4eSTony Nguyen bitmap_and(params->ptypes, params->ptypes, src, 73231ad4e4eSTony Nguyen ICE_FLOW_PTYPE_MAX); 73331ad4e4eSTony Nguyen } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 73431ad4e4eSTony Nguyen bitmap_and(params->ptypes, params->ptypes, 73531ad4e4eSTony Nguyen (const unsigned long *)ice_ptypes_tcp_il, 73631ad4e4eSTony Nguyen ICE_FLOW_PTYPE_MAX); 73731ad4e4eSTony Nguyen } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 73831ad4e4eSTony Nguyen src = (const unsigned long *)ice_ptypes_sctp_il; 73931ad4e4eSTony Nguyen bitmap_and(params->ptypes, params->ptypes, src, 74031ad4e4eSTony Nguyen ICE_FLOW_PTYPE_MAX); 741390bd141SQi Zhang } 742390bd141SQi Zhang 743390bd141SQi Zhang if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 744390bd141SQi Zhang src = !i ? (const unsigned long *)ice_ptypes_icmp_of : 745390bd141SQi Zhang (const unsigned long *)ice_ptypes_icmp_il; 746390bd141SQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 747390bd141SQi Zhang ICE_FLOW_PTYPE_MAX); 748a4e82a81STony Nguyen } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 749a4e82a81STony Nguyen if (!i) { 750a4e82a81STony Nguyen src = (const unsigned long *)ice_ptypes_gre_of; 751a4e82a81STony Nguyen bitmap_and(params->ptypes, params->ptypes, 752a4e82a81STony Nguyen src, ICE_FLOW_PTYPE_MAX); 753a4e82a81STony Nguyen } 7540577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) { 7550577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpc; 7560577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7570577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7580577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) { 7590577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpc_tid; 7600577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7610577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7620577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) { 7630577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpu; 7640577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7650577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 766*cbad5db8SQi Zhang 767*cbad5db8SQi Zhang /* Attributes for GTP packet with downlink */ 768*cbad5db8SQi Zhang params->attr = ice_attr_gtpu_down; 769*cbad5db8SQi Zhang params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down); 7700577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) { 7710577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpu; 7720577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7730577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 774*cbad5db8SQi Zhang 775*cbad5db8SQi Zhang /* Attributes for GTP packet with uplink */ 776*cbad5db8SQi Zhang params->attr = ice_attr_gtpu_up; 777*cbad5db8SQi Zhang params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up); 7780577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) { 7790577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpu; 7800577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7810577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 782*cbad5db8SQi Zhang 783*cbad5db8SQi Zhang /* Attributes for GTP packet with Extension Header */ 784*cbad5db8SQi Zhang params->attr = ice_attr_gtpu_eh; 785*cbad5db8SQi Zhang params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh); 7860577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) { 7870577313eSQi Zhang src = (const unsigned long *)ice_ptypes_gtpu; 7880577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7890577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7900577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) { 7910577313eSQi Zhang src = (const unsigned long *)ice_ptypes_l2tpv3; 7920577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7930577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7940577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) { 7950577313eSQi Zhang src = (const unsigned long *)ice_ptypes_esp; 7960577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 7970577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 7980577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_AH) { 7990577313eSQi Zhang src = (const unsigned long *)ice_ptypes_ah; 8000577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 8010577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 8020577313eSQi Zhang } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) { 8030577313eSQi Zhang src = (const unsigned long *)ice_ptypes_nat_t_esp; 8040577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 8050577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 8060577313eSQi Zhang } 8070577313eSQi Zhang 8080577313eSQi Zhang if (hdrs & ICE_FLOW_SEG_HDR_PFCP) { 8090577313eSQi Zhang if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE) 8100577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pfcp_node; 8110577313eSQi Zhang else 8120577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pfcp_session; 8130577313eSQi Zhang 8140577313eSQi Zhang bitmap_and(params->ptypes, params->ptypes, src, 8150577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 8160577313eSQi Zhang } else { 8170577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pfcp_node; 8180577313eSQi Zhang bitmap_andnot(params->ptypes, params->ptypes, src, 8190577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 8200577313eSQi Zhang 8210577313eSQi Zhang src = (const unsigned long *)ice_ptypes_pfcp_session; 8220577313eSQi Zhang bitmap_andnot(params->ptypes, params->ptypes, src, 8230577313eSQi Zhang ICE_FLOW_PTYPE_MAX); 82431ad4e4eSTony Nguyen } 82531ad4e4eSTony Nguyen } 82631ad4e4eSTony Nguyen 82731ad4e4eSTony Nguyen return 0; 82831ad4e4eSTony Nguyen } 82931ad4e4eSTony Nguyen 83031ad4e4eSTony Nguyen /** 83131ad4e4eSTony Nguyen * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 83231ad4e4eSTony Nguyen * @hw: pointer to the HW struct 83331ad4e4eSTony Nguyen * @params: information about the flow to be processed 83431ad4e4eSTony Nguyen * @seg: packet segment index of the field to be extracted 83531ad4e4eSTony Nguyen * @fld: ID of field to be extracted 836b199dddbSQi Zhang * @match: bit field of all fields 83731ad4e4eSTony Nguyen * 83831ad4e4eSTony Nguyen * This function determines the protocol ID, offset, and size of the given 83931ad4e4eSTony Nguyen * field. It then allocates one or more extraction sequence entries for the 84031ad4e4eSTony Nguyen * given field, and fill the entries with protocol ID and offset information. 84131ad4e4eSTony Nguyen */ 84231ad4e4eSTony Nguyen static enum ice_status 84331ad4e4eSTony Nguyen ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 844b199dddbSQi Zhang u8 seg, enum ice_flow_field fld, u64 match) 84531ad4e4eSTony Nguyen { 846b199dddbSQi Zhang enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 84731ad4e4eSTony Nguyen enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 84831ad4e4eSTony Nguyen u8 fv_words = hw->blk[params->blk].es.fvw; 84931ad4e4eSTony Nguyen struct ice_flow_fld_info *flds; 85031ad4e4eSTony Nguyen u16 cnt, ese_bits, i; 851b199dddbSQi Zhang u16 sib_mask = 0; 852b199dddbSQi Zhang u16 mask; 85331ad4e4eSTony Nguyen u16 off; 85431ad4e4eSTony Nguyen 85531ad4e4eSTony Nguyen flds = params->prof->segs[seg].fields; 85631ad4e4eSTony Nguyen 85731ad4e4eSTony Nguyen switch (fld) { 858390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ETH_DA: 859390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ETH_SA: 860390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_S_VLAN: 861390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_C_VLAN: 862390bd141SQi Zhang prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 863390bd141SQi Zhang break; 864390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ETH_TYPE: 865390bd141SQi Zhang prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 866390bd141SQi Zhang break; 867b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 868b199dddbSQi Zhang prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 869b199dddbSQi Zhang break; 870b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 871b199dddbSQi Zhang prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 872b199dddbSQi Zhang break; 873b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV4_TTL: 874b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV4_PROT: 875b199dddbSQi Zhang prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 876b199dddbSQi Zhang 877b199dddbSQi Zhang /* TTL and PROT share the same extraction seq. entry. 878b199dddbSQi Zhang * Each is considered a sibling to the other in terms of sharing 879b199dddbSQi Zhang * the same extraction sequence entry. 880b199dddbSQi Zhang */ 881b199dddbSQi Zhang if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 882b199dddbSQi Zhang sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 883b199dddbSQi Zhang else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT) 884b199dddbSQi Zhang sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 885b199dddbSQi Zhang 886b199dddbSQi Zhang /* If the sibling field is also included, that field's 887b199dddbSQi Zhang * mask needs to be included. 888b199dddbSQi Zhang */ 889b199dddbSQi Zhang if (match & BIT(sib)) 890b199dddbSQi Zhang sib_mask = ice_flds_info[sib].mask; 891b199dddbSQi Zhang break; 892b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV6_TTL: 893b199dddbSQi Zhang case ICE_FLOW_FIELD_IDX_IPV6_PROT: 894b199dddbSQi Zhang prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 895b199dddbSQi Zhang 896b199dddbSQi Zhang /* TTL and PROT share the same extraction seq. entry. 897b199dddbSQi Zhang * Each is considered a sibling to the other in terms of sharing 898b199dddbSQi Zhang * the same extraction sequence entry. 899b199dddbSQi Zhang */ 900b199dddbSQi Zhang if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 901b199dddbSQi Zhang sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 902b199dddbSQi Zhang else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT) 903b199dddbSQi Zhang sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 904b199dddbSQi Zhang 905b199dddbSQi Zhang /* If the sibling field is also included, that field's 906b199dddbSQi Zhang * mask needs to be included. 907b199dddbSQi Zhang */ 908b199dddbSQi Zhang if (match & BIT(sib)) 909b199dddbSQi Zhang sib_mask = ice_flds_info[sib].mask; 910b199dddbSQi Zhang break; 91131ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_IPV4_SA: 91231ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_IPV4_DA: 91331ad4e4eSTony Nguyen prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 91431ad4e4eSTony Nguyen break; 91531ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_IPV6_SA: 91631ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_IPV6_DA: 91731ad4e4eSTony Nguyen prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 91831ad4e4eSTony Nguyen break; 91931ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 92031ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 921390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 92231ad4e4eSTony Nguyen prot_id = ICE_PROT_TCP_IL; 92331ad4e4eSTony Nguyen break; 92431ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 92531ad4e4eSTony Nguyen case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 92631ad4e4eSTony Nguyen prot_id = ICE_PROT_UDP_IL_OR_S; 92731ad4e4eSTony Nguyen break; 9281c01c8c6SMd Fahad Iqbal Polash case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 9291c01c8c6SMd Fahad Iqbal Polash case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 9301c01c8c6SMd Fahad Iqbal Polash prot_id = ICE_PROT_SCTP_IL; 9311c01c8c6SMd Fahad Iqbal Polash break; 9320577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPC_TEID: 9330577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID: 9340577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID: 9350577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID: 9360577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID: 9370577313eSQi Zhang case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI: 9380577313eSQi Zhang /* GTP is accessed through UDP OF protocol */ 9390577313eSQi Zhang prot_id = ICE_PROT_UDP_OF; 9400577313eSQi Zhang break; 9410577313eSQi Zhang case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID: 9420577313eSQi Zhang prot_id = ICE_PROT_PPPOE; 9430577313eSQi Zhang break; 9440577313eSQi Zhang case ICE_FLOW_FIELD_IDX_PFCP_SEID: 9450577313eSQi Zhang prot_id = ICE_PROT_UDP_IL_OR_S; 9460577313eSQi Zhang break; 9470577313eSQi Zhang case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID: 9480577313eSQi Zhang prot_id = ICE_PROT_L2TPV3; 9490577313eSQi Zhang break; 9500577313eSQi Zhang case ICE_FLOW_FIELD_IDX_ESP_SPI: 9510577313eSQi Zhang prot_id = ICE_PROT_ESP_F; 9520577313eSQi Zhang break; 9530577313eSQi Zhang case ICE_FLOW_FIELD_IDX_AH_SPI: 9540577313eSQi Zhang prot_id = ICE_PROT_ESP_2; 9550577313eSQi Zhang break; 9560577313eSQi Zhang case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI: 9570577313eSQi Zhang prot_id = ICE_PROT_UDP_IL_OR_S; 9580577313eSQi Zhang break; 959390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ARP_SIP: 960390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ARP_DIP: 961390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ARP_SHA: 962390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ARP_DHA: 963390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ARP_OP: 964390bd141SQi Zhang prot_id = ICE_PROT_ARP_OF; 965390bd141SQi Zhang break; 966390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 967390bd141SQi Zhang case ICE_FLOW_FIELD_IDX_ICMP_CODE: 968390bd141SQi Zhang /* ICMP type and code share the same extraction seq. entry */ 969390bd141SQi Zhang prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? 970390bd141SQi Zhang ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 971b199dddbSQi Zhang sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 972b199dddbSQi Zhang ICE_FLOW_FIELD_IDX_ICMP_CODE : 973b199dddbSQi Zhang ICE_FLOW_FIELD_IDX_ICMP_TYPE; 974390bd141SQi Zhang break; 975a4e82a81STony Nguyen case ICE_FLOW_FIELD_IDX_GRE_KEYID: 976a4e82a81STony Nguyen prot_id = ICE_PROT_GRE_OF; 977a4e82a81STony Nguyen break; 97831ad4e4eSTony Nguyen default: 97931ad4e4eSTony Nguyen return ICE_ERR_NOT_IMPL; 98031ad4e4eSTony Nguyen } 98131ad4e4eSTony Nguyen 98231ad4e4eSTony Nguyen /* Each extraction sequence entry is a word in size, and extracts a 98331ad4e4eSTony Nguyen * word-aligned offset from a protocol header. 98431ad4e4eSTony Nguyen */ 98531ad4e4eSTony Nguyen ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 98631ad4e4eSTony Nguyen 98731ad4e4eSTony Nguyen flds[fld].xtrct.prot_id = prot_id; 98831ad4e4eSTony Nguyen flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 98931ad4e4eSTony Nguyen ICE_FLOW_FV_EXTRACT_SZ; 99031ad4e4eSTony Nguyen flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 99131ad4e4eSTony Nguyen flds[fld].xtrct.idx = params->es_cnt; 992b199dddbSQi Zhang flds[fld].xtrct.mask = ice_flds_info[fld].mask; 99331ad4e4eSTony Nguyen 99431ad4e4eSTony Nguyen /* Adjust the next field-entry index after accommodating the number of 99531ad4e4eSTony Nguyen * entries this field consumes 99631ad4e4eSTony Nguyen */ 99731ad4e4eSTony Nguyen cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size, 99831ad4e4eSTony Nguyen ese_bits); 99931ad4e4eSTony Nguyen 100031ad4e4eSTony Nguyen /* Fill in the extraction sequence entries needed for this field */ 100131ad4e4eSTony Nguyen off = flds[fld].xtrct.off; 1002b199dddbSQi Zhang mask = flds[fld].xtrct.mask; 100331ad4e4eSTony Nguyen for (i = 0; i < cnt; i++) { 1004b199dddbSQi Zhang /* Only consume an extraction sequence entry if there is no 1005b199dddbSQi Zhang * sibling field associated with this field or the sibling entry 1006b199dddbSQi Zhang * already extracts the word shared with this field. 1007b199dddbSQi Zhang */ 1008b199dddbSQi Zhang if (sib == ICE_FLOW_FIELD_IDX_MAX || 1009b199dddbSQi Zhang flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 1010b199dddbSQi Zhang flds[sib].xtrct.off != off) { 101131ad4e4eSTony Nguyen u8 idx; 101231ad4e4eSTony Nguyen 101331ad4e4eSTony Nguyen /* Make sure the number of extraction sequence required 101431ad4e4eSTony Nguyen * does not exceed the block's capability 101531ad4e4eSTony Nguyen */ 101631ad4e4eSTony Nguyen if (params->es_cnt >= fv_words) 101731ad4e4eSTony Nguyen return ICE_ERR_MAX_LIMIT; 101831ad4e4eSTony Nguyen 101931ad4e4eSTony Nguyen /* some blocks require a reversed field vector layout */ 102031ad4e4eSTony Nguyen if (hw->blk[params->blk].es.reverse) 102131ad4e4eSTony Nguyen idx = fv_words - params->es_cnt - 1; 102231ad4e4eSTony Nguyen else 102331ad4e4eSTony Nguyen idx = params->es_cnt; 102431ad4e4eSTony Nguyen 102531ad4e4eSTony Nguyen params->es[idx].prot_id = prot_id; 102631ad4e4eSTony Nguyen params->es[idx].off = off; 1027b199dddbSQi Zhang params->mask[idx] = mask | sib_mask; 102831ad4e4eSTony Nguyen params->es_cnt++; 1029b199dddbSQi Zhang } 103031ad4e4eSTony Nguyen 103131ad4e4eSTony Nguyen off += ICE_FLOW_FV_EXTRACT_SZ; 103231ad4e4eSTony Nguyen } 103331ad4e4eSTony Nguyen 103431ad4e4eSTony Nguyen return 0; 103531ad4e4eSTony Nguyen } 103631ad4e4eSTony Nguyen 103731ad4e4eSTony Nguyen /** 10382c57ffcbSHenry Tieman * ice_flow_xtract_raws - Create extract sequence entries for raw bytes 10392c57ffcbSHenry Tieman * @hw: pointer to the HW struct 10402c57ffcbSHenry Tieman * @params: information about the flow to be processed 1041ac382a09SBruce Allan * @seg: index of packet segment whose raw fields are to be extracted 10422c57ffcbSHenry Tieman */ 10432c57ffcbSHenry Tieman static enum ice_status 10442c57ffcbSHenry Tieman ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, 10452c57ffcbSHenry Tieman u8 seg) 10462c57ffcbSHenry Tieman { 10472c57ffcbSHenry Tieman u16 fv_words; 10482c57ffcbSHenry Tieman u16 hdrs_sz; 10492c57ffcbSHenry Tieman u8 i; 10502c57ffcbSHenry Tieman 10512c57ffcbSHenry Tieman if (!params->prof->segs[seg].raws_cnt) 10522c57ffcbSHenry Tieman return 0; 10532c57ffcbSHenry Tieman 10542c57ffcbSHenry Tieman if (params->prof->segs[seg].raws_cnt > 10552c57ffcbSHenry Tieman ARRAY_SIZE(params->prof->segs[seg].raws)) 10562c57ffcbSHenry Tieman return ICE_ERR_MAX_LIMIT; 10572c57ffcbSHenry Tieman 10582c57ffcbSHenry Tieman /* Offsets within the segment headers are not supported */ 10592c57ffcbSHenry Tieman hdrs_sz = ice_flow_calc_seg_sz(params, seg); 10602c57ffcbSHenry Tieman if (!hdrs_sz) 10612c57ffcbSHenry Tieman return ICE_ERR_PARAM; 10622c57ffcbSHenry Tieman 10632c57ffcbSHenry Tieman fv_words = hw->blk[params->blk].es.fvw; 10642c57ffcbSHenry Tieman 10652c57ffcbSHenry Tieman for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) { 10662c57ffcbSHenry Tieman struct ice_flow_seg_fld_raw *raw; 10672c57ffcbSHenry Tieman u16 off, cnt, j; 10682c57ffcbSHenry Tieman 10692c57ffcbSHenry Tieman raw = ¶ms->prof->segs[seg].raws[i]; 10702c57ffcbSHenry Tieman 10712c57ffcbSHenry Tieman /* Storing extraction information */ 10722c57ffcbSHenry Tieman raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S; 10732c57ffcbSHenry Tieman raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) * 10742c57ffcbSHenry Tieman ICE_FLOW_FV_EXTRACT_SZ; 10752c57ffcbSHenry Tieman raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) * 10762c57ffcbSHenry Tieman BITS_PER_BYTE; 10772c57ffcbSHenry Tieman raw->info.xtrct.idx = params->es_cnt; 10782c57ffcbSHenry Tieman 10792c57ffcbSHenry Tieman /* Determine the number of field vector entries this raw field 10802c57ffcbSHenry Tieman * consumes. 10812c57ffcbSHenry Tieman */ 10822c57ffcbSHenry Tieman cnt = DIV_ROUND_UP(raw->info.xtrct.disp + 10832c57ffcbSHenry Tieman (raw->info.src.last * BITS_PER_BYTE), 10842c57ffcbSHenry Tieman (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE)); 10852c57ffcbSHenry Tieman off = raw->info.xtrct.off; 10862c57ffcbSHenry Tieman for (j = 0; j < cnt; j++) { 10872c57ffcbSHenry Tieman u16 idx; 10882c57ffcbSHenry Tieman 10892c57ffcbSHenry Tieman /* Make sure the number of extraction sequence required 10902c57ffcbSHenry Tieman * does not exceed the block's capability 10912c57ffcbSHenry Tieman */ 10922c57ffcbSHenry Tieman if (params->es_cnt >= hw->blk[params->blk].es.count || 10932c57ffcbSHenry Tieman params->es_cnt >= ICE_MAX_FV_WORDS) 10942c57ffcbSHenry Tieman return ICE_ERR_MAX_LIMIT; 10952c57ffcbSHenry Tieman 10962c57ffcbSHenry Tieman /* some blocks require a reversed field vector layout */ 10972c57ffcbSHenry Tieman if (hw->blk[params->blk].es.reverse) 10982c57ffcbSHenry Tieman idx = fv_words - params->es_cnt - 1; 10992c57ffcbSHenry Tieman else 11002c57ffcbSHenry Tieman idx = params->es_cnt; 11012c57ffcbSHenry Tieman 11022c57ffcbSHenry Tieman params->es[idx].prot_id = raw->info.xtrct.prot_id; 11032c57ffcbSHenry Tieman params->es[idx].off = off; 11042c57ffcbSHenry Tieman params->es_cnt++; 11052c57ffcbSHenry Tieman off += ICE_FLOW_FV_EXTRACT_SZ; 11062c57ffcbSHenry Tieman } 11072c57ffcbSHenry Tieman } 11082c57ffcbSHenry Tieman 11092c57ffcbSHenry Tieman return 0; 11102c57ffcbSHenry Tieman } 11112c57ffcbSHenry Tieman 11122c57ffcbSHenry Tieman /** 111331ad4e4eSTony Nguyen * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 111431ad4e4eSTony Nguyen * @hw: pointer to the HW struct 111531ad4e4eSTony Nguyen * @params: information about the flow to be processed 111631ad4e4eSTony Nguyen * 111731ad4e4eSTony Nguyen * This function iterates through all matched fields in the given segments, and 111831ad4e4eSTony Nguyen * creates an extraction sequence for the fields. 111931ad4e4eSTony Nguyen */ 112031ad4e4eSTony Nguyen static enum ice_status 112131ad4e4eSTony Nguyen ice_flow_create_xtrct_seq(struct ice_hw *hw, 112231ad4e4eSTony Nguyen struct ice_flow_prof_params *params) 112331ad4e4eSTony Nguyen { 112431ad4e4eSTony Nguyen struct ice_flow_prof *prof = params->prof; 112531ad4e4eSTony Nguyen enum ice_status status = 0; 112631ad4e4eSTony Nguyen u8 i; 112731ad4e4eSTony Nguyen 112831ad4e4eSTony Nguyen for (i = 0; i < prof->segs_cnt; i++) { 1129b199dddbSQi Zhang u64 match = params->prof->segs[i].match; 1130b199dddbSQi Zhang enum ice_flow_field j; 113131ad4e4eSTony Nguyen 1132b199dddbSQi Zhang for_each_set_bit(j, (unsigned long *)&match, 113331ad4e4eSTony Nguyen ICE_FLOW_FIELD_IDX_MAX) { 1134b199dddbSQi Zhang status = ice_flow_xtract_fld(hw, params, i, j, match); 113531ad4e4eSTony Nguyen if (status) 113631ad4e4eSTony Nguyen return status; 1137b199dddbSQi Zhang clear_bit(j, (unsigned long *)&match); 113831ad4e4eSTony Nguyen } 11392c57ffcbSHenry Tieman 11402c57ffcbSHenry Tieman /* Process raw matching bytes */ 11412c57ffcbSHenry Tieman status = ice_flow_xtract_raws(hw, params, i); 11422c57ffcbSHenry Tieman if (status) 11432c57ffcbSHenry Tieman return status; 114431ad4e4eSTony Nguyen } 114531ad4e4eSTony Nguyen 114631ad4e4eSTony Nguyen return status; 114731ad4e4eSTony Nguyen } 114831ad4e4eSTony Nguyen 114931ad4e4eSTony Nguyen /** 115031ad4e4eSTony Nguyen * ice_flow_proc_segs - process all packet segments associated with a profile 115131ad4e4eSTony Nguyen * @hw: pointer to the HW struct 115231ad4e4eSTony Nguyen * @params: information about the flow to be processed 115331ad4e4eSTony Nguyen */ 115431ad4e4eSTony Nguyen static enum ice_status 115531ad4e4eSTony Nguyen ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 115631ad4e4eSTony Nguyen { 115731ad4e4eSTony Nguyen enum ice_status status; 115831ad4e4eSTony Nguyen 115931ad4e4eSTony Nguyen status = ice_flow_proc_seg_hdrs(params); 116031ad4e4eSTony Nguyen if (status) 116131ad4e4eSTony Nguyen return status; 116231ad4e4eSTony Nguyen 116331ad4e4eSTony Nguyen status = ice_flow_create_xtrct_seq(hw, params); 116431ad4e4eSTony Nguyen if (status) 116531ad4e4eSTony Nguyen return status; 116631ad4e4eSTony Nguyen 116731ad4e4eSTony Nguyen switch (params->blk) { 1168148beb61SHenry Tieman case ICE_BLK_FD: 116931ad4e4eSTony Nguyen case ICE_BLK_RSS: 117031ad4e4eSTony Nguyen status = 0; 117131ad4e4eSTony Nguyen break; 117231ad4e4eSTony Nguyen default: 117331ad4e4eSTony Nguyen return ICE_ERR_NOT_IMPL; 117431ad4e4eSTony Nguyen } 117531ad4e4eSTony Nguyen 117631ad4e4eSTony Nguyen return status; 117731ad4e4eSTony Nguyen } 117831ad4e4eSTony Nguyen 11792c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 11802c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 11812c61054cSTony Nguyen #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 11822c61054cSTony Nguyen 11832c61054cSTony Nguyen /** 11842c61054cSTony Nguyen * ice_flow_find_prof_conds - Find a profile matching headers and conditions 11852c61054cSTony Nguyen * @hw: pointer to the HW struct 11862c61054cSTony Nguyen * @blk: classification stage 11872c61054cSTony Nguyen * @dir: flow direction 11882c61054cSTony Nguyen * @segs: array of one or more packet segments that describe the flow 11892c61054cSTony Nguyen * @segs_cnt: number of packet segments provided 11902c61054cSTony Nguyen * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 11912c61054cSTony Nguyen * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 11922c61054cSTony Nguyen */ 11932c61054cSTony Nguyen static struct ice_flow_prof * 11942c61054cSTony Nguyen ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 11952c61054cSTony Nguyen enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 11962c61054cSTony Nguyen u8 segs_cnt, u16 vsi_handle, u32 conds) 11972c61054cSTony Nguyen { 11982c61054cSTony Nguyen struct ice_flow_prof *p, *prof = NULL; 11992c61054cSTony Nguyen 12002c61054cSTony Nguyen mutex_lock(&hw->fl_profs_locks[blk]); 12012c61054cSTony Nguyen list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 12022c61054cSTony Nguyen if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 12032c61054cSTony Nguyen segs_cnt && segs_cnt == p->segs_cnt) { 12042c61054cSTony Nguyen u8 i; 12052c61054cSTony Nguyen 12062c61054cSTony Nguyen /* Check for profile-VSI association if specified */ 12072c61054cSTony Nguyen if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 12082c61054cSTony Nguyen ice_is_vsi_valid(hw, vsi_handle) && 12092c61054cSTony Nguyen !test_bit(vsi_handle, p->vsis)) 12102c61054cSTony Nguyen continue; 12112c61054cSTony Nguyen 12122c61054cSTony Nguyen /* Protocol headers must be checked. Matched fields are 12132c61054cSTony Nguyen * checked if specified. 12142c61054cSTony Nguyen */ 12152c61054cSTony Nguyen for (i = 0; i < segs_cnt; i++) 12162c61054cSTony Nguyen if (segs[i].hdrs != p->segs[i].hdrs || 12172c61054cSTony Nguyen ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 12182c61054cSTony Nguyen segs[i].match != p->segs[i].match)) 12192c61054cSTony Nguyen break; 12202c61054cSTony Nguyen 12212c61054cSTony Nguyen /* A match is found if all segments are matched */ 12222c61054cSTony Nguyen if (i == segs_cnt) { 12232c61054cSTony Nguyen prof = p; 12242c61054cSTony Nguyen break; 12252c61054cSTony Nguyen } 12262c61054cSTony Nguyen } 12272c61054cSTony Nguyen mutex_unlock(&hw->fl_profs_locks[blk]); 12282c61054cSTony Nguyen 12292c61054cSTony Nguyen return prof; 12302c61054cSTony Nguyen } 12312c61054cSTony Nguyen 12322c61054cSTony Nguyen /** 12332c61054cSTony Nguyen * ice_flow_find_prof_id - Look up a profile with given profile ID 12342c61054cSTony Nguyen * @hw: pointer to the HW struct 12352c61054cSTony Nguyen * @blk: classification stage 12362c61054cSTony Nguyen * @prof_id: unique ID to identify this flow profile 12372c61054cSTony Nguyen */ 12382c61054cSTony Nguyen static struct ice_flow_prof * 12392c61054cSTony Nguyen ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 12402c61054cSTony Nguyen { 12412c61054cSTony Nguyen struct ice_flow_prof *p; 12422c61054cSTony Nguyen 12432c61054cSTony Nguyen list_for_each_entry(p, &hw->fl_profs[blk], l_entry) 12442c61054cSTony Nguyen if (p->id == prof_id) 12452c61054cSTony Nguyen return p; 12462c61054cSTony Nguyen 12472c61054cSTony Nguyen return NULL; 12482c61054cSTony Nguyen } 12492c61054cSTony Nguyen 125031ad4e4eSTony Nguyen /** 1251148beb61SHenry Tieman * ice_dealloc_flow_entry - Deallocate flow entry memory 1252148beb61SHenry Tieman * @hw: pointer to the HW struct 1253148beb61SHenry Tieman * @entry: flow entry to be removed 1254148beb61SHenry Tieman */ 1255148beb61SHenry Tieman static void 1256148beb61SHenry Tieman ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry) 1257148beb61SHenry Tieman { 1258148beb61SHenry Tieman if (!entry) 1259148beb61SHenry Tieman return; 1260148beb61SHenry Tieman 1261148beb61SHenry Tieman if (entry->entry) 1262148beb61SHenry Tieman devm_kfree(ice_hw_to_dev(hw), entry->entry); 1263148beb61SHenry Tieman 1264148beb61SHenry Tieman devm_kfree(ice_hw_to_dev(hw), entry); 1265148beb61SHenry Tieman } 1266148beb61SHenry Tieman 1267148beb61SHenry Tieman /** 1268148beb61SHenry Tieman * ice_flow_rem_entry_sync - Remove a flow entry 1269148beb61SHenry Tieman * @hw: pointer to the HW struct 1270148beb61SHenry Tieman * @blk: classification stage 1271148beb61SHenry Tieman * @entry: flow entry to be removed 1272148beb61SHenry Tieman */ 1273148beb61SHenry Tieman static enum ice_status 1274148beb61SHenry Tieman ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, 1275148beb61SHenry Tieman struct ice_flow_entry *entry) 1276148beb61SHenry Tieman { 1277148beb61SHenry Tieman if (!entry) 1278148beb61SHenry Tieman return ICE_ERR_BAD_PTR; 1279148beb61SHenry Tieman 1280148beb61SHenry Tieman list_del(&entry->l_entry); 1281148beb61SHenry Tieman 1282148beb61SHenry Tieman ice_dealloc_flow_entry(hw, entry); 1283148beb61SHenry Tieman 1284148beb61SHenry Tieman return 0; 1285148beb61SHenry Tieman } 1286148beb61SHenry Tieman 1287148beb61SHenry Tieman /** 128831ad4e4eSTony Nguyen * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 128931ad4e4eSTony Nguyen * @hw: pointer to the HW struct 129031ad4e4eSTony Nguyen * @blk: classification stage 129131ad4e4eSTony Nguyen * @dir: flow direction 129231ad4e4eSTony Nguyen * @prof_id: unique ID to identify this flow profile 129331ad4e4eSTony Nguyen * @segs: array of one or more packet segments that describe the flow 129431ad4e4eSTony Nguyen * @segs_cnt: number of packet segments provided 129531ad4e4eSTony Nguyen * @prof: stores the returned flow profile added 129631ad4e4eSTony Nguyen * 129731ad4e4eSTony Nguyen * Assumption: the caller has acquired the lock to the profile list 129831ad4e4eSTony Nguyen */ 129931ad4e4eSTony Nguyen static enum ice_status 130031ad4e4eSTony Nguyen ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 130131ad4e4eSTony Nguyen enum ice_flow_dir dir, u64 prof_id, 130231ad4e4eSTony Nguyen struct ice_flow_seg_info *segs, u8 segs_cnt, 130331ad4e4eSTony Nguyen struct ice_flow_prof **prof) 130431ad4e4eSTony Nguyen { 130588dcfdb4SBruce Allan struct ice_flow_prof_params *params; 130631ad4e4eSTony Nguyen enum ice_status status; 130731ad4e4eSTony Nguyen u8 i; 130831ad4e4eSTony Nguyen 130931ad4e4eSTony Nguyen if (!prof) 131031ad4e4eSTony Nguyen return ICE_ERR_BAD_PTR; 131131ad4e4eSTony Nguyen 131288dcfdb4SBruce Allan params = kzalloc(sizeof(*params), GFP_KERNEL); 131388dcfdb4SBruce Allan if (!params) 131431ad4e4eSTony Nguyen return ICE_ERR_NO_MEMORY; 131531ad4e4eSTony Nguyen 131688dcfdb4SBruce Allan params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof), 131788dcfdb4SBruce Allan GFP_KERNEL); 131888dcfdb4SBruce Allan if (!params->prof) { 131988dcfdb4SBruce Allan status = ICE_ERR_NO_MEMORY; 132088dcfdb4SBruce Allan goto free_params; 132188dcfdb4SBruce Allan } 132288dcfdb4SBruce Allan 132331ad4e4eSTony Nguyen /* initialize extraction sequence to all invalid (0xff) */ 132431ad4e4eSTony Nguyen for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 132588dcfdb4SBruce Allan params->es[i].prot_id = ICE_PROT_INVALID; 132688dcfdb4SBruce Allan params->es[i].off = ICE_FV_OFFSET_INVAL; 132731ad4e4eSTony Nguyen } 132831ad4e4eSTony Nguyen 132988dcfdb4SBruce Allan params->blk = blk; 133088dcfdb4SBruce Allan params->prof->id = prof_id; 133188dcfdb4SBruce Allan params->prof->dir = dir; 133288dcfdb4SBruce Allan params->prof->segs_cnt = segs_cnt; 133331ad4e4eSTony Nguyen 133431ad4e4eSTony Nguyen /* Make a copy of the segments that need to be persistent in the flow 133531ad4e4eSTony Nguyen * profile instance 133631ad4e4eSTony Nguyen */ 133731ad4e4eSTony Nguyen for (i = 0; i < segs_cnt; i++) 133888dcfdb4SBruce Allan memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs)); 133931ad4e4eSTony Nguyen 134088dcfdb4SBruce Allan status = ice_flow_proc_segs(hw, params); 134131ad4e4eSTony Nguyen if (status) { 13429228d8b2SJacob Keller ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 134331ad4e4eSTony Nguyen goto out; 134431ad4e4eSTony Nguyen } 134531ad4e4eSTony Nguyen 134631ad4e4eSTony Nguyen /* Add a HW profile for this flow profile */ 134788dcfdb4SBruce Allan status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes, 1348*cbad5db8SQi Zhang params->attr, params->attr_cnt, params->es, 1349*cbad5db8SQi Zhang params->mask); 135031ad4e4eSTony Nguyen if (status) { 135131ad4e4eSTony Nguyen ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 135231ad4e4eSTony Nguyen goto out; 135331ad4e4eSTony Nguyen } 135431ad4e4eSTony Nguyen 135588dcfdb4SBruce Allan INIT_LIST_HEAD(¶ms->prof->entries); 135688dcfdb4SBruce Allan mutex_init(¶ms->prof->entries_lock); 135788dcfdb4SBruce Allan *prof = params->prof; 135831ad4e4eSTony Nguyen 135931ad4e4eSTony Nguyen out: 136031ad4e4eSTony Nguyen if (status) 136188dcfdb4SBruce Allan devm_kfree(ice_hw_to_dev(hw), params->prof); 136288dcfdb4SBruce Allan free_params: 136388dcfdb4SBruce Allan kfree(params); 136431ad4e4eSTony Nguyen 136531ad4e4eSTony Nguyen return status; 136631ad4e4eSTony Nguyen } 136731ad4e4eSTony Nguyen 136831ad4e4eSTony Nguyen /** 13692c61054cSTony Nguyen * ice_flow_rem_prof_sync - remove a flow profile 13702c61054cSTony Nguyen * @hw: pointer to the hardware structure 13712c61054cSTony Nguyen * @blk: classification stage 13722c61054cSTony Nguyen * @prof: pointer to flow profile to remove 13732c61054cSTony Nguyen * 13742c61054cSTony Nguyen * Assumption: the caller has acquired the lock to the profile list 13752c61054cSTony Nguyen */ 13762c61054cSTony Nguyen static enum ice_status 13772c61054cSTony Nguyen ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 13782c61054cSTony Nguyen struct ice_flow_prof *prof) 13792c61054cSTony Nguyen { 13802c61054cSTony Nguyen enum ice_status status; 13812c61054cSTony Nguyen 1382148beb61SHenry Tieman /* Remove all remaining flow entries before removing the flow profile */ 1383148beb61SHenry Tieman if (!list_empty(&prof->entries)) { 1384148beb61SHenry Tieman struct ice_flow_entry *e, *t; 1385148beb61SHenry Tieman 1386148beb61SHenry Tieman mutex_lock(&prof->entries_lock); 1387148beb61SHenry Tieman 1388148beb61SHenry Tieman list_for_each_entry_safe(e, t, &prof->entries, l_entry) { 1389148beb61SHenry Tieman status = ice_flow_rem_entry_sync(hw, blk, e); 1390148beb61SHenry Tieman if (status) 1391148beb61SHenry Tieman break; 1392148beb61SHenry Tieman } 1393148beb61SHenry Tieman 1394148beb61SHenry Tieman mutex_unlock(&prof->entries_lock); 1395148beb61SHenry Tieman } 1396148beb61SHenry Tieman 13972c61054cSTony Nguyen /* Remove all hardware profiles associated with this flow profile */ 13982c61054cSTony Nguyen status = ice_rem_prof(hw, blk, prof->id); 13992c61054cSTony Nguyen if (!status) { 14002c61054cSTony Nguyen list_del(&prof->l_entry); 14012c61054cSTony Nguyen mutex_destroy(&prof->entries_lock); 14022c61054cSTony Nguyen devm_kfree(ice_hw_to_dev(hw), prof); 14032c61054cSTony Nguyen } 14042c61054cSTony Nguyen 14052c61054cSTony Nguyen return status; 14062c61054cSTony Nguyen } 14072c61054cSTony Nguyen 14082c61054cSTony Nguyen /** 1409451f2c44STony Nguyen * ice_flow_assoc_prof - associate a VSI with a flow profile 1410451f2c44STony Nguyen * @hw: pointer to the hardware structure 1411451f2c44STony Nguyen * @blk: classification stage 1412451f2c44STony Nguyen * @prof: pointer to flow profile 1413451f2c44STony Nguyen * @vsi_handle: software VSI handle 1414451f2c44STony Nguyen * 1415451f2c44STony Nguyen * Assumption: the caller has acquired the lock to the profile list 1416451f2c44STony Nguyen * and the software VSI handle has been validated 1417451f2c44STony Nguyen */ 1418451f2c44STony Nguyen static enum ice_status 1419451f2c44STony Nguyen ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 1420451f2c44STony Nguyen struct ice_flow_prof *prof, u16 vsi_handle) 1421451f2c44STony Nguyen { 1422451f2c44STony Nguyen enum ice_status status = 0; 1423451f2c44STony Nguyen 1424451f2c44STony Nguyen if (!test_bit(vsi_handle, prof->vsis)) { 1425451f2c44STony Nguyen status = ice_add_prof_id_flow(hw, blk, 1426451f2c44STony Nguyen ice_get_hw_vsi_num(hw, 1427451f2c44STony Nguyen vsi_handle), 1428451f2c44STony Nguyen prof->id); 1429451f2c44STony Nguyen if (!status) 1430451f2c44STony Nguyen set_bit(vsi_handle, prof->vsis); 1431451f2c44STony Nguyen else 14329228d8b2SJacob Keller ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 1433451f2c44STony Nguyen status); 1434451f2c44STony Nguyen } 1435451f2c44STony Nguyen 1436451f2c44STony Nguyen return status; 1437451f2c44STony Nguyen } 1438451f2c44STony Nguyen 1439451f2c44STony Nguyen /** 14402c61054cSTony Nguyen * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 14412c61054cSTony Nguyen * @hw: pointer to the hardware structure 14422c61054cSTony Nguyen * @blk: classification stage 14432c61054cSTony Nguyen * @prof: pointer to flow profile 14442c61054cSTony Nguyen * @vsi_handle: software VSI handle 14452c61054cSTony Nguyen * 14462c61054cSTony Nguyen * Assumption: the caller has acquired the lock to the profile list 14472c61054cSTony Nguyen * and the software VSI handle has been validated 14482c61054cSTony Nguyen */ 14492c61054cSTony Nguyen static enum ice_status 14502c61054cSTony Nguyen ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 14512c61054cSTony Nguyen struct ice_flow_prof *prof, u16 vsi_handle) 14522c61054cSTony Nguyen { 14532c61054cSTony Nguyen enum ice_status status = 0; 14542c61054cSTony Nguyen 14552c61054cSTony Nguyen if (test_bit(vsi_handle, prof->vsis)) { 14562c61054cSTony Nguyen status = ice_rem_prof_id_flow(hw, blk, 14572c61054cSTony Nguyen ice_get_hw_vsi_num(hw, 14582c61054cSTony Nguyen vsi_handle), 14592c61054cSTony Nguyen prof->id); 14602c61054cSTony Nguyen if (!status) 14612c61054cSTony Nguyen clear_bit(vsi_handle, prof->vsis); 14622c61054cSTony Nguyen else 14639228d8b2SJacob Keller ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 14642c61054cSTony Nguyen status); 14652c61054cSTony Nguyen } 14662c61054cSTony Nguyen 14672c61054cSTony Nguyen return status; 14682c61054cSTony Nguyen } 14692c61054cSTony Nguyen 14702c61054cSTony Nguyen /** 147131ad4e4eSTony Nguyen * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 147231ad4e4eSTony Nguyen * @hw: pointer to the HW struct 147331ad4e4eSTony Nguyen * @blk: classification stage 147431ad4e4eSTony Nguyen * @dir: flow direction 147531ad4e4eSTony Nguyen * @prof_id: unique ID to identify this flow profile 147631ad4e4eSTony Nguyen * @segs: array of one or more packet segments that describe the flow 147731ad4e4eSTony Nguyen * @segs_cnt: number of packet segments provided 1478451f2c44STony Nguyen * @prof: stores the returned flow profile added 147931ad4e4eSTony Nguyen */ 1480148beb61SHenry Tieman enum ice_status 148131ad4e4eSTony Nguyen ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 1482451f2c44STony Nguyen u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 1483451f2c44STony Nguyen struct ice_flow_prof **prof) 148431ad4e4eSTony Nguyen { 148531ad4e4eSTony Nguyen enum ice_status status; 148631ad4e4eSTony Nguyen 148731ad4e4eSTony Nguyen if (segs_cnt > ICE_FLOW_SEG_MAX) 148831ad4e4eSTony Nguyen return ICE_ERR_MAX_LIMIT; 148931ad4e4eSTony Nguyen 149031ad4e4eSTony Nguyen if (!segs_cnt) 149131ad4e4eSTony Nguyen return ICE_ERR_PARAM; 149231ad4e4eSTony Nguyen 149331ad4e4eSTony Nguyen if (!segs) 149431ad4e4eSTony Nguyen return ICE_ERR_BAD_PTR; 149531ad4e4eSTony Nguyen 149631ad4e4eSTony Nguyen status = ice_flow_val_hdrs(segs, segs_cnt); 149731ad4e4eSTony Nguyen if (status) 149831ad4e4eSTony Nguyen return status; 149931ad4e4eSTony Nguyen 150031ad4e4eSTony Nguyen mutex_lock(&hw->fl_profs_locks[blk]); 150131ad4e4eSTony Nguyen 150231ad4e4eSTony Nguyen status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 1503451f2c44STony Nguyen prof); 150431ad4e4eSTony Nguyen if (!status) 1505451f2c44STony Nguyen list_add(&(*prof)->l_entry, &hw->fl_profs[blk]); 150631ad4e4eSTony Nguyen 150731ad4e4eSTony Nguyen mutex_unlock(&hw->fl_profs_locks[blk]); 150831ad4e4eSTony Nguyen 150931ad4e4eSTony Nguyen return status; 151031ad4e4eSTony Nguyen } 151131ad4e4eSTony Nguyen 1512c90ed40cSTony Nguyen /** 15132c61054cSTony Nguyen * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 15142c61054cSTony Nguyen * @hw: pointer to the HW struct 15152c61054cSTony Nguyen * @blk: the block for which the flow profile is to be removed 15162c61054cSTony Nguyen * @prof_id: unique ID of the flow profile to be removed 15172c61054cSTony Nguyen */ 1518148beb61SHenry Tieman enum ice_status 15192c61054cSTony Nguyen ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 15202c61054cSTony Nguyen { 15212c61054cSTony Nguyen struct ice_flow_prof *prof; 15222c61054cSTony Nguyen enum ice_status status; 15232c61054cSTony Nguyen 15242c61054cSTony Nguyen mutex_lock(&hw->fl_profs_locks[blk]); 15252c61054cSTony Nguyen 15262c61054cSTony Nguyen prof = ice_flow_find_prof_id(hw, blk, prof_id); 15272c61054cSTony Nguyen if (!prof) { 15282c61054cSTony Nguyen status = ICE_ERR_DOES_NOT_EXIST; 15292c61054cSTony Nguyen goto out; 15302c61054cSTony Nguyen } 15312c61054cSTony Nguyen 15322c61054cSTony Nguyen /* prof becomes invalid after the call */ 15332c61054cSTony Nguyen status = ice_flow_rem_prof_sync(hw, blk, prof); 15342c61054cSTony Nguyen 15352c61054cSTony Nguyen out: 15362c61054cSTony Nguyen mutex_unlock(&hw->fl_profs_locks[blk]); 15372c61054cSTony Nguyen 15382c61054cSTony Nguyen return status; 15392c61054cSTony Nguyen } 15402c61054cSTony Nguyen 15412c61054cSTony Nguyen /** 1542148beb61SHenry Tieman * ice_flow_add_entry - Add a flow entry 1543148beb61SHenry Tieman * @hw: pointer to the HW struct 1544148beb61SHenry Tieman * @blk: classification stage 1545148beb61SHenry Tieman * @prof_id: ID of the profile to add a new flow entry to 1546148beb61SHenry Tieman * @entry_id: unique ID to identify this flow entry 1547148beb61SHenry Tieman * @vsi_handle: software VSI handle for the flow entry 1548148beb61SHenry Tieman * @prio: priority of the flow entry 1549148beb61SHenry Tieman * @data: pointer to a data buffer containing flow entry's match values/masks 1550148beb61SHenry Tieman * @entry_h: pointer to buffer that receives the new flow entry's handle 1551148beb61SHenry Tieman */ 1552148beb61SHenry Tieman enum ice_status 1553148beb61SHenry Tieman ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 1554148beb61SHenry Tieman u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, 1555148beb61SHenry Tieman void *data, u64 *entry_h) 1556148beb61SHenry Tieman { 1557148beb61SHenry Tieman struct ice_flow_entry *e = NULL; 1558148beb61SHenry Tieman struct ice_flow_prof *prof; 1559148beb61SHenry Tieman enum ice_status status; 1560148beb61SHenry Tieman 1561148beb61SHenry Tieman /* No flow entry data is expected for RSS */ 1562148beb61SHenry Tieman if (!entry_h || (!data && blk != ICE_BLK_RSS)) 1563148beb61SHenry Tieman return ICE_ERR_BAD_PTR; 1564148beb61SHenry Tieman 1565148beb61SHenry Tieman if (!ice_is_vsi_valid(hw, vsi_handle)) 1566148beb61SHenry Tieman return ICE_ERR_PARAM; 1567148beb61SHenry Tieman 1568148beb61SHenry Tieman mutex_lock(&hw->fl_profs_locks[blk]); 1569148beb61SHenry Tieman 1570148beb61SHenry Tieman prof = ice_flow_find_prof_id(hw, blk, prof_id); 1571148beb61SHenry Tieman if (!prof) { 1572148beb61SHenry Tieman status = ICE_ERR_DOES_NOT_EXIST; 1573148beb61SHenry Tieman } else { 1574148beb61SHenry Tieman /* Allocate memory for the entry being added and associate 1575148beb61SHenry Tieman * the VSI to the found flow profile 1576148beb61SHenry Tieman */ 1577148beb61SHenry Tieman e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL); 1578148beb61SHenry Tieman if (!e) 1579148beb61SHenry Tieman status = ICE_ERR_NO_MEMORY; 1580148beb61SHenry Tieman else 1581148beb61SHenry Tieman status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1582148beb61SHenry Tieman } 1583148beb61SHenry Tieman 1584148beb61SHenry Tieman mutex_unlock(&hw->fl_profs_locks[blk]); 1585148beb61SHenry Tieman if (status) 1586148beb61SHenry Tieman goto out; 1587148beb61SHenry Tieman 1588148beb61SHenry Tieman e->id = entry_id; 1589148beb61SHenry Tieman e->vsi_handle = vsi_handle; 1590148beb61SHenry Tieman e->prof = prof; 1591148beb61SHenry Tieman e->priority = prio; 1592148beb61SHenry Tieman 1593148beb61SHenry Tieman switch (blk) { 1594148beb61SHenry Tieman case ICE_BLK_FD: 1595148beb61SHenry Tieman case ICE_BLK_RSS: 1596148beb61SHenry Tieman break; 1597148beb61SHenry Tieman default: 1598148beb61SHenry Tieman status = ICE_ERR_NOT_IMPL; 1599148beb61SHenry Tieman goto out; 1600148beb61SHenry Tieman } 1601148beb61SHenry Tieman 1602148beb61SHenry Tieman mutex_lock(&prof->entries_lock); 1603148beb61SHenry Tieman list_add(&e->l_entry, &prof->entries); 1604148beb61SHenry Tieman mutex_unlock(&prof->entries_lock); 1605148beb61SHenry Tieman 1606148beb61SHenry Tieman *entry_h = ICE_FLOW_ENTRY_HNDL(e); 1607148beb61SHenry Tieman 1608148beb61SHenry Tieman out: 1609148beb61SHenry Tieman if (status && e) { 1610148beb61SHenry Tieman if (e->entry) 1611148beb61SHenry Tieman devm_kfree(ice_hw_to_dev(hw), e->entry); 1612148beb61SHenry Tieman devm_kfree(ice_hw_to_dev(hw), e); 1613148beb61SHenry Tieman } 1614148beb61SHenry Tieman 1615148beb61SHenry Tieman return status; 1616148beb61SHenry Tieman } 1617148beb61SHenry Tieman 1618148beb61SHenry Tieman /** 1619148beb61SHenry Tieman * ice_flow_rem_entry - Remove a flow entry 1620148beb61SHenry Tieman * @hw: pointer to the HW struct 1621148beb61SHenry Tieman * @blk: classification stage 1622148beb61SHenry Tieman * @entry_h: handle to the flow entry to be removed 1623148beb61SHenry Tieman */ 1624148beb61SHenry Tieman enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, 1625148beb61SHenry Tieman u64 entry_h) 1626148beb61SHenry Tieman { 1627148beb61SHenry Tieman struct ice_flow_entry *entry; 1628148beb61SHenry Tieman struct ice_flow_prof *prof; 1629148beb61SHenry Tieman enum ice_status status = 0; 1630148beb61SHenry Tieman 1631148beb61SHenry Tieman if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) 1632148beb61SHenry Tieman return ICE_ERR_PARAM; 1633148beb61SHenry Tieman 1634148beb61SHenry Tieman entry = ICE_FLOW_ENTRY_PTR(entry_h); 1635148beb61SHenry Tieman 1636148beb61SHenry Tieman /* Retain the pointer to the flow profile as the entry will be freed */ 1637148beb61SHenry Tieman prof = entry->prof; 1638148beb61SHenry Tieman 1639148beb61SHenry Tieman if (prof) { 1640148beb61SHenry Tieman mutex_lock(&prof->entries_lock); 1641148beb61SHenry Tieman status = ice_flow_rem_entry_sync(hw, blk, entry); 1642148beb61SHenry Tieman mutex_unlock(&prof->entries_lock); 1643148beb61SHenry Tieman } 1644148beb61SHenry Tieman 1645148beb61SHenry Tieman return status; 1646148beb61SHenry Tieman } 1647148beb61SHenry Tieman 1648148beb61SHenry Tieman /** 1649c90ed40cSTony Nguyen * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 1650c90ed40cSTony Nguyen * @seg: packet segment the field being set belongs to 1651c90ed40cSTony Nguyen * @fld: field to be set 16526dae8aa0SBruce Allan * @field_type: type of the field 1653c90ed40cSTony Nguyen * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1654c90ed40cSTony Nguyen * entry's input buffer 1655c90ed40cSTony Nguyen * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1656c90ed40cSTony Nguyen * input buffer 1657c90ed40cSTony Nguyen * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1658c90ed40cSTony Nguyen * entry's input buffer 1659c90ed40cSTony Nguyen * 1660c90ed40cSTony Nguyen * This helper function stores information of a field being matched, including 1661c90ed40cSTony Nguyen * the type of the field and the locations of the value to match, the mask, and 1662ac382a09SBruce Allan * the upper-bound value in the start of the input buffer for a flow entry. 1663c90ed40cSTony Nguyen * This function should only be used for fixed-size data structures. 1664c90ed40cSTony Nguyen * 1665c90ed40cSTony Nguyen * This function also opportunistically determines the protocol headers to be 1666c90ed40cSTony Nguyen * present based on the fields being set. Some fields cannot be used alone to 1667c90ed40cSTony Nguyen * determine the protocol headers present. Sometimes, fields for particular 1668c90ed40cSTony Nguyen * protocol headers are not matched. In those cases, the protocol headers 1669c90ed40cSTony Nguyen * must be explicitly set. 1670c90ed40cSTony Nguyen */ 1671c90ed40cSTony Nguyen static void 1672c90ed40cSTony Nguyen ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 16736dae8aa0SBruce Allan enum ice_flow_fld_match_type field_type, u16 val_loc, 1674c90ed40cSTony Nguyen u16 mask_loc, u16 last_loc) 1675c90ed40cSTony Nguyen { 1676c90ed40cSTony Nguyen u64 bit = BIT_ULL(fld); 1677c90ed40cSTony Nguyen 1678c90ed40cSTony Nguyen seg->match |= bit; 16796dae8aa0SBruce Allan if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 1680c90ed40cSTony Nguyen seg->range |= bit; 1681c90ed40cSTony Nguyen 16826dae8aa0SBruce Allan seg->fields[fld].type = field_type; 1683c90ed40cSTony Nguyen seg->fields[fld].src.val = val_loc; 1684c90ed40cSTony Nguyen seg->fields[fld].src.mask = mask_loc; 1685c90ed40cSTony Nguyen seg->fields[fld].src.last = last_loc; 1686c90ed40cSTony Nguyen 1687c90ed40cSTony Nguyen ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 1688c90ed40cSTony Nguyen } 1689c90ed40cSTony Nguyen 1690c90ed40cSTony Nguyen /** 1691c90ed40cSTony Nguyen * ice_flow_set_fld - specifies locations of field from entry's input buffer 1692c90ed40cSTony Nguyen * @seg: packet segment the field being set belongs to 1693c90ed40cSTony Nguyen * @fld: field to be set 1694c90ed40cSTony Nguyen * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1695c90ed40cSTony Nguyen * entry's input buffer 1696c90ed40cSTony Nguyen * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1697c90ed40cSTony Nguyen * input buffer 1698c90ed40cSTony Nguyen * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1699c90ed40cSTony Nguyen * entry's input buffer 1700c90ed40cSTony Nguyen * @range: indicate if field being matched is to be in a range 1701c90ed40cSTony Nguyen * 1702c90ed40cSTony Nguyen * This function specifies the locations, in the form of byte offsets from the 1703c90ed40cSTony Nguyen * start of the input buffer for a flow entry, from where the value to match, 1704c90ed40cSTony Nguyen * the mask value, and upper value can be extracted. These locations are then 1705c90ed40cSTony Nguyen * stored in the flow profile. When adding a flow entry associated with the 1706c90ed40cSTony Nguyen * flow profile, these locations will be used to quickly extract the values and 1707c90ed40cSTony Nguyen * create the content of a match entry. This function should only be used for 1708c90ed40cSTony Nguyen * fixed-size data structures. 1709c90ed40cSTony Nguyen */ 1710148beb61SHenry Tieman void 1711c90ed40cSTony Nguyen ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1712c90ed40cSTony Nguyen u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 1713c90ed40cSTony Nguyen { 1714c90ed40cSTony Nguyen enum ice_flow_fld_match_type t = range ? 1715c90ed40cSTony Nguyen ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 1716c90ed40cSTony Nguyen 1717c90ed40cSTony Nguyen ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 1718c90ed40cSTony Nguyen } 1719c90ed40cSTony Nguyen 17202c57ffcbSHenry Tieman /** 17212c57ffcbSHenry Tieman * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf 17222c57ffcbSHenry Tieman * @seg: packet segment the field being set belongs to 17232c57ffcbSHenry Tieman * @off: offset of the raw field from the beginning of the segment in bytes 17242c57ffcbSHenry Tieman * @len: length of the raw pattern to be matched 17252c57ffcbSHenry Tieman * @val_loc: location of the value to match from entry's input buffer 17262c57ffcbSHenry Tieman * @mask_loc: location of mask value from entry's input buffer 17272c57ffcbSHenry Tieman * 17282c57ffcbSHenry Tieman * This function specifies the offset of the raw field to be match from the 17292c57ffcbSHenry Tieman * beginning of the specified packet segment, and the locations, in the form of 17302c57ffcbSHenry Tieman * byte offsets from the start of the input buffer for a flow entry, from where 17312c57ffcbSHenry Tieman * the value to match and the mask value to be extracted. These locations are 17322c57ffcbSHenry Tieman * then stored in the flow profile. When adding flow entries to the associated 17332c57ffcbSHenry Tieman * flow profile, these locations can be used to quickly extract the values to 17342c57ffcbSHenry Tieman * create the content of a match entry. This function should only be used for 17352c57ffcbSHenry Tieman * fixed-size data structures. 17362c57ffcbSHenry Tieman */ 17372c57ffcbSHenry Tieman void 17382c57ffcbSHenry Tieman ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, 17392c57ffcbSHenry Tieman u16 val_loc, u16 mask_loc) 17402c57ffcbSHenry Tieman { 17412c57ffcbSHenry Tieman if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { 17422c57ffcbSHenry Tieman seg->raws[seg->raws_cnt].off = off; 17432c57ffcbSHenry Tieman seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; 17442c57ffcbSHenry Tieman seg->raws[seg->raws_cnt].info.src.val = val_loc; 17452c57ffcbSHenry Tieman seg->raws[seg->raws_cnt].info.src.mask = mask_loc; 17462c57ffcbSHenry Tieman /* The "last" field is used to store the length of the field */ 17472c57ffcbSHenry Tieman seg->raws[seg->raws_cnt].info.src.last = len; 17482c57ffcbSHenry Tieman } 17492c57ffcbSHenry Tieman 17502c57ffcbSHenry Tieman /* Overflows of "raws" will be handled as an error condition later in 17512c57ffcbSHenry Tieman * the flow when this information is processed. 17522c57ffcbSHenry Tieman */ 17532c57ffcbSHenry Tieman seg->raws_cnt++; 17542c57ffcbSHenry Tieman } 17552c57ffcbSHenry Tieman 1756390bd141SQi Zhang #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \ 1757390bd141SQi Zhang (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 1758390bd141SQi Zhang 1759c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 1760c90ed40cSTony Nguyen (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 1761c90ed40cSTony Nguyen 1762c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 1763c90ed40cSTony Nguyen (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 1764c90ed40cSTony Nguyen 1765c90ed40cSTony Nguyen #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 1766390bd141SQi Zhang (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ 1767390bd141SQi Zhang ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 1768c90ed40cSTony Nguyen ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 1769c90ed40cSTony Nguyen 1770c90ed40cSTony Nguyen /** 1771c90ed40cSTony Nguyen * ice_flow_set_rss_seg_info - setup packet segments for RSS 1772c90ed40cSTony Nguyen * @segs: pointer to the flow field segment(s) 1773c90ed40cSTony Nguyen * @hash_fields: fields to be hashed on for the segment(s) 1774c90ed40cSTony Nguyen * @flow_hdr: protocol header fields within a packet segment 1775c90ed40cSTony Nguyen * 1776c90ed40cSTony Nguyen * Helper function to extract fields from hash bitmap and use flow 1777c90ed40cSTony Nguyen * header value to set flow field segment for further use in flow 1778c90ed40cSTony Nguyen * profile entry or removal. 1779c90ed40cSTony Nguyen */ 1780c90ed40cSTony Nguyen static enum ice_status 1781c90ed40cSTony Nguyen ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, 1782c90ed40cSTony Nguyen u32 flow_hdr) 1783c90ed40cSTony Nguyen { 1784c90ed40cSTony Nguyen u64 val; 1785c90ed40cSTony Nguyen u8 i; 1786c90ed40cSTony Nguyen 1787c90ed40cSTony Nguyen for_each_set_bit(i, (unsigned long *)&hash_fields, 1788c90ed40cSTony Nguyen ICE_FLOW_FIELD_IDX_MAX) 1789c90ed40cSTony Nguyen ice_flow_set_fld(segs, (enum ice_flow_field)i, 1790c90ed40cSTony Nguyen ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 1791c90ed40cSTony Nguyen ICE_FLOW_FLD_OFF_INVAL, false); 1792c90ed40cSTony Nguyen 1793c90ed40cSTony Nguyen ICE_FLOW_SET_HDRS(segs, flow_hdr); 1794c90ed40cSTony Nguyen 17950577313eSQi Zhang if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & 17960577313eSQi Zhang ~ICE_FLOW_RSS_HDRS_INNER_MASK) 1797c90ed40cSTony Nguyen return ICE_ERR_PARAM; 1798c90ed40cSTony Nguyen 1799c90ed40cSTony Nguyen val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 1800c90ed40cSTony Nguyen if (val && !is_power_of_2(val)) 1801c90ed40cSTony Nguyen return ICE_ERR_CFG; 1802c90ed40cSTony Nguyen 1803c90ed40cSTony Nguyen val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 1804c90ed40cSTony Nguyen if (val && !is_power_of_2(val)) 1805c90ed40cSTony Nguyen return ICE_ERR_CFG; 1806c90ed40cSTony Nguyen 1807c90ed40cSTony Nguyen return 0; 1808c90ed40cSTony Nguyen } 1809c90ed40cSTony Nguyen 18102c61054cSTony Nguyen /** 18112c61054cSTony Nguyen * ice_rem_vsi_rss_list - remove VSI from RSS list 18122c61054cSTony Nguyen * @hw: pointer to the hardware structure 18132c61054cSTony Nguyen * @vsi_handle: software VSI handle 18142c61054cSTony Nguyen * 18152c61054cSTony Nguyen * Remove the VSI from all RSS configurations in the list. 18162c61054cSTony Nguyen */ 18172c61054cSTony Nguyen void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 18182c61054cSTony Nguyen { 18192c61054cSTony Nguyen struct ice_rss_cfg *r, *tmp; 18202c61054cSTony Nguyen 18212c61054cSTony Nguyen if (list_empty(&hw->rss_list_head)) 18222c61054cSTony Nguyen return; 18232c61054cSTony Nguyen 18242c61054cSTony Nguyen mutex_lock(&hw->rss_locks); 18252c61054cSTony Nguyen list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 18262c61054cSTony Nguyen if (test_and_clear_bit(vsi_handle, r->vsis)) 18272c61054cSTony Nguyen if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 18282c61054cSTony Nguyen list_del(&r->l_entry); 18292c61054cSTony Nguyen devm_kfree(ice_hw_to_dev(hw), r); 18302c61054cSTony Nguyen } 18312c61054cSTony Nguyen mutex_unlock(&hw->rss_locks); 18322c61054cSTony Nguyen } 18332c61054cSTony Nguyen 18342c61054cSTony Nguyen /** 18352c61054cSTony Nguyen * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 18362c61054cSTony Nguyen * @hw: pointer to the hardware structure 18372c61054cSTony Nguyen * @vsi_handle: software VSI handle 18382c61054cSTony Nguyen * 18392c61054cSTony Nguyen * This function will iterate through all flow profiles and disassociate 18402c61054cSTony Nguyen * the VSI from that profile. If the flow profile has no VSIs it will 18412c61054cSTony Nguyen * be removed. 18422c61054cSTony Nguyen */ 18432c61054cSTony Nguyen enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 18442c61054cSTony Nguyen { 18452c61054cSTony Nguyen const enum ice_block blk = ICE_BLK_RSS; 18462c61054cSTony Nguyen struct ice_flow_prof *p, *t; 18472c61054cSTony Nguyen enum ice_status status = 0; 18482c61054cSTony Nguyen 18492c61054cSTony Nguyen if (!ice_is_vsi_valid(hw, vsi_handle)) 18502c61054cSTony Nguyen return ICE_ERR_PARAM; 18512c61054cSTony Nguyen 18522c61054cSTony Nguyen if (list_empty(&hw->fl_profs[blk])) 18532c61054cSTony Nguyen return 0; 18542c61054cSTony Nguyen 1855cdedbab9SVignesh Sridhar mutex_lock(&hw->rss_locks); 18562c61054cSTony Nguyen list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry) 18572c61054cSTony Nguyen if (test_bit(vsi_handle, p->vsis)) { 18582c61054cSTony Nguyen status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 18592c61054cSTony Nguyen if (status) 18602c61054cSTony Nguyen break; 18612c61054cSTony Nguyen 18622c61054cSTony Nguyen if (bitmap_empty(p->vsis, ICE_MAX_VSI)) { 1863cdedbab9SVignesh Sridhar status = ice_flow_rem_prof(hw, blk, p->id); 18642c61054cSTony Nguyen if (status) 18652c61054cSTony Nguyen break; 18662c61054cSTony Nguyen } 18672c61054cSTony Nguyen } 1868cdedbab9SVignesh Sridhar mutex_unlock(&hw->rss_locks); 18692c61054cSTony Nguyen 18702c61054cSTony Nguyen return status; 18712c61054cSTony Nguyen } 18722c61054cSTony Nguyen 18732c61054cSTony Nguyen /** 18742c61054cSTony Nguyen * ice_rem_rss_list - remove RSS configuration from list 18752c61054cSTony Nguyen * @hw: pointer to the hardware structure 18762c61054cSTony Nguyen * @vsi_handle: software VSI handle 18772c61054cSTony Nguyen * @prof: pointer to flow profile 18782c61054cSTony Nguyen * 18792c61054cSTony Nguyen * Assumption: lock has already been acquired for RSS list 18802c61054cSTony Nguyen */ 18812c61054cSTony Nguyen static void 18822c61054cSTony Nguyen ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 18832c61054cSTony Nguyen { 18842c61054cSTony Nguyen struct ice_rss_cfg *r, *tmp; 18852c61054cSTony Nguyen 18862c61054cSTony Nguyen /* Search for RSS hash fields associated to the VSI that match the 18872c61054cSTony Nguyen * hash configurations associated to the flow profile. If found 18882c61054cSTony Nguyen * remove from the RSS entry list of the VSI context and delete entry. 18892c61054cSTony Nguyen */ 18902c61054cSTony Nguyen list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) 18912c61054cSTony Nguyen if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 18922c61054cSTony Nguyen r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 18932c61054cSTony Nguyen clear_bit(vsi_handle, r->vsis); 18942c61054cSTony Nguyen if (bitmap_empty(r->vsis, ICE_MAX_VSI)) { 18952c61054cSTony Nguyen list_del(&r->l_entry); 18962c61054cSTony Nguyen devm_kfree(ice_hw_to_dev(hw), r); 18972c61054cSTony Nguyen } 18982c61054cSTony Nguyen return; 18992c61054cSTony Nguyen } 19002c61054cSTony Nguyen } 19012c61054cSTony Nguyen 19022c61054cSTony Nguyen /** 19032c61054cSTony Nguyen * ice_add_rss_list - add RSS configuration to list 19042c61054cSTony Nguyen * @hw: pointer to the hardware structure 19052c61054cSTony Nguyen * @vsi_handle: software VSI handle 19062c61054cSTony Nguyen * @prof: pointer to flow profile 19072c61054cSTony Nguyen * 19082c61054cSTony Nguyen * Assumption: lock has already been acquired for RSS list 19092c61054cSTony Nguyen */ 19102c61054cSTony Nguyen static enum ice_status 19112c61054cSTony Nguyen ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 19122c61054cSTony Nguyen { 19132c61054cSTony Nguyen struct ice_rss_cfg *r, *rss_cfg; 19142c61054cSTony Nguyen 19152c61054cSTony Nguyen list_for_each_entry(r, &hw->rss_list_head, l_entry) 19162c61054cSTony Nguyen if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 19172c61054cSTony Nguyen r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 19182c61054cSTony Nguyen set_bit(vsi_handle, r->vsis); 19192c61054cSTony Nguyen return 0; 19202c61054cSTony Nguyen } 19212c61054cSTony Nguyen 19222c61054cSTony Nguyen rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg), 19232c61054cSTony Nguyen GFP_KERNEL); 19242c61054cSTony Nguyen if (!rss_cfg) 19252c61054cSTony Nguyen return ICE_ERR_NO_MEMORY; 19262c61054cSTony Nguyen 19272c61054cSTony Nguyen rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; 19282c61054cSTony Nguyen rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; 19292c61054cSTony Nguyen set_bit(vsi_handle, rss_cfg->vsis); 19302c61054cSTony Nguyen 19312c61054cSTony Nguyen list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head); 19322c61054cSTony Nguyen 19332c61054cSTony Nguyen return 0; 19342c61054cSTony Nguyen } 19352c61054cSTony Nguyen 193631ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_S 0 193731ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 193831ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_S 32 193931ad4e4eSTony Nguyen #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 194031ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_S 63 194131ad4e4eSTony Nguyen #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) 194231ad4e4eSTony Nguyen 1943c90ed40cSTony Nguyen #define ICE_RSS_OUTER_HEADERS 1 1944a4e82a81STony Nguyen #define ICE_RSS_INNER_HEADERS 2 1945c90ed40cSTony Nguyen 194631ad4e4eSTony Nguyen /* Flow profile ID format: 194731ad4e4eSTony Nguyen * [0:31] - Packet match fields 194831ad4e4eSTony Nguyen * [32:62] - Protocol header 194931ad4e4eSTony Nguyen * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled 195031ad4e4eSTony Nguyen */ 195131ad4e4eSTony Nguyen #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ 195231ad4e4eSTony Nguyen (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 195331ad4e4eSTony Nguyen (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 195431ad4e4eSTony Nguyen ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)) 195531ad4e4eSTony Nguyen 1956c90ed40cSTony Nguyen /** 1957c90ed40cSTony Nguyen * ice_add_rss_cfg_sync - add an RSS configuration 195831ad4e4eSTony Nguyen * @hw: pointer to the hardware structure 1959451f2c44STony Nguyen * @vsi_handle: software VSI handle 1960c90ed40cSTony Nguyen * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 1961c90ed40cSTony Nguyen * @addl_hdrs: protocol header fields 1962c90ed40cSTony Nguyen * @segs_cnt: packet segment count 1963c90ed40cSTony Nguyen * 1964c90ed40cSTony Nguyen * Assumption: lock has already been acquired for RSS list 1965c90ed40cSTony Nguyen */ 1966c90ed40cSTony Nguyen static enum ice_status 1967451f2c44STony Nguyen ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1968451f2c44STony Nguyen u32 addl_hdrs, u8 segs_cnt) 1969c90ed40cSTony Nguyen { 1970451f2c44STony Nguyen const enum ice_block blk = ICE_BLK_RSS; 1971451f2c44STony Nguyen struct ice_flow_prof *prof = NULL; 1972c90ed40cSTony Nguyen struct ice_flow_seg_info *segs; 1973c90ed40cSTony Nguyen enum ice_status status; 1974c90ed40cSTony Nguyen 1975c90ed40cSTony Nguyen if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX) 1976c90ed40cSTony Nguyen return ICE_ERR_PARAM; 1977c90ed40cSTony Nguyen 1978c90ed40cSTony Nguyen segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL); 1979c90ed40cSTony Nguyen if (!segs) 1980c90ed40cSTony Nguyen return ICE_ERR_NO_MEMORY; 1981c90ed40cSTony Nguyen 1982c90ed40cSTony Nguyen /* Construct the packet segment info from the hashed fields */ 1983c90ed40cSTony Nguyen status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, 1984c90ed40cSTony Nguyen addl_hdrs); 198531ad4e4eSTony Nguyen if (status) 198631ad4e4eSTony Nguyen goto exit; 1987c90ed40cSTony Nguyen 19882c61054cSTony Nguyen /* Search for a flow profile that has matching headers, hash fields 19892c61054cSTony Nguyen * and has the input VSI associated to it. If found, no further 19902c61054cSTony Nguyen * operations required and exit. 19912c61054cSTony Nguyen */ 19922c61054cSTony Nguyen prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 19932c61054cSTony Nguyen vsi_handle, 19942c61054cSTony Nguyen ICE_FLOW_FIND_PROF_CHK_FLDS | 19952c61054cSTony Nguyen ICE_FLOW_FIND_PROF_CHK_VSI); 19962c61054cSTony Nguyen if (prof) 19972c61054cSTony Nguyen goto exit; 19982c61054cSTony Nguyen 19992c61054cSTony Nguyen /* Check if a flow profile exists with the same protocol headers and 20002c61054cSTony Nguyen * associated with the input VSI. If so disassociate the VSI from 20012c61054cSTony Nguyen * this profile. The VSI will be added to a new profile created with 20022c61054cSTony Nguyen * the protocol header and new hash field configuration. 20032c61054cSTony Nguyen */ 20042c61054cSTony Nguyen prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 20052c61054cSTony Nguyen vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 20062c61054cSTony Nguyen if (prof) { 20072c61054cSTony Nguyen status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 20082c61054cSTony Nguyen if (!status) 20092c61054cSTony Nguyen ice_rem_rss_list(hw, vsi_handle, prof); 20102c61054cSTony Nguyen else 20112c61054cSTony Nguyen goto exit; 20122c61054cSTony Nguyen 20132c61054cSTony Nguyen /* Remove profile if it has no VSIs associated */ 20142c61054cSTony Nguyen if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) { 20152c61054cSTony Nguyen status = ice_flow_rem_prof(hw, blk, prof->id); 20162c61054cSTony Nguyen if (status) 20172c61054cSTony Nguyen goto exit; 20182c61054cSTony Nguyen } 20192c61054cSTony Nguyen } 20202c61054cSTony Nguyen 20212c61054cSTony Nguyen /* Search for a profile that has same match fields only. If this 20222c61054cSTony Nguyen * exists then associate the VSI to this profile. 20232c61054cSTony Nguyen */ 20242c61054cSTony Nguyen prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 20252c61054cSTony Nguyen vsi_handle, 20262c61054cSTony Nguyen ICE_FLOW_FIND_PROF_CHK_FLDS); 20272c61054cSTony Nguyen if (prof) { 20282c61054cSTony Nguyen status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 20292c61054cSTony Nguyen if (!status) 20302c61054cSTony Nguyen status = ice_add_rss_list(hw, vsi_handle, prof); 20312c61054cSTony Nguyen goto exit; 20322c61054cSTony Nguyen } 20332c61054cSTony Nguyen 203431ad4e4eSTony Nguyen /* Create a new flow profile with generated profile and packet 203531ad4e4eSTony Nguyen * segment information. 203631ad4e4eSTony Nguyen */ 2037451f2c44STony Nguyen status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 203831ad4e4eSTony Nguyen ICE_FLOW_GEN_PROFID(hashed_flds, 203931ad4e4eSTony Nguyen segs[segs_cnt - 1].hdrs, 204031ad4e4eSTony Nguyen segs_cnt), 2041451f2c44STony Nguyen segs, segs_cnt, &prof); 2042451f2c44STony Nguyen if (status) 2043451f2c44STony Nguyen goto exit; 2044451f2c44STony Nguyen 2045451f2c44STony Nguyen status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 20462c61054cSTony Nguyen /* If association to a new flow profile failed then this profile can 20472c61054cSTony Nguyen * be removed. 20482c61054cSTony Nguyen */ 20492c61054cSTony Nguyen if (status) { 20502c61054cSTony Nguyen ice_flow_rem_prof(hw, blk, prof->id); 20512c61054cSTony Nguyen goto exit; 20522c61054cSTony Nguyen } 20532c61054cSTony Nguyen 20542c61054cSTony Nguyen status = ice_add_rss_list(hw, vsi_handle, prof); 205531ad4e4eSTony Nguyen 205631ad4e4eSTony Nguyen exit: 2057c90ed40cSTony Nguyen kfree(segs); 2058c90ed40cSTony Nguyen return status; 2059c90ed40cSTony Nguyen } 2060c90ed40cSTony Nguyen 2061c90ed40cSTony Nguyen /** 2062c90ed40cSTony Nguyen * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 2063c90ed40cSTony Nguyen * @hw: pointer to the hardware structure 2064c90ed40cSTony Nguyen * @vsi_handle: software VSI handle 2065c90ed40cSTony Nguyen * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 2066c90ed40cSTony Nguyen * @addl_hdrs: protocol header fields 2067c90ed40cSTony Nguyen * 2068c90ed40cSTony Nguyen * This function will generate a flow profile based on fields associated with 2069c90ed40cSTony Nguyen * the input fields to hash on, the flow type and use the VSI number to add 2070c90ed40cSTony Nguyen * a flow entry to the profile. 2071c90ed40cSTony Nguyen */ 2072c90ed40cSTony Nguyen enum ice_status 2073c90ed40cSTony Nguyen ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 2074c90ed40cSTony Nguyen u32 addl_hdrs) 2075c90ed40cSTony Nguyen { 2076c90ed40cSTony Nguyen enum ice_status status; 2077c90ed40cSTony Nguyen 2078c90ed40cSTony Nguyen if (hashed_flds == ICE_HASH_INVALID || 2079c90ed40cSTony Nguyen !ice_is_vsi_valid(hw, vsi_handle)) 2080c90ed40cSTony Nguyen return ICE_ERR_PARAM; 2081c90ed40cSTony Nguyen 2082c90ed40cSTony Nguyen mutex_lock(&hw->rss_locks); 2083451f2c44STony Nguyen status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, 2084c90ed40cSTony Nguyen ICE_RSS_OUTER_HEADERS); 2085a4e82a81STony Nguyen if (!status) 2086a4e82a81STony Nguyen status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, 2087a4e82a81STony Nguyen addl_hdrs, ICE_RSS_INNER_HEADERS); 2088c90ed40cSTony Nguyen mutex_unlock(&hw->rss_locks); 2089c90ed40cSTony Nguyen 2090c90ed40cSTony Nguyen return status; 2091c90ed40cSTony Nguyen } 2092c90ed40cSTony Nguyen 20931c01c8c6SMd Fahad Iqbal Polash /* Mapping of AVF hash bit fields to an L3-L4 hash combination. 20941c01c8c6SMd Fahad Iqbal Polash * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 20951c01c8c6SMd Fahad Iqbal Polash * convert its values to their appropriate flow L3, L4 values. 20961c01c8c6SMd Fahad Iqbal Polash */ 20971c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 20981c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 20991c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 21001c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 21011c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 21021c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 21031c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 21041c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 21051c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 21061c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 21071c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 21081c01c8c6SMd Fahad Iqbal Polash (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 21091c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 21101c01c8c6SMd Fahad Iqbal Polash 21111c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 21121c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 21131c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 21141c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 21151c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 21161c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 21171c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 21181c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 21191c01c8c6SMd Fahad Iqbal Polash (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 21201c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 21211c01c8c6SMd Fahad Iqbal Polash #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 21221c01c8c6SMd Fahad Iqbal Polash (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 21231c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 21241c01c8c6SMd Fahad Iqbal Polash 21251c01c8c6SMd Fahad Iqbal Polash /** 21261c01c8c6SMd Fahad Iqbal Polash * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 21271c01c8c6SMd Fahad Iqbal Polash * @hw: pointer to the hardware structure 21281c01c8c6SMd Fahad Iqbal Polash * @vsi_handle: software VSI handle 21291c01c8c6SMd Fahad Iqbal Polash * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 21301c01c8c6SMd Fahad Iqbal Polash * 21311c01c8c6SMd Fahad Iqbal Polash * This function will take the hash bitmap provided by the AVF driver via a 21321c01c8c6SMd Fahad Iqbal Polash * message, convert it to ICE-compatible values, and configure RSS flow 21331c01c8c6SMd Fahad Iqbal Polash * profiles. 21341c01c8c6SMd Fahad Iqbal Polash */ 21351c01c8c6SMd Fahad Iqbal Polash enum ice_status 21361c01c8c6SMd Fahad Iqbal Polash ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 21371c01c8c6SMd Fahad Iqbal Polash { 21381c01c8c6SMd Fahad Iqbal Polash enum ice_status status = 0; 21391c01c8c6SMd Fahad Iqbal Polash u64 hash_flds; 21401c01c8c6SMd Fahad Iqbal Polash 21411c01c8c6SMd Fahad Iqbal Polash if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 21421c01c8c6SMd Fahad Iqbal Polash !ice_is_vsi_valid(hw, vsi_handle)) 21431c01c8c6SMd Fahad Iqbal Polash return ICE_ERR_PARAM; 21441c01c8c6SMd Fahad Iqbal Polash 21451c01c8c6SMd Fahad Iqbal Polash /* Make sure no unsupported bits are specified */ 21461c01c8c6SMd Fahad Iqbal Polash if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 21471c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 21481c01c8c6SMd Fahad Iqbal Polash return ICE_ERR_CFG; 21491c01c8c6SMd Fahad Iqbal Polash 21501c01c8c6SMd Fahad Iqbal Polash hash_flds = avf_hash; 21511c01c8c6SMd Fahad Iqbal Polash 21521c01c8c6SMd Fahad Iqbal Polash /* Always create an L3 RSS configuration for any L4 RSS configuration */ 21531c01c8c6SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 21541c01c8c6SMd Fahad Iqbal Polash hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 21551c01c8c6SMd Fahad Iqbal Polash 21561c01c8c6SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 21571c01c8c6SMd Fahad Iqbal Polash hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 21581c01c8c6SMd Fahad Iqbal Polash 21591c01c8c6SMd Fahad Iqbal Polash /* Create the corresponding RSS configuration for each valid hash bit */ 21601c01c8c6SMd Fahad Iqbal Polash while (hash_flds) { 21611c01c8c6SMd Fahad Iqbal Polash u64 rss_hash = ICE_HASH_INVALID; 21621c01c8c6SMd Fahad Iqbal Polash 21631c01c8c6SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 21641c01c8c6SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 21651c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV4; 21661c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 21671c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21681c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 21691c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV4 | 21701c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_TCP_PORT; 21711c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 21721c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21731c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 21741c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV4 | 21751c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_UDP_PORT; 21761c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 21771c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21781c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 21791c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV4 | 21801c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_SCTP_PORT; 21811c01c8c6SMd Fahad Iqbal Polash hash_flds &= 21821c01c8c6SMd Fahad Iqbal Polash ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 21831c01c8c6SMd Fahad Iqbal Polash } 21841c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 21851c01c8c6SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 21861c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV6; 21871c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 21881c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21891c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 21901c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV6 | 21911c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_TCP_PORT; 21921c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 21931c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21941c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 21951c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV6 | 21961c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_UDP_PORT; 21971c01c8c6SMd Fahad Iqbal Polash hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 21981c01c8c6SMd Fahad Iqbal Polash } else if (hash_flds & 21991c01c8c6SMd Fahad Iqbal Polash BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 22001c01c8c6SMd Fahad Iqbal Polash rss_hash = ICE_FLOW_HASH_IPV6 | 22011c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_HASH_SCTP_PORT; 22021c01c8c6SMd Fahad Iqbal Polash hash_flds &= 22031c01c8c6SMd Fahad Iqbal Polash ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 22041c01c8c6SMd Fahad Iqbal Polash } 22051c01c8c6SMd Fahad Iqbal Polash } 22061c01c8c6SMd Fahad Iqbal Polash 22071c01c8c6SMd Fahad Iqbal Polash if (rss_hash == ICE_HASH_INVALID) 22081c01c8c6SMd Fahad Iqbal Polash return ICE_ERR_OUT_OF_RANGE; 22091c01c8c6SMd Fahad Iqbal Polash 22101c01c8c6SMd Fahad Iqbal Polash status = ice_add_rss_cfg(hw, vsi_handle, rss_hash, 22111c01c8c6SMd Fahad Iqbal Polash ICE_FLOW_SEG_HDR_NONE); 22121c01c8c6SMd Fahad Iqbal Polash if (status) 22131c01c8c6SMd Fahad Iqbal Polash break; 22141c01c8c6SMd Fahad Iqbal Polash } 22151c01c8c6SMd Fahad Iqbal Polash 22161c01c8c6SMd Fahad Iqbal Polash return status; 22171c01c8c6SMd Fahad Iqbal Polash } 22181c01c8c6SMd Fahad Iqbal Polash 2219c90ed40cSTony Nguyen /** 2220c90ed40cSTony Nguyen * ice_replay_rss_cfg - replay RSS configurations associated with VSI 2221c90ed40cSTony Nguyen * @hw: pointer to the hardware structure 2222c90ed40cSTony Nguyen * @vsi_handle: software VSI handle 2223c90ed40cSTony Nguyen */ 2224c90ed40cSTony Nguyen enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 2225c90ed40cSTony Nguyen { 2226c90ed40cSTony Nguyen enum ice_status status = 0; 2227c90ed40cSTony Nguyen struct ice_rss_cfg *r; 2228c90ed40cSTony Nguyen 2229c90ed40cSTony Nguyen if (!ice_is_vsi_valid(hw, vsi_handle)) 2230c90ed40cSTony Nguyen return ICE_ERR_PARAM; 2231c90ed40cSTony Nguyen 2232c90ed40cSTony Nguyen mutex_lock(&hw->rss_locks); 2233c90ed40cSTony Nguyen list_for_each_entry(r, &hw->rss_list_head, l_entry) { 2234c90ed40cSTony Nguyen if (test_bit(vsi_handle, r->vsis)) { 2235451f2c44STony Nguyen status = ice_add_rss_cfg_sync(hw, vsi_handle, 2236451f2c44STony Nguyen r->hashed_flds, 2237c90ed40cSTony Nguyen r->packet_hdr, 2238c90ed40cSTony Nguyen ICE_RSS_OUTER_HEADERS); 2239c90ed40cSTony Nguyen if (status) 2240c90ed40cSTony Nguyen break; 2241a4e82a81STony Nguyen status = ice_add_rss_cfg_sync(hw, vsi_handle, 2242a4e82a81STony Nguyen r->hashed_flds, 2243a4e82a81STony Nguyen r->packet_hdr, 2244a4e82a81STony Nguyen ICE_RSS_INNER_HEADERS); 2245a4e82a81STony Nguyen if (status) 2246a4e82a81STony Nguyen break; 2247c90ed40cSTony Nguyen } 2248c90ed40cSTony Nguyen } 2249c90ed40cSTony Nguyen mutex_unlock(&hw->rss_locks); 2250c90ed40cSTony Nguyen 2251c90ed40cSTony Nguyen return status; 2252c90ed40cSTony Nguyen } 22536876fb64SMd Fahad Iqbal Polash 22546876fb64SMd Fahad Iqbal Polash /** 22556876fb64SMd Fahad Iqbal Polash * ice_get_rss_cfg - returns hashed fields for the given header types 22566876fb64SMd Fahad Iqbal Polash * @hw: pointer to the hardware structure 22576876fb64SMd Fahad Iqbal Polash * @vsi_handle: software VSI handle 22586876fb64SMd Fahad Iqbal Polash * @hdrs: protocol header type 22596876fb64SMd Fahad Iqbal Polash * 22606876fb64SMd Fahad Iqbal Polash * This function will return the match fields of the first instance of flow 22616876fb64SMd Fahad Iqbal Polash * profile having the given header types and containing input VSI 22626876fb64SMd Fahad Iqbal Polash */ 22636876fb64SMd Fahad Iqbal Polash u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 22646876fb64SMd Fahad Iqbal Polash { 2265cdedbab9SVignesh Sridhar u64 rss_hash = ICE_HASH_INVALID; 2266cdedbab9SVignesh Sridhar struct ice_rss_cfg *r; 22676876fb64SMd Fahad Iqbal Polash 22686876fb64SMd Fahad Iqbal Polash /* verify if the protocol header is non zero and VSI is valid */ 22696876fb64SMd Fahad Iqbal Polash if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 22706876fb64SMd Fahad Iqbal Polash return ICE_HASH_INVALID; 22716876fb64SMd Fahad Iqbal Polash 22726876fb64SMd Fahad Iqbal Polash mutex_lock(&hw->rss_locks); 22736876fb64SMd Fahad Iqbal Polash list_for_each_entry(r, &hw->rss_list_head, l_entry) 22746876fb64SMd Fahad Iqbal Polash if (test_bit(vsi_handle, r->vsis) && 22756876fb64SMd Fahad Iqbal Polash r->packet_hdr == hdrs) { 2276cdedbab9SVignesh Sridhar rss_hash = r->hashed_flds; 22776876fb64SMd Fahad Iqbal Polash break; 22786876fb64SMd Fahad Iqbal Polash } 22796876fb64SMd Fahad Iqbal Polash mutex_unlock(&hw->rss_locks); 22806876fb64SMd Fahad Iqbal Polash 2281cdedbab9SVignesh Sridhar return rss_hash; 22826876fb64SMd Fahad Iqbal Polash } 2283