1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2020 Intel Corporation 3 */ 4 5 #include "ice_common.h" 6 #include "ice_flow.h" 7 8 /* Size of known protocol header fields */ 9 #define ICE_FLOW_FLD_SZ_ETH_TYPE 2 10 #define ICE_FLOW_FLD_SZ_VLAN 2 11 #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4 12 #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16 13 #define ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR 4 14 #define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR 6 15 #define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR 8 16 #define ICE_FLOW_FLD_SZ_IP_DSCP 1 17 #define ICE_FLOW_FLD_SZ_IP_TTL 1 18 #define ICE_FLOW_FLD_SZ_IP_PROT 1 19 #define ICE_FLOW_FLD_SZ_PORT 2 20 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1 21 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1 22 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1 23 #define ICE_FLOW_FLD_SZ_ARP_OPER 2 24 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4 25 #define ICE_FLOW_FLD_SZ_GTP_TEID 4 26 #define ICE_FLOW_FLD_SZ_GTP_QFI 2 27 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2 28 #define ICE_FLOW_FLD_SZ_PFCP_SEID 8 29 #define ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID 4 30 #define ICE_FLOW_FLD_SZ_ESP_SPI 4 31 #define ICE_FLOW_FLD_SZ_AH_SPI 4 32 #define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI 4 33 #define ICE_FLOW_FLD_SZ_VXLAN_VNI 4 34 #define ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID 2 35 36 /* Describe properties of a protocol header field */ 37 struct ice_flow_field_info { 38 enum ice_flow_seg_hdr hdr; 39 s16 off; /* Offset from start of a protocol header, in bits */ 40 u16 size; /* Size of fields in bits */ 41 u16 mask; /* 16-bit mask for field */ 42 }; 43 44 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 45 .hdr = _hdr, \ 46 .off = (_offset_bytes) * BITS_PER_BYTE, \ 47 .size = (_size_bytes) * BITS_PER_BYTE, \ 48 .mask = 0, \ 49 } 50 51 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \ 52 .hdr = _hdr, \ 53 .off = (_offset_bytes) * BITS_PER_BYTE, \ 54 .size = (_size_bytes) * BITS_PER_BYTE, \ 55 .mask = _mask, \ 56 } 57 58 /* Table containing properties of supported protocol header fields */ 59 static const 60 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 61 /* Ether */ 62 /* ICE_FLOW_FIELD_IDX_ETH_DA */ 63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 64 /* ICE_FLOW_FIELD_IDX_ETH_SA */ 65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 66 /* ICE_FLOW_FIELD_IDX_S_VLAN */ 67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN), 68 /* ICE_FLOW_FIELD_IDX_C_VLAN */ 69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN), 70 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 71 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE), 72 /* IPv4 / IPv6 */ 73 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 74 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP, 75 0x00fc), 76 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 77 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP, 78 0x0ff0), 79 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 80 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 81 ICE_FLOW_FLD_SZ_IP_TTL, 0xff00), 82 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 83 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 84 ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff), 85 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 86 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 87 ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff), 88 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */ 89 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 90 ICE_FLOW_FLD_SZ_IP_PROT, 0xff00), 91 /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR), 93 /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR), 95 /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR), 97 /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR), 99 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */ 100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, 101 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR), 102 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */ 103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, 104 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR), 105 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */ 106 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, 107 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR), 108 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */ 109 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, 110 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR), 111 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */ 112 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, 113 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR), 114 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */ 115 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, 116 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR), 117 /* Transport */ 118 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT), 120 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 121 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT), 122 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 123 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT), 124 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT), 126 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 127 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT), 128 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 129 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT), 130 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS), 132 /* ARP */ 133 /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 134 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR), 135 /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 136 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR), 137 /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 138 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 139 /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 140 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 141 /* ICE_FLOW_FIELD_IDX_ARP_OP */ 142 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER), 143 /* ICMP */ 144 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 145 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE), 146 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 147 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE), 148 /* GRE */ 149 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 150 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID), 151 /* GTP */ 152 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */ 153 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, 154 ICE_FLOW_FLD_SZ_GTP_TEID), 155 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */ 156 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, 157 ICE_FLOW_FLD_SZ_GTP_TEID), 158 /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */ 159 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, 160 ICE_FLOW_FLD_SZ_GTP_TEID), 161 /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */ 162 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, 163 ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00), 164 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */ 165 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, 166 ICE_FLOW_FLD_SZ_GTP_TEID), 167 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */ 168 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, 169 ICE_FLOW_FLD_SZ_GTP_TEID), 170 /* PPPOE */ 171 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */ 172 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, 173 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID), 174 /* PFCP */ 175 /* ICE_FLOW_FIELD_IDX_PFCP_SEID */ 176 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, 177 ICE_FLOW_FLD_SZ_PFCP_SEID), 178 /* L2TPV3 */ 179 /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */ 180 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, 181 ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID), 182 /* ESP */ 183 /* ICE_FLOW_FIELD_IDX_ESP_SPI */ 184 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, 185 ICE_FLOW_FLD_SZ_ESP_SPI), 186 /* AH */ 187 /* ICE_FLOW_FIELD_IDX_AH_SPI */ 188 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, 189 ICE_FLOW_FLD_SZ_AH_SPI), 190 /* NAT_T_ESP */ 191 /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */ 192 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, 193 ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI), 194 /* ICE_FLOW_FIELD_IDX_VXLAN_VNI */ 195 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VXLAN, 12, 196 ICE_FLOW_FLD_SZ_VXLAN_VNI), 197 /* ECPRI_TP0 */ 198 /* ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID */ 199 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ECPRI_TP0, 4, 200 ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID), 201 /* UDP_ECPRI_TP0 */ 202 /* ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID */ 203 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0, 12, 204 ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID), 205 }; 206 207 /* Bitmaps indicating relevant packet types for a particular protocol header 208 * 209 * Packet types for packets with an Outer/First/Single MAC header 210 */ 211 static const u32 ice_ptypes_mac_ofos[] = { 212 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 213 0x0000077E, 0x000003FF, 0x00000000, 0x00000000, 214 0x00400000, 0x03FFF000, 0xFFFFFFE0, 0x00100707, 215 0x00000000, 0x00000000, 0x00000000, 0x00000000, 216 0x00000000, 0x00000000, 0x00000000, 0x00000000, 217 0x00000000, 0x00000000, 0x00000000, 0x00000000, 218 0x00000000, 0x00000000, 0x00000000, 0x00000000, 219 0x00000000, 0x00000000, 0x00000000, 0x00000000, 220 }; 221 222 /* Packet types for packets with an Innermost/Last MAC VLAN header */ 223 static const u32 ice_ptypes_macvlan_il[] = { 224 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 225 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 226 0x00000000, 0x00000000, 0x00000000, 0x00000000, 227 0x00000000, 0x00000000, 0x00000000, 0x00000000, 228 0x00000000, 0x00000000, 0x00000000, 0x00000000, 229 0x00000000, 0x00000000, 0x00000000, 0x00000000, 230 0x00000000, 0x00000000, 0x00000000, 0x00000000, 231 0x00000000, 0x00000000, 0x00000000, 0x00000000, 232 }; 233 234 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT 235 * include IPV4 other PTYPEs 236 */ 237 static const u32 ice_ptypes_ipv4_ofos[] = { 238 0x1DC00000, 0x24000800, 0x00000000, 0x00000000, 239 0x00000000, 0x00000155, 0x00000000, 0x00000000, 240 0x00000000, 0x000FC000, 0x000002A0, 0x00100000, 241 0x00000000, 0x00000000, 0x00000000, 0x00000000, 242 0x00000000, 0x00000000, 0x00000000, 0x00000000, 243 0x00000000, 0x00000000, 0x00000000, 0x00000000, 244 0x00000000, 0x00000000, 0x00000000, 0x00000000, 245 0x00000000, 0x00000000, 0x00000000, 0x00000000, 246 }; 247 248 /* Packet types for packets with an Outer/First/Single IPv4 header, includes 249 * IPV4 other PTYPEs 250 */ 251 static const u32 ice_ptypes_ipv4_ofos_all[] = { 252 0x1DC00000, 0x24000800, 0x00000000, 0x00000000, 253 0x00000000, 0x00000155, 0x00000000, 0x00000000, 254 0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101, 255 0x00000000, 0x00000000, 0x00000000, 0x00000000, 256 0x00000000, 0x00000000, 0x00000000, 0x00000000, 257 0x00000000, 0x00000000, 0x00000000, 0x00000000, 258 0x00000000, 0x00000000, 0x00000000, 0x00000000, 259 0x00000000, 0x00000000, 0x00000000, 0x00000000, 260 }; 261 262 /* Packet types for packets with an Innermost/Last IPv4 header */ 263 static const u32 ice_ptypes_ipv4_il[] = { 264 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 265 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 266 0x00000000, 0x00000000, 0x001FF800, 0x00100000, 267 0x00000000, 0x00000000, 0x00000000, 0x00000000, 268 0x00000000, 0x00000000, 0x00000000, 0x00000000, 269 0x00000000, 0x00000000, 0x00000000, 0x00000000, 270 0x00000000, 0x00000000, 0x00000000, 0x00000000, 271 0x00000000, 0x00000000, 0x00000000, 0x00000000, 272 }; 273 274 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT 275 * include IVP6 other PTYPEs 276 */ 277 static const u32 ice_ptypes_ipv6_ofos[] = { 278 0x00000000, 0x00000000, 0x77000000, 0x10002000, 279 0x00000000, 0x000002AA, 0x00000000, 0x00000000, 280 0x00000000, 0x03F00000, 0x00000540, 0x00000000, 281 0x00000000, 0x00000000, 0x00000000, 0x00000000, 282 0x00000000, 0x00000000, 0x00000000, 0x00000000, 283 0x00000000, 0x00000000, 0x00000000, 0x00000000, 284 0x00000000, 0x00000000, 0x00000000, 0x00000000, 285 0x00000000, 0x00000000, 0x00000000, 0x00000000, 286 }; 287 288 /* Packet types for packets with an Outer/First/Single IPv6 header, includes 289 * IPV6 other PTYPEs 290 */ 291 static const u32 ice_ptypes_ipv6_ofos_all[] = { 292 0x00000000, 0x00000000, 0x77000000, 0x10002000, 293 0x00000000, 0x000002AA, 0x00000000, 0x00000000, 294 0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206, 295 0x00000000, 0x00000000, 0x00000000, 0x00000000, 296 0x00000000, 0x00000000, 0x00000000, 0x00000000, 297 0x00000000, 0x00000000, 0x00000000, 0x00000000, 298 0x00000000, 0x00000000, 0x00000000, 0x00000000, 299 0x00000000, 0x00000000, 0x00000000, 0x00000000, 300 }; 301 302 /* Packet types for packets with an Innermost/Last IPv6 header */ 303 static const u32 ice_ptypes_ipv6_il[] = { 304 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 305 0x00000770, 0x00000000, 0x00000000, 0x00000000, 306 0x00000000, 0x00000000, 0x7FE00000, 0x00000000, 307 0x00000000, 0x00000000, 0x00000000, 0x00000000, 308 0x00000000, 0x00000000, 0x00000000, 0x00000000, 309 0x00000000, 0x00000000, 0x00000000, 0x00000000, 310 0x00000000, 0x00000000, 0x00000000, 0x00000000, 311 0x00000000, 0x00000000, 0x00000000, 0x00000000, 312 }; 313 314 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */ 315 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = { 316 0x10C00000, 0x04000800, 0x00000000, 0x00000000, 317 0x00000000, 0x00000000, 0x00000000, 0x00000000, 318 0x00000000, 0x000cc000, 0x000002A0, 0x00000000, 319 0x00000000, 0x00000000, 0x00000000, 0x00000000, 320 0x00000000, 0x00000000, 0x00000000, 0x00000000, 321 0x00000000, 0x00000000, 0x00000000, 0x00000000, 322 0x00000000, 0x00000000, 0x00000000, 0x00000000, 323 0x00000000, 0x00000000, 0x00000000, 0x00000000, 324 }; 325 326 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 327 static const u32 ice_ptypes_ipv4_il_no_l4[] = { 328 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 329 0x00000008, 0x00000000, 0x00000000, 0x00000000, 330 0x00000000, 0x00000000, 0x00139800, 0x00000000, 331 0x00000000, 0x00000000, 0x00000000, 0x00000000, 332 0x00000000, 0x00000000, 0x00000000, 0x00000000, 333 0x00000000, 0x00000000, 0x00000000, 0x00000000, 334 0x00000000, 0x00000000, 0x00000000, 0x00000000, 335 0x00000000, 0x00000000, 0x00000000, 0x00000000, 336 }; 337 338 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */ 339 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = { 340 0x00000000, 0x00000000, 0x43000000, 0x10002000, 341 0x00000000, 0x00000000, 0x00000000, 0x00000000, 342 0x00000000, 0x02300000, 0x00000540, 0x00000000, 343 0x00000000, 0x00000000, 0x00000000, 0x00000000, 344 0x00000000, 0x00000000, 0x00000000, 0x00000000, 345 0x00000000, 0x00000000, 0x00000000, 0x00000000, 346 0x00000000, 0x00000000, 0x00000000, 0x00000000, 347 0x00000000, 0x00000000, 0x00000000, 0x00000000, 348 }; 349 350 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 351 static const u32 ice_ptypes_ipv6_il_no_l4[] = { 352 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 353 0x00000430, 0x00000000, 0x00000000, 0x00000000, 354 0x00000000, 0x00000000, 0x4e600000, 0x00000000, 355 0x00000000, 0x00000000, 0x00000000, 0x00000000, 356 0x00000000, 0x00000000, 0x00000000, 0x00000000, 357 0x00000000, 0x00000000, 0x00000000, 0x00000000, 358 0x00000000, 0x00000000, 0x00000000, 0x00000000, 359 0x00000000, 0x00000000, 0x00000000, 0x00000000, 360 }; 361 362 /* Packet types for packets with an Outermost/First ARP header */ 363 static const u32 ice_ptypes_arp_of[] = { 364 0x00000800, 0x00000000, 0x00000000, 0x00000000, 365 0x00000000, 0x00000000, 0x00000000, 0x00000000, 366 0x00000000, 0x00000000, 0x00000000, 0x00000000, 367 0x00000000, 0x00000000, 0x00000000, 0x00000000, 368 0x00000000, 0x00000000, 0x00000000, 0x00000000, 369 0x00000000, 0x00000000, 0x00000000, 0x00000000, 370 0x00000000, 0x00000000, 0x00000000, 0x00000000, 371 0x00000000, 0x00000000, 0x00000000, 0x00000000, 372 }; 373 374 /* UDP Packet types for non-tunneled packets or tunneled 375 * packets with inner UDP. 376 */ 377 static const u32 ice_ptypes_udp_il[] = { 378 0x81000000, 0x20204040, 0x04000010, 0x80810102, 379 0x00000040, 0x00000000, 0x00000000, 0x00000000, 380 0x00000000, 0x00410000, 0x908427E0, 0x00100007, 381 0x00000000, 0x00000000, 0x00000000, 0x00000000, 382 0x00000000, 0x00000000, 0x00000000, 0x00000000, 383 0x00000000, 0x00000000, 0x00000000, 0x00000000, 384 0x00000000, 0x00000000, 0x00000000, 0x00000000, 385 0x00000000, 0x00000000, 0x00000000, 0x00000000, 386 }; 387 388 /* Packet types for packets with an Innermost/Last TCP header */ 389 static const u32 ice_ptypes_tcp_il[] = { 390 0x04000000, 0x80810102, 0x10000040, 0x02040408, 391 0x00000102, 0x00000000, 0x00000000, 0x00000000, 392 0x00000000, 0x00820000, 0x21084000, 0x00000000, 393 0x00000000, 0x00000000, 0x00000000, 0x00000000, 394 0x00000000, 0x00000000, 0x00000000, 0x00000000, 395 0x00000000, 0x00000000, 0x00000000, 0x00000000, 396 0x00000000, 0x00000000, 0x00000000, 0x00000000, 397 0x00000000, 0x00000000, 0x00000000, 0x00000000, 398 }; 399 400 /* Packet types for packets with an Innermost/Last SCTP header */ 401 static const u32 ice_ptypes_sctp_il[] = { 402 0x08000000, 0x01020204, 0x20000081, 0x04080810, 403 0x00000204, 0x00000000, 0x00000000, 0x00000000, 404 0x00000000, 0x01040000, 0x00000000, 0x00000000, 405 0x00000000, 0x00000000, 0x00000000, 0x00000000, 406 0x00000000, 0x00000000, 0x00000000, 0x00000000, 407 0x00000000, 0x00000000, 0x00000000, 0x00000000, 408 0x00000000, 0x00000000, 0x00000000, 0x00000000, 409 0x00000000, 0x00000000, 0x00000000, 0x00000000, 410 }; 411 412 /* Packet types for packets with an Outermost/First ICMP header */ 413 static const u32 ice_ptypes_icmp_of[] = { 414 0x10000000, 0x00000000, 0x00000000, 0x00000000, 415 0x00000000, 0x00000000, 0x00000000, 0x00000000, 416 0x00000000, 0x00000000, 0x00000000, 0x00000000, 417 0x00000000, 0x00000000, 0x00000000, 0x00000000, 418 0x00000000, 0x00000000, 0x00000000, 0x00000000, 419 0x00000000, 0x00000000, 0x00000000, 0x00000000, 420 0x00000000, 0x00000000, 0x00000000, 0x00000000, 421 0x00000000, 0x00000000, 0x00000000, 0x00000000, 422 }; 423 424 /* Packet types for packets with an Innermost/Last ICMP header */ 425 static const u32 ice_ptypes_icmp_il[] = { 426 0x00000000, 0x02040408, 0x40000102, 0x08101020, 427 0x00000408, 0x00000000, 0x00000000, 0x00000000, 428 0x00000000, 0x00000000, 0x42108000, 0x00000000, 429 0x00000000, 0x00000000, 0x00000000, 0x00000000, 430 0x00000000, 0x00000000, 0x00000000, 0x00000000, 431 0x00000000, 0x00000000, 0x00000000, 0x00000000, 432 0x00000000, 0x00000000, 0x00000000, 0x00000000, 433 0x00000000, 0x00000000, 0x00000000, 0x00000000, 434 }; 435 436 /* Packet types for packets with an Outermost/First GRE header */ 437 static const u32 ice_ptypes_gre_of[] = { 438 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, 439 0x0000017E, 0x00000000, 0x00000000, 0x00000000, 440 0x00000000, 0x00000000, 0x00000000, 0x00000000, 441 0x00000000, 0x00000000, 0x00000000, 0x00000000, 442 0x00000000, 0x00000000, 0x00000000, 0x00000000, 443 0x00000000, 0x00000000, 0x00000000, 0x00000000, 444 0x00000000, 0x00000000, 0x00000000, 0x00000000, 445 0x00000000, 0x00000000, 0x00000000, 0x00000000, 446 }; 447 448 /* Packet types for packets with an Innermost/Last MAC header */ 449 static const u32 ice_ptypes_mac_il[] = { 450 0x00000000, 0x20000000, 0x00000000, 0x00000000, 451 0x00000000, 0x00000000, 0x00000000, 0x00000000, 452 0x00000000, 0x00000000, 0x00000000, 0x00000000, 453 0x00000000, 0x00000000, 0x00000000, 0x00000000, 454 0x00000000, 0x00000000, 0x00000000, 0x00000000, 455 0x00000000, 0x00000000, 0x00000000, 0x00000000, 456 0x00000000, 0x00000000, 0x00000000, 0x00000000, 457 0x00000000, 0x00000000, 0x00000000, 0x00000000, 458 }; 459 460 /* Packet types for GTPC */ 461 static const u32 ice_ptypes_gtpc[] = { 462 0x00000000, 0x00000000, 0x00000000, 0x00000000, 463 0x00000000, 0x00000000, 0x00000000, 0x00000000, 464 0x00000000, 0x00000000, 0x000001E0, 0x00000000, 465 0x00000000, 0x00000000, 0x00000000, 0x00000000, 466 0x00000000, 0x00000000, 0x00000000, 0x00000000, 467 0x00000000, 0x00000000, 0x00000000, 0x00000000, 468 0x00000000, 0x00000000, 0x00000000, 0x00000000, 469 0x00000000, 0x00000000, 0x00000000, 0x00000000, 470 }; 471 472 /* Packet types for VXLAN with VNI */ 473 static const u32 ice_ptypes_vxlan_vni[] = { 474 0x00000000, 0xBFBFF800, 0x00EFDFDF, 0xFEFDE000, 475 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000, 476 0x00000000, 0x00000000, 0x00000000, 0x00000000, 477 0x00000000, 0x00000000, 0x00000000, 0x00000000, 478 0x00000000, 0x00000000, 0x00000000, 0x00000000, 479 0x00000000, 0x00000000, 0x00000000, 0x00000000, 480 0x00000000, 0x00000000, 0x00000000, 0x00000000, 481 0x00000000, 0x00000000, 0x00000000, 0x00000000, 482 }; 483 484 /* Packet types for GTPC with TEID */ 485 static const u32 ice_ptypes_gtpc_tid[] = { 486 0x00000000, 0x00000000, 0x00000000, 0x00000000, 487 0x00000000, 0x00000000, 0x00000000, 0x00000000, 488 0x00000000, 0x00000000, 0x00000060, 0x00000000, 489 0x00000000, 0x00000000, 0x00000000, 0x00000000, 490 0x00000000, 0x00000000, 0x00000000, 0x00000000, 491 0x00000000, 0x00000000, 0x00000000, 0x00000000, 492 0x00000000, 0x00000000, 0x00000000, 0x00000000, 493 0x00000000, 0x00000000, 0x00000000, 0x00000000, 494 }; 495 496 /* Packet types for GTPU */ 497 static const struct ice_ptype_attributes ice_attr_gtpu_session[] = { 498 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION }, 499 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 500 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 501 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION }, 502 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION }, 503 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION }, 504 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 505 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 506 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION }, 507 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION }, 508 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION }, 509 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 510 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 511 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION }, 512 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION }, 513 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION }, 514 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 515 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION }, 516 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION }, 517 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION }, 518 }; 519 520 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = { 521 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 522 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 523 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 524 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 525 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 526 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 527 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 528 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 529 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 530 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 531 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 532 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 533 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 534 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 535 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 536 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, 537 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 538 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, 539 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, 540 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, 541 }; 542 543 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = { 544 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 545 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 546 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 547 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 548 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 549 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 550 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 551 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 552 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 553 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 554 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 555 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 556 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 557 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 558 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 559 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 560 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 561 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 562 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 563 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, 564 }; 565 566 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = { 567 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 568 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 569 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 570 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 571 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 572 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 573 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 574 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 575 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 576 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, 577 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 578 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 579 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 580 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 581 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 582 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, 583 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 584 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, 585 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, 586 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, 587 }; 588 589 static const u32 ice_ptypes_gtpu[] = { 590 0x00000000, 0x00000000, 0x00000000, 0x00000000, 591 0x00000000, 0x00000000, 0x00000000, 0x00000000, 592 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000, 593 0x00000000, 0x00000000, 0x00000000, 0x00000000, 594 0x00000000, 0x00000000, 0x00000000, 0x00000000, 595 0x00000000, 0x00000000, 0x00000000, 0x00000000, 596 0x00000000, 0x00000000, 0x00000000, 0x00000000, 597 0x00000000, 0x00000000, 0x00000000, 0x00000000, 598 }; 599 600 /* Packet types for pppoe */ 601 static const u32 ice_ptypes_pppoe[] = { 602 0x00000000, 0x00000000, 0x00000000, 0x00000000, 603 0x00000000, 0x00000000, 0x00000000, 0x00000000, 604 0x00000000, 0x03ffe000, 0x00000000, 0x00000000, 605 0x00000000, 0x00000000, 0x00000000, 0x00000000, 606 0x00000000, 0x00000000, 0x00000000, 0x00000000, 607 0x00000000, 0x00000000, 0x00000000, 0x00000000, 608 0x00000000, 0x00000000, 0x00000000, 0x00000000, 609 0x00000000, 0x00000000, 0x00000000, 0x00000000, 610 }; 611 612 /* Packet types for packets with PFCP NODE header */ 613 static const u32 ice_ptypes_pfcp_node[] = { 614 0x00000000, 0x00000000, 0x00000000, 0x00000000, 615 0x00000000, 0x00000000, 0x00000000, 0x00000000, 616 0x00000000, 0x00000000, 0x80000000, 0x00000002, 617 0x00000000, 0x00000000, 0x00000000, 0x00000000, 618 0x00000000, 0x00000000, 0x00000000, 0x00000000, 619 0x00000000, 0x00000000, 0x00000000, 0x00000000, 620 0x00000000, 0x00000000, 0x00000000, 0x00000000, 621 0x00000000, 0x00000000, 0x00000000, 0x00000000, 622 }; 623 624 /* Packet types for packets with PFCP SESSION header */ 625 static const u32 ice_ptypes_pfcp_session[] = { 626 0x00000000, 0x00000000, 0x00000000, 0x00000000, 627 0x00000000, 0x00000000, 0x00000000, 0x00000000, 628 0x00000000, 0x00000000, 0x00000000, 0x00000005, 629 0x00000000, 0x00000000, 0x00000000, 0x00000000, 630 0x00000000, 0x00000000, 0x00000000, 0x00000000, 631 0x00000000, 0x00000000, 0x00000000, 0x00000000, 632 0x00000000, 0x00000000, 0x00000000, 0x00000000, 633 0x00000000, 0x00000000, 0x00000000, 0x00000000, 634 }; 635 636 /* Packet types for l2tpv3 */ 637 static const u32 ice_ptypes_l2tpv3[] = { 638 0x00000000, 0x00000000, 0x00000000, 0x00000000, 639 0x00000000, 0x00000000, 0x00000000, 0x00000000, 640 0x00000000, 0x00000000, 0x00000000, 0x00000300, 641 0x00000000, 0x00000000, 0x00000000, 0x00000000, 642 0x00000000, 0x00000000, 0x00000000, 0x00000000, 643 0x00000000, 0x00000000, 0x00000000, 0x00000000, 644 0x00000000, 0x00000000, 0x00000000, 0x00000000, 645 0x00000000, 0x00000000, 0x00000000, 0x00000000, 646 }; 647 648 /* Packet types for esp */ 649 static const u32 ice_ptypes_esp[] = { 650 0x00000000, 0x00000000, 0x00000000, 0x00000000, 651 0x00000000, 0x00000003, 0x00000000, 0x00000000, 652 0x00000000, 0x00000000, 0x00000000, 0x00000000, 653 0x00000000, 0x00000000, 0x00000000, 0x00000000, 654 0x00000000, 0x00000000, 0x00000000, 0x00000000, 655 0x00000000, 0x00000000, 0x00000000, 0x00000000, 656 0x00000000, 0x00000000, 0x00000000, 0x00000000, 657 0x00000000, 0x00000000, 0x00000000, 0x00000000, 658 }; 659 660 /* Packet types for ah */ 661 static const u32 ice_ptypes_ah[] = { 662 0x00000000, 0x00000000, 0x00000000, 0x00000000, 663 0x00000000, 0x0000000C, 0x00000000, 0x00000000, 664 0x00000000, 0x00000000, 0x00000000, 0x00000000, 665 0x00000000, 0x00000000, 0x00000000, 0x00000000, 666 0x00000000, 0x00000000, 0x00000000, 0x00000000, 667 0x00000000, 0x00000000, 0x00000000, 0x00000000, 668 0x00000000, 0x00000000, 0x00000000, 0x00000000, 669 0x00000000, 0x00000000, 0x00000000, 0x00000000, 670 }; 671 672 /* Packet types for packets with NAT_T ESP header */ 673 static const u32 ice_ptypes_nat_t_esp[] = { 674 0x00000000, 0x00000000, 0x00000000, 0x00000000, 675 0x00000000, 0x00000030, 0x00000000, 0x00000000, 676 0x00000000, 0x00000000, 0x00000000, 0x00000000, 677 0x00000000, 0x00000000, 0x00000000, 0x00000000, 678 0x00000000, 0x00000000, 0x00000000, 0x00000000, 679 0x00000000, 0x00000000, 0x00000000, 0x00000000, 680 0x00000000, 0x00000000, 0x00000000, 0x00000000, 681 0x00000000, 0x00000000, 0x00000000, 0x00000000, 682 }; 683 684 static const u32 ice_ptypes_mac_non_ip_ofos[] = { 685 0x00000846, 0x00000000, 0x00000000, 0x00000000, 686 0x00000000, 0x00000000, 0x00000000, 0x00000000, 687 0x00400000, 0x03FFF000, 0x00000000, 0x00000000, 688 0x00000000, 0x00000000, 0x00000000, 0x00000000, 689 0x00000000, 0x00000000, 0x00000000, 0x00000000, 690 0x00000000, 0x00000000, 0x00000000, 0x00000000, 691 0x00000000, 0x00000000, 0x00000000, 0x00000000, 692 0x00000000, 0x00000000, 0x00000000, 0x00000000, 693 }; 694 695 static const u32 ice_ptypes_gtpu_no_ip[] = { 696 0x00000000, 0x00000000, 0x00000000, 0x00000000, 697 0x00000000, 0x00000000, 0x00000000, 0x00000000, 698 0x00000000, 0x00000000, 0x00000600, 0x00000000, 699 0x00000000, 0x00000000, 0x00000000, 0x00000000, 700 0x00000000, 0x00000000, 0x00000000, 0x00000000, 701 0x00000000, 0x00000000, 0x00000000, 0x00000000, 702 0x00000000, 0x00000000, 0x00000000, 0x00000000, 703 0x00000000, 0x00000000, 0x00000000, 0x00000000, 704 }; 705 706 static const u32 ice_ptypes_ecpri_tp0[] = { 707 0x00000000, 0x00000000, 0x00000000, 0x00000000, 708 0x00000000, 0x00000000, 0x00000000, 0x00000000, 709 0x00000000, 0x00000000, 0x00000000, 0x00000400, 710 0x00000000, 0x00000000, 0x00000000, 0x00000000, 711 0x00000000, 0x00000000, 0x00000000, 0x00000000, 712 0x00000000, 0x00000000, 0x00000000, 0x00000000, 713 0x00000000, 0x00000000, 0x00000000, 0x00000000, 714 0x00000000, 0x00000000, 0x00000000, 0x00000000, 715 }; 716 717 static const u32 ice_ptypes_udp_ecpri_tp0[] = { 718 0x00000000, 0x00000000, 0x00000000, 0x00000000, 719 0x00000000, 0x00000000, 0x00000000, 0x00000000, 720 0x00000000, 0x00000000, 0x00000000, 0x00100000, 721 0x00000000, 0x00000000, 0x00000000, 0x00000000, 722 0x00000000, 0x00000000, 0x00000000, 0x00000000, 723 0x00000000, 0x00000000, 0x00000000, 0x00000000, 724 0x00000000, 0x00000000, 0x00000000, 0x00000000, 725 0x00000000, 0x00000000, 0x00000000, 0x00000000, 726 }; 727 728 /* Manage parameters and info. used during the creation of a flow profile */ 729 struct ice_flow_prof_params { 730 enum ice_block blk; 731 u16 entry_length; /* # of bytes formatted entry will require */ 732 u8 es_cnt; 733 struct ice_flow_prof *prof; 734 735 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 736 * This will give us the direction flags. 737 */ 738 struct ice_fv_word es[ICE_MAX_FV_WORDS]; 739 /* attributes can be used to add attributes to a particular PTYPE */ 740 const struct ice_ptype_attributes *attr; 741 u16 attr_cnt; 742 743 u16 mask[ICE_MAX_FV_WORDS]; 744 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX); 745 }; 746 747 #define ICE_FLOW_RSS_HDRS_INNER_MASK \ 748 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \ 749 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \ 750 ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \ 751 ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \ 752 ICE_FLOW_SEG_HDR_NAT_T_ESP | ICE_FLOW_SEG_HDR_GTPU_NON_IP | \ 753 ICE_FLOW_SEG_HDR_ECPRI_TP0 | ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0) 754 755 #define ICE_FLOW_SEG_HDRS_L2_MASK \ 756 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 757 #define ICE_FLOW_SEG_HDRS_L3_MASK \ 758 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \ 759 ICE_FLOW_SEG_HDR_ARP) 760 #define ICE_FLOW_SEG_HDRS_L4_MASK \ 761 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 762 ICE_FLOW_SEG_HDR_SCTP) 763 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */ 764 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \ 765 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 766 767 /** 768 * ice_flow_val_hdrs - validates packet segments for valid protocol headers 769 * @segs: array of one or more packet segments that describe the flow 770 * @segs_cnt: number of packet segments provided 771 */ 772 static enum ice_status 773 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 774 { 775 u8 i; 776 777 for (i = 0; i < segs_cnt; i++) { 778 /* Multiple L3 headers */ 779 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 780 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 781 return ICE_ERR_PARAM; 782 783 /* Multiple L4 headers */ 784 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 785 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 786 return ICE_ERR_PARAM; 787 } 788 789 return ICE_SUCCESS; 790 } 791 792 /* Sizes of fixed known protocol headers without header options */ 793 #define ICE_FLOW_PROT_HDR_SZ_MAC 14 794 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2) 795 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20 796 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40 797 #define ICE_FLOW_PROT_HDR_SZ_ARP 28 798 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8 799 #define ICE_FLOW_PROT_HDR_SZ_TCP 20 800 #define ICE_FLOW_PROT_HDR_SZ_UDP 8 801 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12 802 803 /** 804 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers 805 * @params: information about the flow to be processed 806 * @seg: index of packet segment whose header size is to be determined 807 */ 808 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg) 809 { 810 u16 sz; 811 812 /* L2 headers */ 813 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ? 814 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC; 815 816 /* L3 headers */ 817 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) 818 sz += ICE_FLOW_PROT_HDR_SZ_IPV4; 819 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) 820 sz += ICE_FLOW_PROT_HDR_SZ_IPV6; 821 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP) 822 sz += ICE_FLOW_PROT_HDR_SZ_ARP; 823 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK) 824 /* A L3 header is required if L4 is specified */ 825 return 0; 826 827 /* L4 headers */ 828 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP) 829 sz += ICE_FLOW_PROT_HDR_SZ_ICMP; 830 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP) 831 sz += ICE_FLOW_PROT_HDR_SZ_TCP; 832 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP) 833 sz += ICE_FLOW_PROT_HDR_SZ_UDP; 834 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP) 835 sz += ICE_FLOW_PROT_HDR_SZ_SCTP; 836 837 return sz; 838 } 839 840 /** 841 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 842 * @params: information about the flow to be processed 843 * 844 * This function identifies the packet types associated with the protocol 845 * headers being present in packet segments of the specified flow profile. 846 */ 847 static enum ice_status 848 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 849 { 850 struct ice_flow_prof *prof; 851 u8 i; 852 853 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes), 854 ICE_NONDMA_MEM); 855 856 prof = params->prof; 857 858 for (i = 0; i < params->prof->segs_cnt; i++) { 859 const ice_bitmap_t *src; 860 u32 hdrs; 861 862 hdrs = prof->segs[i].hdrs; 863 864 if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 865 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos : 866 (const ice_bitmap_t *)ice_ptypes_mac_il; 867 ice_and_bitmap(params->ptypes, params->ptypes, src, 868 ICE_FLOW_PTYPE_MAX); 869 } 870 871 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 872 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; 873 ice_and_bitmap(params->ptypes, params->ptypes, src, 874 ICE_FLOW_PTYPE_MAX); 875 } 876 877 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 878 ice_and_bitmap(params->ptypes, params->ptypes, 879 (const ice_bitmap_t *)ice_ptypes_arp_of, 880 ICE_FLOW_PTYPE_MAX); 881 } 882 883 if (hdrs & ICE_FLOW_SEG_HDR_ECPRI_TP0) { 884 src = (const ice_bitmap_t *)ice_ptypes_ecpri_tp0; 885 ice_and_bitmap(params->ptypes, params->ptypes, src, 886 ICE_FLOW_PTYPE_MAX); 887 } 888 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 889 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 890 src = i ? 891 (const ice_bitmap_t *)ice_ptypes_ipv4_il : 892 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all; 893 ice_and_bitmap(params->ptypes, params->ptypes, src, 894 ICE_FLOW_PTYPE_MAX); 895 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 896 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 897 src = i ? 898 (const ice_bitmap_t *)ice_ptypes_ipv6_il : 899 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all; 900 ice_and_bitmap(params->ptypes, params->ptypes, src, 901 ICE_FLOW_PTYPE_MAX); 902 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 903 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 904 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 : 905 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4; 906 ice_and_bitmap(params->ptypes, params->ptypes, src, 907 ICE_FLOW_PTYPE_MAX); 908 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 909 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos : 910 (const ice_bitmap_t *)ice_ptypes_ipv4_il; 911 ice_and_bitmap(params->ptypes, params->ptypes, src, 912 ICE_FLOW_PTYPE_MAX); 913 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 914 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 915 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 : 916 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4; 917 ice_and_bitmap(params->ptypes, params->ptypes, src, 918 ICE_FLOW_PTYPE_MAX); 919 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 920 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : 921 (const ice_bitmap_t *)ice_ptypes_ipv6_il; 922 ice_and_bitmap(params->ptypes, params->ptypes, src, 923 ICE_FLOW_PTYPE_MAX); 924 } 925 926 if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) { 927 src = (const ice_bitmap_t *)ice_ptypes_mac_non_ip_ofos; 928 ice_and_bitmap(params->ptypes, params->ptypes, 929 src, ICE_FLOW_PTYPE_MAX); 930 } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) { 931 src = (const ice_bitmap_t *)ice_ptypes_pppoe; 932 ice_and_bitmap(params->ptypes, params->ptypes, src, 933 ICE_FLOW_PTYPE_MAX); 934 } else { 935 src = (const ice_bitmap_t *)ice_ptypes_pppoe; 936 ice_andnot_bitmap(params->ptypes, params->ptypes, src, 937 ICE_FLOW_PTYPE_MAX); 938 } 939 940 if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 941 src = (const ice_bitmap_t *)ice_ptypes_udp_il; 942 ice_and_bitmap(params->ptypes, params->ptypes, src, 943 ICE_FLOW_PTYPE_MAX); 944 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 945 ice_and_bitmap(params->ptypes, params->ptypes, 946 (const ice_bitmap_t *)ice_ptypes_tcp_il, 947 ICE_FLOW_PTYPE_MAX); 948 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 949 src = (const ice_bitmap_t *)ice_ptypes_sctp_il; 950 ice_and_bitmap(params->ptypes, params->ptypes, src, 951 ICE_FLOW_PTYPE_MAX); 952 } 953 954 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 955 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of : 956 (const ice_bitmap_t *)ice_ptypes_icmp_il; 957 ice_and_bitmap(params->ptypes, params->ptypes, src, 958 ICE_FLOW_PTYPE_MAX); 959 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 960 if (!i) { 961 src = (const ice_bitmap_t *)ice_ptypes_gre_of; 962 ice_and_bitmap(params->ptypes, params->ptypes, 963 src, ICE_FLOW_PTYPE_MAX); 964 } 965 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) { 966 src = (const ice_bitmap_t *)ice_ptypes_gtpc; 967 ice_and_bitmap(params->ptypes, params->ptypes, 968 src, ICE_FLOW_PTYPE_MAX); 969 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) { 970 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid; 971 ice_and_bitmap(params->ptypes, params->ptypes, 972 src, ICE_FLOW_PTYPE_MAX); 973 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_NON_IP) { 974 src = (const ice_bitmap_t *)ice_ptypes_gtpu_no_ip; 975 ice_and_bitmap(params->ptypes, params->ptypes, 976 src, ICE_FLOW_PTYPE_MAX); 977 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) { 978 src = (const ice_bitmap_t *)ice_ptypes_gtpu; 979 ice_and_bitmap(params->ptypes, params->ptypes, 980 src, ICE_FLOW_PTYPE_MAX); 981 982 /* Attributes for GTP packet with downlink */ 983 params->attr = ice_attr_gtpu_down; 984 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down); 985 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) { 986 src = (const ice_bitmap_t *)ice_ptypes_gtpu; 987 ice_and_bitmap(params->ptypes, params->ptypes, 988 src, ICE_FLOW_PTYPE_MAX); 989 990 /* Attributes for GTP packet with uplink */ 991 params->attr = ice_attr_gtpu_up; 992 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up); 993 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) { 994 src = (const ice_bitmap_t *)ice_ptypes_gtpu; 995 ice_and_bitmap(params->ptypes, params->ptypes, 996 src, ICE_FLOW_PTYPE_MAX); 997 998 /* Attributes for GTP packet with Extension Header */ 999 params->attr = ice_attr_gtpu_eh; 1000 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh); 1001 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) { 1002 src = (const ice_bitmap_t *)ice_ptypes_gtpu; 1003 ice_and_bitmap(params->ptypes, params->ptypes, 1004 src, ICE_FLOW_PTYPE_MAX); 1005 1006 /* Attributes for GTP packet without Extension Header */ 1007 params->attr = ice_attr_gtpu_session; 1008 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session); 1009 } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) { 1010 src = (const ice_bitmap_t *)ice_ptypes_l2tpv3; 1011 ice_and_bitmap(params->ptypes, params->ptypes, 1012 src, ICE_FLOW_PTYPE_MAX); 1013 } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) { 1014 src = (const ice_bitmap_t *)ice_ptypes_esp; 1015 ice_and_bitmap(params->ptypes, params->ptypes, 1016 src, ICE_FLOW_PTYPE_MAX); 1017 } else if (hdrs & ICE_FLOW_SEG_HDR_AH) { 1018 src = (const ice_bitmap_t *)ice_ptypes_ah; 1019 ice_and_bitmap(params->ptypes, params->ptypes, 1020 src, ICE_FLOW_PTYPE_MAX); 1021 } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) { 1022 src = (const ice_bitmap_t *)ice_ptypes_nat_t_esp; 1023 ice_and_bitmap(params->ptypes, params->ptypes, 1024 src, ICE_FLOW_PTYPE_MAX); 1025 } else if (hdrs & ICE_FLOW_SEG_HDR_VXLAN) { 1026 src = (const ice_bitmap_t *)ice_ptypes_vxlan_vni; 1027 ice_and_bitmap(params->ptypes, params->ptypes, 1028 src, ICE_FLOW_PTYPE_MAX); 1029 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0) { 1030 src = (const ice_bitmap_t *)ice_ptypes_udp_ecpri_tp0; 1031 ice_and_bitmap(params->ptypes, params->ptypes, 1032 src, ICE_FLOW_PTYPE_MAX); 1033 } 1034 1035 if (hdrs & ICE_FLOW_SEG_HDR_PFCP) { 1036 if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE) 1037 src = 1038 (const ice_bitmap_t *)ice_ptypes_pfcp_node; 1039 else 1040 src = 1041 (const ice_bitmap_t *)ice_ptypes_pfcp_session; 1042 1043 ice_and_bitmap(params->ptypes, params->ptypes, 1044 src, ICE_FLOW_PTYPE_MAX); 1045 } else { 1046 src = (const ice_bitmap_t *)ice_ptypes_pfcp_node; 1047 ice_andnot_bitmap(params->ptypes, params->ptypes, 1048 src, ICE_FLOW_PTYPE_MAX); 1049 1050 src = (const ice_bitmap_t *)ice_ptypes_pfcp_session; 1051 ice_andnot_bitmap(params->ptypes, params->ptypes, 1052 src, ICE_FLOW_PTYPE_MAX); 1053 } 1054 } 1055 1056 return ICE_SUCCESS; 1057 } 1058 1059 /** 1060 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags 1061 * @hw: pointer to the HW struct 1062 * @params: information about the flow to be processed 1063 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata. 1064 * 1065 * This function will allocate an extraction sequence entries for a DWORD size 1066 * chunk of the packet flags. 1067 */ 1068 static enum ice_status 1069 ice_flow_xtract_pkt_flags(struct ice_hw *hw, 1070 struct ice_flow_prof_params *params, 1071 enum ice_flex_mdid_pkt_flags flags) 1072 { 1073 u8 fv_words = hw->blk[params->blk].es.fvw; 1074 u8 idx; 1075 1076 /* Make sure the number of extraction sequence entries required does not 1077 * exceed the block's capacity. 1078 */ 1079 if (params->es_cnt >= fv_words) 1080 return ICE_ERR_MAX_LIMIT; 1081 1082 /* some blocks require a reversed field vector layout */ 1083 if (hw->blk[params->blk].es.reverse) 1084 idx = fv_words - params->es_cnt - 1; 1085 else 1086 idx = params->es_cnt; 1087 1088 params->es[idx].prot_id = ICE_PROT_META_ID; 1089 params->es[idx].off = flags; 1090 params->es_cnt++; 1091 1092 return ICE_SUCCESS; 1093 } 1094 1095 /** 1096 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 1097 * @hw: pointer to the HW struct 1098 * @params: information about the flow to be processed 1099 * @seg: packet segment index of the field to be extracted 1100 * @fld: ID of field to be extracted 1101 * @match: bitfield of all fields 1102 * 1103 * This function determines the protocol ID, offset, and size of the given 1104 * field. It then allocates one or more extraction sequence entries for the 1105 * given field, and fill the entries with protocol ID and offset information. 1106 */ 1107 static enum ice_status 1108 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 1109 u8 seg, enum ice_flow_field fld, u64 match) 1110 { 1111 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 1112 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 1113 u8 fv_words = hw->blk[params->blk].es.fvw; 1114 struct ice_flow_fld_info *flds; 1115 u16 cnt, ese_bits, i; 1116 u16 sib_mask = 0; 1117 u16 mask; 1118 u16 off; 1119 1120 flds = params->prof->segs[seg].fields; 1121 1122 switch (fld) { 1123 case ICE_FLOW_FIELD_IDX_ETH_DA: 1124 case ICE_FLOW_FIELD_IDX_ETH_SA: 1125 case ICE_FLOW_FIELD_IDX_S_VLAN: 1126 case ICE_FLOW_FIELD_IDX_C_VLAN: 1127 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 1128 break; 1129 case ICE_FLOW_FIELD_IDX_ETH_TYPE: 1130 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 1131 break; 1132 case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 1133 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 1134 break; 1135 case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 1136 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 1137 break; 1138 case ICE_FLOW_FIELD_IDX_IPV4_TTL: 1139 case ICE_FLOW_FIELD_IDX_IPV4_PROT: 1140 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 1141 1142 /* TTL and PROT share the same extraction seq. entry. 1143 * Each is considered a sibling to the other in terms of sharing 1144 * the same extraction sequence entry. 1145 */ 1146 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 1147 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 1148 else 1149 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 1150 1151 /* If the sibling field is also included, that field's 1152 * mask needs to be included. 1153 */ 1154 if (match & BIT(sib)) 1155 sib_mask = ice_flds_info[sib].mask; 1156 break; 1157 case ICE_FLOW_FIELD_IDX_IPV6_TTL: 1158 case ICE_FLOW_FIELD_IDX_IPV6_PROT: 1159 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 1160 1161 /* TTL and PROT share the same extraction seq. entry. 1162 * Each is considered a sibling to the other in terms of sharing 1163 * the same extraction sequence entry. 1164 */ 1165 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 1166 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 1167 else 1168 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 1169 1170 /* If the sibling field is also included, that field's 1171 * mask needs to be included. 1172 */ 1173 if (match & BIT(sib)) 1174 sib_mask = ice_flds_info[sib].mask; 1175 break; 1176 case ICE_FLOW_FIELD_IDX_IPV4_SA: 1177 case ICE_FLOW_FIELD_IDX_IPV4_DA: 1178 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 1179 break; 1180 case ICE_FLOW_FIELD_IDX_IPV6_SA: 1181 case ICE_FLOW_FIELD_IDX_IPV6_DA: 1182 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA: 1183 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA: 1184 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA: 1185 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA: 1186 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA: 1187 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA: 1188 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 1189 break; 1190 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 1191 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 1192 case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 1193 prot_id = ICE_PROT_TCP_IL; 1194 break; 1195 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 1196 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 1197 prot_id = ICE_PROT_UDP_IL_OR_S; 1198 break; 1199 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 1200 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 1201 prot_id = ICE_PROT_SCTP_IL; 1202 break; 1203 case ICE_FLOW_FIELD_IDX_VXLAN_VNI: 1204 case ICE_FLOW_FIELD_IDX_GTPC_TEID: 1205 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID: 1206 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID: 1207 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID: 1208 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID: 1209 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI: 1210 /* GTP is accessed through UDP OF protocol */ 1211 prot_id = ICE_PROT_UDP_OF; 1212 break; 1213 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID: 1214 prot_id = ICE_PROT_PPPOE; 1215 break; 1216 case ICE_FLOW_FIELD_IDX_PFCP_SEID: 1217 prot_id = ICE_PROT_UDP_IL_OR_S; 1218 break; 1219 case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID: 1220 prot_id = ICE_PROT_L2TPV3; 1221 break; 1222 case ICE_FLOW_FIELD_IDX_ESP_SPI: 1223 prot_id = ICE_PROT_ESP_F; 1224 break; 1225 case ICE_FLOW_FIELD_IDX_AH_SPI: 1226 prot_id = ICE_PROT_ESP_2; 1227 break; 1228 case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI: 1229 prot_id = ICE_PROT_UDP_IL_OR_S; 1230 break; 1231 case ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID: 1232 prot_id = ICE_PROT_ECPRI; 1233 break; 1234 case ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID: 1235 prot_id = ICE_PROT_UDP_IL_OR_S; 1236 break; 1237 case ICE_FLOW_FIELD_IDX_ARP_SIP: 1238 case ICE_FLOW_FIELD_IDX_ARP_DIP: 1239 case ICE_FLOW_FIELD_IDX_ARP_SHA: 1240 case ICE_FLOW_FIELD_IDX_ARP_DHA: 1241 case ICE_FLOW_FIELD_IDX_ARP_OP: 1242 prot_id = ICE_PROT_ARP_OF; 1243 break; 1244 case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 1245 case ICE_FLOW_FIELD_IDX_ICMP_CODE: 1246 /* ICMP type and code share the same extraction seq. entry */ 1247 prot_id = (params->prof->segs[seg].hdrs & 1248 ICE_FLOW_SEG_HDR_IPV4) ? 1249 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 1250 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 1251 ICE_FLOW_FIELD_IDX_ICMP_CODE : 1252 ICE_FLOW_FIELD_IDX_ICMP_TYPE; 1253 break; 1254 case ICE_FLOW_FIELD_IDX_GRE_KEYID: 1255 prot_id = ICE_PROT_GRE_OF; 1256 break; 1257 default: 1258 return ICE_ERR_NOT_IMPL; 1259 } 1260 1261 /* Each extraction sequence entry is a word in size, and extracts a 1262 * word-aligned offset from a protocol header. 1263 */ 1264 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 1265 1266 flds[fld].xtrct.prot_id = prot_id; 1267 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 1268 ICE_FLOW_FV_EXTRACT_SZ; 1269 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 1270 flds[fld].xtrct.idx = params->es_cnt; 1271 flds[fld].xtrct.mask = ice_flds_info[fld].mask; 1272 1273 /* Adjust the next field-entry index after accommodating the number of 1274 * entries this field consumes 1275 */ 1276 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp + 1277 ice_flds_info[fld].size, ese_bits); 1278 1279 /* Fill in the extraction sequence entries needed for this field */ 1280 off = flds[fld].xtrct.off; 1281 mask = flds[fld].xtrct.mask; 1282 for (i = 0; i < cnt; i++) { 1283 /* Only consume an extraction sequence entry if there is no 1284 * sibling field associated with this field or the sibling entry 1285 * already extracts the word shared with this field. 1286 */ 1287 if (sib == ICE_FLOW_FIELD_IDX_MAX || 1288 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 1289 flds[sib].xtrct.off != off) { 1290 u8 idx; 1291 1292 /* Make sure the number of extraction sequence required 1293 * does not exceed the block's capability 1294 */ 1295 if (params->es_cnt >= fv_words) 1296 return ICE_ERR_MAX_LIMIT; 1297 1298 /* some blocks require a reversed field vector layout */ 1299 if (hw->blk[params->blk].es.reverse) 1300 idx = fv_words - params->es_cnt - 1; 1301 else 1302 idx = params->es_cnt; 1303 1304 params->es[idx].prot_id = prot_id; 1305 params->es[idx].off = off; 1306 params->mask[idx] = mask | sib_mask; 1307 params->es_cnt++; 1308 } 1309 1310 off += ICE_FLOW_FV_EXTRACT_SZ; 1311 } 1312 1313 return ICE_SUCCESS; 1314 } 1315 1316 /** 1317 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes 1318 * @hw: pointer to the HW struct 1319 * @params: information about the flow to be processed 1320 * @seg: index of packet segment whose raw fields are to be extracted 1321 */ 1322 static enum ice_status 1323 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, 1324 u8 seg) 1325 { 1326 u16 fv_words; 1327 u16 hdrs_sz; 1328 u8 i; 1329 1330 if (!params->prof->segs[seg].raws_cnt) 1331 return ICE_SUCCESS; 1332 1333 if (params->prof->segs[seg].raws_cnt > 1334 ARRAY_SIZE(params->prof->segs[seg].raws)) 1335 return ICE_ERR_MAX_LIMIT; 1336 1337 /* Offsets within the segment headers are not supported */ 1338 hdrs_sz = ice_flow_calc_seg_sz(params, seg); 1339 if (!hdrs_sz) 1340 return ICE_ERR_PARAM; 1341 1342 fv_words = hw->blk[params->blk].es.fvw; 1343 1344 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) { 1345 struct ice_flow_seg_fld_raw *raw; 1346 u16 off, cnt, j; 1347 1348 raw = ¶ms->prof->segs[seg].raws[i]; 1349 1350 /* Storing extraction information */ 1351 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S; 1352 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) * 1353 ICE_FLOW_FV_EXTRACT_SZ; 1354 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) * 1355 BITS_PER_BYTE; 1356 raw->info.xtrct.idx = params->es_cnt; 1357 1358 /* Determine the number of field vector entries this raw field 1359 * consumes. 1360 */ 1361 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp + 1362 (raw->info.src.last * BITS_PER_BYTE), 1363 (ICE_FLOW_FV_EXTRACT_SZ * 1364 BITS_PER_BYTE)); 1365 off = raw->info.xtrct.off; 1366 for (j = 0; j < cnt; j++) { 1367 u16 idx; 1368 1369 /* Make sure the number of extraction sequence required 1370 * does not exceed the block's capability 1371 */ 1372 if (params->es_cnt >= hw->blk[params->blk].es.count || 1373 params->es_cnt >= ICE_MAX_FV_WORDS) 1374 return ICE_ERR_MAX_LIMIT; 1375 1376 /* some blocks require a reversed field vector layout */ 1377 if (hw->blk[params->blk].es.reverse) 1378 idx = fv_words - params->es_cnt - 1; 1379 else 1380 idx = params->es_cnt; 1381 1382 params->es[idx].prot_id = raw->info.xtrct.prot_id; 1383 params->es[idx].off = off; 1384 params->es_cnt++; 1385 off += ICE_FLOW_FV_EXTRACT_SZ; 1386 } 1387 } 1388 1389 return ICE_SUCCESS; 1390 } 1391 1392 /** 1393 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 1394 * @hw: pointer to the HW struct 1395 * @params: information about the flow to be processed 1396 * 1397 * This function iterates through all matched fields in the given segments, and 1398 * creates an extraction sequence for the fields. 1399 */ 1400 static enum ice_status 1401 ice_flow_create_xtrct_seq(struct ice_hw *hw, 1402 struct ice_flow_prof_params *params) 1403 { 1404 enum ice_status status = ICE_SUCCESS; 1405 u8 i; 1406 1407 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from 1408 * packet flags 1409 */ 1410 if (params->blk == ICE_BLK_ACL) { 1411 status = ice_flow_xtract_pkt_flags(hw, params, 1412 ICE_RX_MDID_PKT_FLAGS_15_0); 1413 if (status) 1414 return status; 1415 } 1416 1417 for (i = 0; i < params->prof->segs_cnt; i++) { 1418 u64 match = params->prof->segs[i].match; 1419 enum ice_flow_field j; 1420 1421 ice_for_each_set_bit(j, (ice_bitmap_t *)&match, 1422 ICE_FLOW_FIELD_IDX_MAX) { 1423 status = ice_flow_xtract_fld(hw, params, i, j, match); 1424 if (status) 1425 return status; 1426 ice_clear_bit(j, (ice_bitmap_t *)&match); 1427 } 1428 1429 /* Process raw matching bytes */ 1430 status = ice_flow_xtract_raws(hw, params, i); 1431 if (status) 1432 return status; 1433 } 1434 1435 return status; 1436 } 1437 1438 /** 1439 * ice_flow_sel_acl_scen - returns the specific scenario 1440 * @hw: pointer to the hardware structure 1441 * @params: information about the flow to be processed 1442 * 1443 * This function will return the specific scenario based on the 1444 * params passed to it 1445 */ 1446 static enum ice_status 1447 ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params) 1448 { 1449 /* Find the best-fit scenario for the provided match width */ 1450 struct ice_acl_scen *cand_scen = NULL, *scen; 1451 1452 if (!hw->acl_tbl) 1453 return ICE_ERR_DOES_NOT_EXIST; 1454 1455 /* Loop through each scenario and match against the scenario width 1456 * to select the specific scenario 1457 */ 1458 LIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry) 1459 if (scen->eff_width >= params->entry_length && 1460 (!cand_scen || cand_scen->eff_width > scen->eff_width)) 1461 cand_scen = scen; 1462 if (!cand_scen) 1463 return ICE_ERR_DOES_NOT_EXIST; 1464 1465 params->prof->cfg.scen = cand_scen; 1466 1467 return ICE_SUCCESS; 1468 } 1469 1470 /** 1471 * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries 1472 * @params: information about the flow to be processed 1473 */ 1474 static enum ice_status 1475 ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params) 1476 { 1477 u16 index, i, range_idx = 0; 1478 1479 index = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 1480 1481 for (i = 0; i < params->prof->segs_cnt; i++) { 1482 struct ice_flow_seg_info *seg = ¶ms->prof->segs[i]; 1483 u8 j; 1484 1485 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match, 1486 ICE_FLOW_FIELD_IDX_MAX) { 1487 struct ice_flow_fld_info *fld = &seg->fields[j]; 1488 1489 fld->entry.mask = ICE_FLOW_FLD_OFF_INVAL; 1490 1491 if (fld->type == ICE_FLOW_FLD_TYPE_RANGE) { 1492 fld->entry.last = ICE_FLOW_FLD_OFF_INVAL; 1493 1494 /* Range checking only supported for single 1495 * words 1496 */ 1497 if (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size + 1498 fld->xtrct.disp, 1499 BITS_PER_BYTE * 2) > 1) 1500 return ICE_ERR_PARAM; 1501 1502 /* Ranges must define low and high values */ 1503 if (fld->src.val == ICE_FLOW_FLD_OFF_INVAL || 1504 fld->src.last == ICE_FLOW_FLD_OFF_INVAL) 1505 return ICE_ERR_PARAM; 1506 1507 fld->entry.val = range_idx++; 1508 } else { 1509 /* Store adjusted byte-length of field for later 1510 * use, taking into account potential 1511 * non-byte-aligned displacement 1512 */ 1513 fld->entry.last = DIVIDE_AND_ROUND_UP 1514 (ice_flds_info[j].size + 1515 (fld->xtrct.disp % BITS_PER_BYTE), 1516 BITS_PER_BYTE); 1517 fld->entry.val = index; 1518 index += fld->entry.last; 1519 } 1520 } 1521 1522 for (j = 0; j < seg->raws_cnt; j++) { 1523 struct ice_flow_seg_fld_raw *raw = &seg->raws[j]; 1524 1525 raw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL; 1526 raw->info.entry.val = index; 1527 raw->info.entry.last = raw->info.src.last; 1528 index += raw->info.entry.last; 1529 } 1530 } 1531 1532 /* Currently only support using the byte selection base, which only 1533 * allows for an effective entry size of 30 bytes. Reject anything 1534 * larger. 1535 */ 1536 if (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS) 1537 return ICE_ERR_PARAM; 1538 1539 /* Only 8 range checkers per profile, reject anything trying to use 1540 * more 1541 */ 1542 if (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG) 1543 return ICE_ERR_PARAM; 1544 1545 /* Store # bytes required for entry for later use */ 1546 params->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 1547 1548 return ICE_SUCCESS; 1549 } 1550 1551 /** 1552 * ice_flow_proc_segs - process all packet segments associated with a profile 1553 * @hw: pointer to the HW struct 1554 * @params: information about the flow to be processed 1555 */ 1556 static enum ice_status 1557 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 1558 { 1559 enum ice_status status; 1560 1561 status = ice_flow_proc_seg_hdrs(params); 1562 if (status) 1563 return status; 1564 1565 status = ice_flow_create_xtrct_seq(hw, params); 1566 if (status) 1567 return status; 1568 1569 switch (params->blk) { 1570 case ICE_BLK_FD: 1571 case ICE_BLK_RSS: 1572 status = ICE_SUCCESS; 1573 break; 1574 case ICE_BLK_ACL: 1575 status = ice_flow_acl_def_entry_frmt(params); 1576 if (status) 1577 return status; 1578 status = ice_flow_sel_acl_scen(hw, params); 1579 if (status) 1580 return status; 1581 break; 1582 default: 1583 return ICE_ERR_NOT_IMPL; 1584 } 1585 1586 return status; 1587 } 1588 1589 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 1590 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 1591 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 1592 1593 /** 1594 * ice_flow_find_prof_conds - Find a profile matching headers and conditions 1595 * @hw: pointer to the HW struct 1596 * @blk: classification stage 1597 * @dir: flow direction 1598 * @segs: array of one or more packet segments that describe the flow 1599 * @segs_cnt: number of packet segments provided 1600 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 1601 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 1602 */ 1603 static struct ice_flow_prof * 1604 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 1605 enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 1606 u8 segs_cnt, u16 vsi_handle, u32 conds) 1607 { 1608 struct ice_flow_prof *p, *prof = NULL; 1609 1610 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1611 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 1612 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 1613 segs_cnt && segs_cnt == p->segs_cnt) { 1614 u8 i; 1615 1616 /* Check for profile-VSI association if specified */ 1617 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 1618 ice_is_vsi_valid(hw, vsi_handle) && 1619 !ice_is_bit_set(p->vsis, vsi_handle)) 1620 continue; 1621 1622 /* Protocol headers must be checked. Matched fields are 1623 * checked if specified. 1624 */ 1625 for (i = 0; i < segs_cnt; i++) 1626 if (segs[i].hdrs != p->segs[i].hdrs || 1627 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 1628 segs[i].match != p->segs[i].match)) 1629 break; 1630 1631 /* A match is found if all segments are matched */ 1632 if (i == segs_cnt) { 1633 prof = p; 1634 break; 1635 } 1636 } 1637 ice_release_lock(&hw->fl_profs_locks[blk]); 1638 1639 return prof; 1640 } 1641 1642 /** 1643 * ice_flow_find_prof - Look up a profile matching headers and matched fields 1644 * @hw: pointer to the HW struct 1645 * @blk: classification stage 1646 * @dir: flow direction 1647 * @segs: array of one or more packet segments that describe the flow 1648 * @segs_cnt: number of packet segments provided 1649 */ 1650 u64 1651 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 1652 struct ice_flow_seg_info *segs, u8 segs_cnt) 1653 { 1654 struct ice_flow_prof *p; 1655 1656 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, 1657 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); 1658 1659 return p ? p->id : ICE_FLOW_PROF_ID_INVAL; 1660 } 1661 1662 /** 1663 * ice_flow_find_prof_id - Look up a profile with given profile ID 1664 * @hw: pointer to the HW struct 1665 * @blk: classification stage 1666 * @prof_id: unique ID to identify this flow profile 1667 */ 1668 static struct ice_flow_prof * 1669 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 1670 { 1671 struct ice_flow_prof *p; 1672 1673 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 1674 if (p->id == prof_id) 1675 return p; 1676 1677 return NULL; 1678 } 1679 1680 /** 1681 * ice_dealloc_flow_entry - Deallocate flow entry memory 1682 * @hw: pointer to the HW struct 1683 * @entry: flow entry to be removed 1684 */ 1685 static void 1686 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry) 1687 { 1688 if (!entry) 1689 return; 1690 1691 if (entry->entry) 1692 ice_free(hw, entry->entry); 1693 1694 if (entry->range_buf) { 1695 ice_free(hw, entry->range_buf); 1696 entry->range_buf = NULL; 1697 } 1698 1699 if (entry->acts) { 1700 ice_free(hw, entry->acts); 1701 entry->acts = NULL; 1702 entry->acts_cnt = 0; 1703 } 1704 1705 ice_free(hw, entry); 1706 } 1707 1708 /** 1709 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle 1710 * @hw: pointer to the HW struct 1711 * @blk: classification stage 1712 * @prof_id: the profile ID handle 1713 * @hw_prof_id: pointer to variable to receive the HW profile ID 1714 */ 1715 enum ice_status 1716 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 1717 u8 *hw_prof_id) 1718 { 1719 enum ice_status status = ICE_ERR_DOES_NOT_EXIST; 1720 struct ice_prof_map *map; 1721 1722 ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 1723 map = ice_search_prof_id(hw, blk, prof_id); 1724 if (map) { 1725 *hw_prof_id = map->prof_id; 1726 status = ICE_SUCCESS; 1727 } 1728 ice_release_lock(&hw->blk[blk].es.prof_map_lock); 1729 return status; 1730 } 1731 1732 #define ICE_ACL_INVALID_SCEN 0x3f 1733 1734 /** 1735 * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any PF 1736 * @hw: pointer to the hardware structure 1737 * @prof: pointer to flow profile 1738 * @buf: destination buffer function writes partial extraction sequence to 1739 * 1740 * returns ICE_SUCCESS if no PF is associated to the given profile 1741 * returns ICE_ERR_IN_USE if at least one PF is associated to the given profile 1742 * returns other error code for real error 1743 */ 1744 static enum ice_status 1745 ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof, 1746 struct ice_aqc_acl_prof_generic_frmt *buf) 1747 { 1748 enum ice_status status; 1749 u8 prof_id = 0; 1750 1751 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 1752 if (status) 1753 return status; 1754 1755 status = ice_query_acl_prof(hw, prof_id, buf, NULL); 1756 if (status) 1757 return status; 1758 1759 /* If all PF's associated scenarios are all 0 or all 1760 * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has 1761 * not been configured yet. 1762 */ 1763 if (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 && 1764 buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 && 1765 buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 && 1766 buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0) 1767 return ICE_SUCCESS; 1768 1769 if (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN && 1770 buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN && 1771 buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN && 1772 buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN && 1773 buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN && 1774 buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN && 1775 buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN && 1776 buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN) 1777 return ICE_SUCCESS; 1778 1779 return ICE_ERR_IN_USE; 1780 } 1781 1782 /** 1783 * ice_flow_acl_free_act_cntr - Free the ACL rule's actions 1784 * @hw: pointer to the hardware structure 1785 * @acts: array of actions to be performed on a match 1786 * @acts_cnt: number of actions 1787 */ 1788 static enum ice_status 1789 ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts, 1790 u8 acts_cnt) 1791 { 1792 int i; 1793 1794 for (i = 0; i < acts_cnt; i++) { 1795 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT || 1796 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES || 1797 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) { 1798 struct ice_acl_cntrs cntrs; 1799 enum ice_status status; 1800 1801 cntrs.bank = 0; /* Only bank0 for the moment */ 1802 cntrs.first_cntr = 1803 LE16_TO_CPU(acts[i].data.acl_act.value); 1804 cntrs.last_cntr = 1805 LE16_TO_CPU(acts[i].data.acl_act.value); 1806 1807 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) 1808 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL; 1809 else 1810 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE; 1811 1812 status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL); 1813 if (status) 1814 return status; 1815 } 1816 } 1817 return ICE_SUCCESS; 1818 } 1819 1820 /** 1821 * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile 1822 * @hw: pointer to the hardware structure 1823 * @prof: pointer to flow profile 1824 * 1825 * Disassociate the scenario from the profile for the PF of the VSI. 1826 */ 1827 static enum ice_status 1828 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof) 1829 { 1830 struct ice_aqc_acl_prof_generic_frmt buf; 1831 enum ice_status status = ICE_SUCCESS; 1832 u8 prof_id = 0; 1833 1834 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 1835 1836 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 1837 if (status) 1838 return status; 1839 1840 status = ice_query_acl_prof(hw, prof_id, &buf, NULL); 1841 if (status) 1842 return status; 1843 1844 /* Clear scenario for this PF */ 1845 buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN; 1846 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL); 1847 1848 return status; 1849 } 1850 1851 /** 1852 * ice_flow_rem_entry_sync - Remove a flow entry 1853 * @hw: pointer to the HW struct 1854 * @blk: classification stage 1855 * @entry: flow entry to be removed 1856 */ 1857 static enum ice_status 1858 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk, 1859 struct ice_flow_entry *entry) 1860 { 1861 if (!entry) 1862 return ICE_ERR_BAD_PTR; 1863 1864 if (blk == ICE_BLK_ACL) { 1865 enum ice_status status; 1866 1867 if (!entry->prof) 1868 return ICE_ERR_BAD_PTR; 1869 1870 status = ice_acl_rem_entry(hw, entry->prof->cfg.scen, 1871 entry->scen_entry_idx); 1872 if (status) 1873 return status; 1874 1875 /* Checks if we need to release an ACL counter. */ 1876 if (entry->acts_cnt && entry->acts) 1877 ice_flow_acl_free_act_cntr(hw, entry->acts, 1878 entry->acts_cnt); 1879 } 1880 1881 LIST_DEL(&entry->l_entry); 1882 1883 ice_dealloc_flow_entry(hw, entry); 1884 1885 return ICE_SUCCESS; 1886 } 1887 1888 /** 1889 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 1890 * @hw: pointer to the HW struct 1891 * @blk: classification stage 1892 * @dir: flow direction 1893 * @prof_id: unique ID to identify this flow profile 1894 * @segs: array of one or more packet segments that describe the flow 1895 * @segs_cnt: number of packet segments provided 1896 * @acts: array of default actions 1897 * @acts_cnt: number of default actions 1898 * @prof: stores the returned flow profile added 1899 * 1900 * Assumption: the caller has acquired the lock to the profile list 1901 */ 1902 static enum ice_status 1903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 1904 enum ice_flow_dir dir, u64 prof_id, 1905 struct ice_flow_seg_info *segs, u8 segs_cnt, 1906 struct ice_flow_action *acts, u8 acts_cnt, 1907 struct ice_flow_prof **prof) 1908 { 1909 struct ice_flow_prof_params *params; 1910 enum ice_status status; 1911 u8 i; 1912 1913 if (!prof || (acts_cnt && !acts)) 1914 return ICE_ERR_BAD_PTR; 1915 1916 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params)); 1917 if (!params) 1918 return ICE_ERR_NO_MEMORY; 1919 1920 params->prof = (struct ice_flow_prof *) 1921 ice_malloc(hw, sizeof(*params->prof)); 1922 if (!params->prof) { 1923 status = ICE_ERR_NO_MEMORY; 1924 goto free_params; 1925 } 1926 1927 /* initialize extraction sequence to all invalid (0xff) */ 1928 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 1929 params->es[i].prot_id = ICE_PROT_INVALID; 1930 params->es[i].off = ICE_FV_OFFSET_INVAL; 1931 } 1932 1933 params->blk = blk; 1934 params->prof->id = prof_id; 1935 params->prof->dir = dir; 1936 params->prof->segs_cnt = segs_cnt; 1937 1938 /* Make a copy of the segments that need to be persistent in the flow 1939 * profile instance 1940 */ 1941 for (i = 0; i < segs_cnt; i++) 1942 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs), 1943 ICE_NONDMA_TO_NONDMA); 1944 1945 /* Make a copy of the actions that need to be persistent in the flow 1946 * profile instance. 1947 */ 1948 if (acts_cnt) { 1949 params->prof->acts = (struct ice_flow_action *) 1950 ice_memdup(hw, acts, acts_cnt * sizeof(*acts), 1951 ICE_NONDMA_TO_NONDMA); 1952 1953 if (!params->prof->acts) { 1954 status = ICE_ERR_NO_MEMORY; 1955 goto out; 1956 } 1957 } 1958 1959 status = ice_flow_proc_segs(hw, params); 1960 if (status) { 1961 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 1962 goto out; 1963 } 1964 1965 /* Add a HW profile for this flow profile */ 1966 status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes, 1967 params->attr, params->attr_cnt, params->es, 1968 params->mask); 1969 if (status) { 1970 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 1971 goto out; 1972 } 1973 1974 INIT_LIST_HEAD(¶ms->prof->entries); 1975 ice_init_lock(¶ms->prof->entries_lock); 1976 *prof = params->prof; 1977 1978 out: 1979 if (status) { 1980 if (params->prof->acts) 1981 ice_free(hw, params->prof->acts); 1982 ice_free(hw, params->prof); 1983 } 1984 free_params: 1985 ice_free(hw, params); 1986 1987 return status; 1988 } 1989 1990 /** 1991 * ice_flow_rem_prof_sync - remove a flow profile 1992 * @hw: pointer to the hardware structure 1993 * @blk: classification stage 1994 * @prof: pointer to flow profile to remove 1995 * 1996 * Assumption: the caller has acquired the lock to the profile list 1997 */ 1998 static enum ice_status 1999 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 2000 struct ice_flow_prof *prof) 2001 { 2002 enum ice_status status; 2003 2004 /* Remove all remaining flow entries before removing the flow profile */ 2005 if (!LIST_EMPTY(&prof->entries)) { 2006 struct ice_flow_entry *e, *t; 2007 2008 ice_acquire_lock(&prof->entries_lock); 2009 2010 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry, 2011 l_entry) { 2012 status = ice_flow_rem_entry_sync(hw, blk, e); 2013 if (status) 2014 break; 2015 } 2016 2017 ice_release_lock(&prof->entries_lock); 2018 } 2019 2020 if (blk == ICE_BLK_ACL) { 2021 struct ice_aqc_acl_profile_ranges query_rng_buf; 2022 struct ice_aqc_acl_prof_generic_frmt buf; 2023 u8 prof_id = 0; 2024 2025 /* Disassociate the scenario from the profile for the PF */ 2026 status = ice_flow_acl_disassoc_scen(hw, prof); 2027 if (status) 2028 return status; 2029 2030 /* Clear the range-checker if the profile ID is no longer 2031 * used by any PF 2032 */ 2033 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf); 2034 if (status && status != ICE_ERR_IN_USE) { 2035 return status; 2036 } else if (!status) { 2037 /* Clear the range-checker value for profile ID */ 2038 ice_memset(&query_rng_buf, 0, 2039 sizeof(struct ice_aqc_acl_profile_ranges), 2040 ICE_NONDMA_MEM); 2041 2042 status = ice_flow_get_hw_prof(hw, blk, prof->id, 2043 &prof_id); 2044 if (status) 2045 return status; 2046 2047 status = ice_prog_acl_prof_ranges(hw, prof_id, 2048 &query_rng_buf, NULL); 2049 if (status) 2050 return status; 2051 } 2052 } 2053 2054 /* Remove all hardware profiles associated with this flow profile */ 2055 status = ice_rem_prof(hw, blk, prof->id); 2056 if (!status) { 2057 LIST_DEL(&prof->l_entry); 2058 ice_destroy_lock(&prof->entries_lock); 2059 if (prof->acts) 2060 ice_free(hw, prof->acts); 2061 ice_free(hw, prof); 2062 } 2063 2064 return status; 2065 } 2066 2067 /** 2068 * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field 2069 * @buf: Destination buffer function writes partial xtrct sequence to 2070 * @info: Info about field 2071 */ 2072 static void 2073 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf, 2074 struct ice_flow_fld_info *info) 2075 { 2076 u16 dst, i; 2077 u8 src; 2078 2079 src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ + 2080 info->xtrct.disp / BITS_PER_BYTE; 2081 dst = info->entry.val; 2082 for (i = 0; i < info->entry.last; i++) 2083 /* HW stores field vector words in LE, convert words back to BE 2084 * so constructed entries will end up in network order 2085 */ 2086 buf->byte_selection[dst++] = src++ ^ 1; 2087 } 2088 2089 /** 2090 * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence 2091 * @hw: pointer to the hardware structure 2092 * @prof: pointer to flow profile 2093 */ 2094 static enum ice_status 2095 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof) 2096 { 2097 struct ice_aqc_acl_prof_generic_frmt buf; 2098 struct ice_flow_fld_info *info; 2099 enum ice_status status; 2100 u8 prof_id = 0; 2101 u16 i; 2102 2103 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 2104 2105 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 2106 if (status) 2107 return status; 2108 2109 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf); 2110 if (status && status != ICE_ERR_IN_USE) 2111 return status; 2112 2113 if (!status) { 2114 /* Program the profile dependent configuration. This is done 2115 * only once regardless of the number of PFs using that profile 2116 */ 2117 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 2118 2119 for (i = 0; i < prof->segs_cnt; i++) { 2120 struct ice_flow_seg_info *seg = &prof->segs[i]; 2121 u16 j; 2122 2123 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match, 2124 ICE_FLOW_FIELD_IDX_MAX) { 2125 info = &seg->fields[j]; 2126 2127 if (info->type == ICE_FLOW_FLD_TYPE_RANGE) 2128 buf.word_selection[info->entry.val] = 2129 info->xtrct.idx; 2130 else 2131 ice_flow_acl_set_xtrct_seq_fld(&buf, 2132 info); 2133 } 2134 2135 for (j = 0; j < seg->raws_cnt; j++) { 2136 info = &seg->raws[j].info; 2137 ice_flow_acl_set_xtrct_seq_fld(&buf, info); 2138 } 2139 } 2140 2141 ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN, 2142 ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS, 2143 ICE_NONDMA_MEM); 2144 } 2145 2146 /* Update the current PF */ 2147 buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id; 2148 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL); 2149 2150 return status; 2151 } 2152 2153 /** 2154 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG 2155 * @hw: pointer to the hardware structure 2156 * @blk: classification stage 2157 * @vsi_handle: software VSI handle 2158 * @vsig: target VSI group 2159 * 2160 * Assumption: the caller has already verified that the VSI to 2161 * be added has the same characteristics as the VSIG and will 2162 * thereby have access to all resources added to that VSIG. 2163 */ 2164 enum ice_status 2165 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, 2166 u16 vsig) 2167 { 2168 enum ice_status status; 2169 2170 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) 2171 return ICE_ERR_PARAM; 2172 2173 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2174 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), 2175 vsig); 2176 ice_release_lock(&hw->fl_profs_locks[blk]); 2177 2178 return status; 2179 } 2180 2181 /** 2182 * ice_flow_assoc_prof - associate a VSI with a flow profile 2183 * @hw: pointer to the hardware structure 2184 * @blk: classification stage 2185 * @prof: pointer to flow profile 2186 * @vsi_handle: software VSI handle 2187 * 2188 * Assumption: the caller has acquired the lock to the profile list 2189 * and the software VSI handle has been validated 2190 */ 2191 enum ice_status 2192 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 2193 struct ice_flow_prof *prof, u16 vsi_handle) 2194 { 2195 enum ice_status status = ICE_SUCCESS; 2196 2197 if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 2198 if (blk == ICE_BLK_ACL) { 2199 status = ice_flow_acl_set_xtrct_seq(hw, prof); 2200 if (status) 2201 return status; 2202 } 2203 status = ice_add_prof_id_flow(hw, blk, 2204 ice_get_hw_vsi_num(hw, 2205 vsi_handle), 2206 prof->id); 2207 if (!status) 2208 ice_set_bit(vsi_handle, prof->vsis); 2209 else 2210 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 2211 status); 2212 } 2213 2214 return status; 2215 } 2216 2217 /** 2218 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 2219 * @hw: pointer to the hardware structure 2220 * @blk: classification stage 2221 * @prof: pointer to flow profile 2222 * @vsi_handle: software VSI handle 2223 * 2224 * Assumption: the caller has acquired the lock to the profile list 2225 * and the software VSI handle has been validated 2226 */ 2227 static enum ice_status 2228 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 2229 struct ice_flow_prof *prof, u16 vsi_handle) 2230 { 2231 enum ice_status status = ICE_SUCCESS; 2232 2233 if (ice_is_bit_set(prof->vsis, vsi_handle)) { 2234 status = ice_rem_prof_id_flow(hw, blk, 2235 ice_get_hw_vsi_num(hw, 2236 vsi_handle), 2237 prof->id); 2238 if (!status) 2239 ice_clear_bit(vsi_handle, prof->vsis); 2240 else 2241 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 2242 status); 2243 } 2244 2245 return status; 2246 } 2247 2248 /** 2249 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 2250 * @hw: pointer to the HW struct 2251 * @blk: classification stage 2252 * @dir: flow direction 2253 * @prof_id: unique ID to identify this flow profile 2254 * @segs: array of one or more packet segments that describe the flow 2255 * @segs_cnt: number of packet segments provided 2256 * @acts: array of default actions 2257 * @acts_cnt: number of default actions 2258 * @prof: stores the returned flow profile added 2259 */ 2260 enum ice_status 2261 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 2262 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 2263 struct ice_flow_action *acts, u8 acts_cnt, 2264 struct ice_flow_prof **prof) 2265 { 2266 enum ice_status status; 2267 2268 if (segs_cnt > ICE_FLOW_SEG_MAX) 2269 return ICE_ERR_MAX_LIMIT; 2270 2271 if (!segs_cnt) 2272 return ICE_ERR_PARAM; 2273 2274 if (!segs) 2275 return ICE_ERR_BAD_PTR; 2276 2277 status = ice_flow_val_hdrs(segs, segs_cnt); 2278 if (status) 2279 return status; 2280 2281 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2282 2283 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 2284 acts, acts_cnt, prof); 2285 if (!status) 2286 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 2287 2288 ice_release_lock(&hw->fl_profs_locks[blk]); 2289 2290 return status; 2291 } 2292 2293 /** 2294 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 2295 * @hw: pointer to the HW struct 2296 * @blk: the block for which the flow profile is to be removed 2297 * @prof_id: unique ID of the flow profile to be removed 2298 */ 2299 enum ice_status 2300 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 2301 { 2302 struct ice_flow_prof *prof; 2303 enum ice_status status; 2304 2305 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2306 2307 prof = ice_flow_find_prof_id(hw, blk, prof_id); 2308 if (!prof) { 2309 status = ICE_ERR_DOES_NOT_EXIST; 2310 goto out; 2311 } 2312 2313 /* prof becomes invalid after the call */ 2314 status = ice_flow_rem_prof_sync(hw, blk, prof); 2315 2316 out: 2317 ice_release_lock(&hw->fl_profs_locks[blk]); 2318 2319 return status; 2320 } 2321 2322 /** 2323 * ice_flow_find_entry - look for a flow entry using its unique ID 2324 * @hw: pointer to the HW struct 2325 * @blk: classification stage 2326 * @entry_id: unique ID to identify this flow entry 2327 * 2328 * This function looks for the flow entry with the specified unique ID in all 2329 * flow profiles of the specified classification stage. If the entry is found, 2330 * and it returns the handle to the flow entry. Otherwise, it returns 2331 * ICE_FLOW_ENTRY_ID_INVAL. 2332 */ 2333 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id) 2334 { 2335 struct ice_flow_entry *found = NULL; 2336 struct ice_flow_prof *p; 2337 2338 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2339 2340 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { 2341 struct ice_flow_entry *e; 2342 2343 ice_acquire_lock(&p->entries_lock); 2344 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry) 2345 if (e->id == entry_id) { 2346 found = e; 2347 break; 2348 } 2349 ice_release_lock(&p->entries_lock); 2350 2351 if (found) 2352 break; 2353 } 2354 2355 ice_release_lock(&hw->fl_profs_locks[blk]); 2356 2357 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL; 2358 } 2359 2360 /** 2361 * ice_flow_acl_check_actions - Checks the ACL rule's actions 2362 * @hw: pointer to the hardware structure 2363 * @acts: array of actions to be performed on a match 2364 * @acts_cnt: number of actions 2365 * @cnt_alloc: indicates if an ACL counter has been allocated. 2366 */ 2367 static enum ice_status 2368 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts, 2369 u8 acts_cnt, bool *cnt_alloc) 2370 { 2371 ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2); 2372 int i; 2373 2374 ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2); 2375 *cnt_alloc = false; 2376 2377 if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT) 2378 return ICE_ERR_OUT_OF_RANGE; 2379 2380 for (i = 0; i < acts_cnt; i++) { 2381 if (acts[i].type != ICE_FLOW_ACT_NOP && 2382 acts[i].type != ICE_FLOW_ACT_DROP && 2383 acts[i].type != ICE_FLOW_ACT_CNTR_PKT && 2384 acts[i].type != ICE_FLOW_ACT_FWD_QUEUE) 2385 return ICE_ERR_CFG; 2386 2387 /* If the caller want to add two actions of the same type, then 2388 * it is considered invalid configuration. 2389 */ 2390 if (ice_test_and_set_bit(acts[i].type, dup_check)) 2391 return ICE_ERR_PARAM; 2392 } 2393 2394 /* Checks if ACL counters are needed. */ 2395 for (i = 0; i < acts_cnt; i++) { 2396 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT || 2397 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES || 2398 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) { 2399 struct ice_acl_cntrs cntrs; 2400 enum ice_status status; 2401 2402 cntrs.amount = 1; 2403 cntrs.bank = 0; /* Only bank0 for the moment */ 2404 2405 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) 2406 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL; 2407 else 2408 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE; 2409 2410 status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL); 2411 if (status) 2412 return status; 2413 /* Counter index within the bank */ 2414 acts[i].data.acl_act.value = 2415 CPU_TO_LE16(cntrs.first_cntr); 2416 *cnt_alloc = true; 2417 } 2418 } 2419 2420 return ICE_SUCCESS; 2421 } 2422 2423 /** 2424 * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field 2425 * @fld: number of the given field 2426 * @info: info about field 2427 * @range_buf: range checker configuration buffer 2428 * @data: pointer to a data buffer containing flow entry's match values/masks 2429 * @range: Input/output param indicating which range checkers are being used 2430 */ 2431 static void 2432 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info, 2433 struct ice_aqc_acl_profile_ranges *range_buf, 2434 u8 *data, u8 *range) 2435 { 2436 u16 new_mask; 2437 2438 /* If not specified, default mask is all bits in field */ 2439 new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ? 2440 BIT(ice_flds_info[fld].size) - 1 : 2441 (*(u16 *)(data + info->src.mask))) << info->xtrct.disp; 2442 2443 /* If the mask is 0, then we don't need to worry about this input 2444 * range checker value. 2445 */ 2446 if (new_mask) { 2447 u16 new_high = 2448 (*(u16 *)(data + info->src.last)) << info->xtrct.disp; 2449 u16 new_low = 2450 (*(u16 *)(data + info->src.val)) << info->xtrct.disp; 2451 u8 range_idx = info->entry.val; 2452 2453 range_buf->checker_cfg[range_idx].low_boundary = 2454 CPU_TO_BE16(new_low); 2455 range_buf->checker_cfg[range_idx].high_boundary = 2456 CPU_TO_BE16(new_high); 2457 range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask); 2458 2459 /* Indicate which range checker is being used */ 2460 *range |= BIT(range_idx); 2461 } 2462 } 2463 2464 /** 2465 * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field 2466 * @fld: number of the given field 2467 * @info: info about the field 2468 * @buf: buffer containing the entry 2469 * @dontcare: buffer containing don't care mask for entry 2470 * @data: pointer to a data buffer containing flow entry's match values/masks 2471 */ 2472 static void 2473 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf, 2474 u8 *dontcare, u8 *data) 2475 { 2476 u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0; 2477 bool use_mask = false; 2478 u8 disp; 2479 2480 src = info->src.val; 2481 mask = info->src.mask; 2482 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2483 disp = info->xtrct.disp % BITS_PER_BYTE; 2484 2485 if (mask != ICE_FLOW_FLD_OFF_INVAL) 2486 use_mask = true; 2487 2488 for (k = 0; k < info->entry.last; k++, dst++) { 2489 /* Add overflow bits from previous byte */ 2490 buf[dst] = (tmp_s & 0xff00) >> 8; 2491 2492 /* If mask is not valid, tmp_m is always zero, so just setting 2493 * dontcare to 0 (no masked bits). If mask is valid, pulls in 2494 * overflow bits of mask from prev byte 2495 */ 2496 dontcare[dst] = (tmp_m & 0xff00) >> 8; 2497 2498 /* If there is displacement, last byte will only contain 2499 * displaced data, but there is no more data to read from user 2500 * buffer, so skip so as not to potentially read beyond end of 2501 * user buffer 2502 */ 2503 if (!disp || k < info->entry.last - 1) { 2504 /* Store shifted data to use in next byte */ 2505 tmp_s = data[src++] << disp; 2506 2507 /* Add current (shifted) byte */ 2508 buf[dst] |= tmp_s & 0xff; 2509 2510 /* Handle mask if valid */ 2511 if (use_mask) { 2512 tmp_m = (~data[mask++] & 0xff) << disp; 2513 dontcare[dst] |= tmp_m & 0xff; 2514 } 2515 } 2516 } 2517 2518 /* Fill in don't care bits at beginning of field */ 2519 if (disp) { 2520 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2521 for (k = 0; k < disp; k++) 2522 dontcare[dst] |= BIT(k); 2523 } 2524 2525 end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE; 2526 2527 /* Fill in don't care bits at end of field */ 2528 if (end_disp) { 2529 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX + 2530 info->entry.last - 1; 2531 for (k = end_disp; k < BITS_PER_BYTE; k++) 2532 dontcare[dst] |= BIT(k); 2533 } 2534 } 2535 2536 /** 2537 * ice_flow_acl_frmt_entry - Format ACL entry 2538 * @hw: pointer to the hardware structure 2539 * @prof: pointer to flow profile 2540 * @e: pointer to the flow entry 2541 * @data: pointer to a data buffer containing flow entry's match values/masks 2542 * @acts: array of actions to be performed on a match 2543 * @acts_cnt: number of actions 2544 * 2545 * Formats the key (and key_inverse) to be matched from the data passed in, 2546 * along with data from the flow profile. This key/key_inverse pair makes up 2547 * the 'entry' for an ACL flow entry. 2548 */ 2549 static enum ice_status 2550 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof, 2551 struct ice_flow_entry *e, u8 *data, 2552 struct ice_flow_action *acts, u8 acts_cnt) 2553 { 2554 u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk; 2555 struct ice_aqc_acl_profile_ranges *range_buf = NULL; 2556 enum ice_status status; 2557 bool cnt_alloc; 2558 u8 prof_id = 0; 2559 u16 i, buf_sz; 2560 2561 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 2562 if (status) 2563 return status; 2564 2565 /* Format the result action */ 2566 2567 status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc); 2568 if (status) 2569 return status; 2570 2571 status = ICE_ERR_NO_MEMORY; 2572 2573 e->acts = (struct ice_flow_action *) 2574 ice_memdup(hw, acts, acts_cnt * sizeof(*acts), 2575 ICE_NONDMA_TO_NONDMA); 2576 if (!e->acts) 2577 goto out; 2578 2579 e->acts_cnt = acts_cnt; 2580 2581 /* Format the matching data */ 2582 buf_sz = prof->cfg.scen->width; 2583 buf = (u8 *)ice_malloc(hw, buf_sz); 2584 if (!buf) 2585 goto out; 2586 2587 dontcare = (u8 *)ice_malloc(hw, buf_sz); 2588 if (!dontcare) 2589 goto out; 2590 2591 /* 'key' buffer will store both key and key_inverse, so must be twice 2592 * size of buf 2593 */ 2594 key = (u8 *)ice_malloc(hw, buf_sz * 2); 2595 if (!key) 2596 goto out; 2597 2598 range_buf = (struct ice_aqc_acl_profile_ranges *) 2599 ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges)); 2600 if (!range_buf) 2601 goto out; 2602 2603 /* Set don't care mask to all 1's to start, will zero out used bytes */ 2604 ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM); 2605 2606 for (i = 0; i < prof->segs_cnt; i++) { 2607 struct ice_flow_seg_info *seg = &prof->segs[i]; 2608 u8 j; 2609 2610 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match, 2611 ICE_FLOW_FIELD_IDX_MAX) { 2612 struct ice_flow_fld_info *info = &seg->fields[j]; 2613 2614 if (info->type == ICE_FLOW_FLD_TYPE_RANGE) 2615 ice_flow_acl_frmt_entry_range(j, info, 2616 range_buf, data, 2617 &range); 2618 else 2619 ice_flow_acl_frmt_entry_fld(j, info, buf, 2620 dontcare, data); 2621 } 2622 2623 for (j = 0; j < seg->raws_cnt; j++) { 2624 struct ice_flow_fld_info *info = &seg->raws[j].info; 2625 u16 dst, src, mask, k; 2626 bool use_mask = false; 2627 2628 src = info->src.val; 2629 dst = info->entry.val - 2630 ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2631 mask = info->src.mask; 2632 2633 if (mask != ICE_FLOW_FLD_OFF_INVAL) 2634 use_mask = true; 2635 2636 for (k = 0; k < info->entry.last; k++, dst++) { 2637 buf[dst] = data[src++]; 2638 if (use_mask) 2639 dontcare[dst] = ~data[mask++]; 2640 else 2641 dontcare[dst] = 0; 2642 } 2643 } 2644 } 2645 2646 buf[prof->cfg.scen->pid_idx] = (u8)prof_id; 2647 dontcare[prof->cfg.scen->pid_idx] = 0; 2648 2649 /* Format the buffer for direction flags */ 2650 dir_flag_msk = BIT(ICE_FLG_PKT_DIR); 2651 2652 if (prof->dir == ICE_FLOW_RX) 2653 buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk; 2654 2655 if (range) { 2656 buf[prof->cfg.scen->rng_chk_idx] = range; 2657 /* Mark any unused range checkers as don't care */ 2658 dontcare[prof->cfg.scen->rng_chk_idx] = ~range; 2659 e->range_buf = range_buf; 2660 } else { 2661 ice_free(hw, range_buf); 2662 } 2663 2664 status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0, 2665 buf_sz); 2666 if (status) 2667 goto out; 2668 2669 e->entry = key; 2670 e->entry_sz = buf_sz * 2; 2671 2672 out: 2673 if (buf) 2674 ice_free(hw, buf); 2675 2676 if (dontcare) 2677 ice_free(hw, dontcare); 2678 2679 if (status && key) 2680 ice_free(hw, key); 2681 2682 if (status && range_buf) { 2683 ice_free(hw, range_buf); 2684 e->range_buf = NULL; 2685 } 2686 2687 if (status && e->acts) { 2688 ice_free(hw, e->acts); 2689 e->acts = NULL; 2690 e->acts_cnt = 0; 2691 } 2692 2693 if (status && cnt_alloc) 2694 ice_flow_acl_free_act_cntr(hw, acts, acts_cnt); 2695 2696 return status; 2697 } 2698 2699 /** 2700 * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches 2701 * the compared data. 2702 * @prof: pointer to flow profile 2703 * @e: pointer to the comparing flow entry 2704 * @do_chg_action: decide if we want to change the ACL action 2705 * @do_add_entry: decide if we want to add the new ACL entry 2706 * @do_rem_entry: decide if we want to remove the current ACL entry 2707 * 2708 * Find an ACL scenario entry that matches the compared data. In the same time, 2709 * this function also figure out: 2710 * a/ If we want to change the ACL action 2711 * b/ If we want to add the new ACL entry 2712 * c/ If we want to remove the current ACL entry 2713 */ 2714 static struct ice_flow_entry * 2715 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof, 2716 struct ice_flow_entry *e, bool *do_chg_action, 2717 bool *do_add_entry, bool *do_rem_entry) 2718 { 2719 struct ice_flow_entry *p, *return_entry = NULL; 2720 u8 i, j; 2721 2722 /* Check if: 2723 * a/ There exists an entry with same matching data, but different 2724 * priority, then we remove this existing ACL entry. Then, we 2725 * will add the new entry to the ACL scenario. 2726 * b/ There exists an entry with same matching data, priority, and 2727 * result action, then we do nothing 2728 * c/ There exists an entry with same matching data, priority, but 2729 * different, action, then do only change the action's entry. 2730 * d/ Else, we add this new entry to the ACL scenario. 2731 */ 2732 *do_chg_action = false; 2733 *do_add_entry = true; 2734 *do_rem_entry = false; 2735 LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) { 2736 if (memcmp(p->entry, e->entry, p->entry_sz)) 2737 continue; 2738 2739 /* From this point, we have the same matching_data. */ 2740 *do_add_entry = false; 2741 return_entry = p; 2742 2743 if (p->priority != e->priority) { 2744 /* matching data && !priority */ 2745 *do_add_entry = true; 2746 *do_rem_entry = true; 2747 break; 2748 } 2749 2750 /* From this point, we will have matching_data && priority */ 2751 if (p->acts_cnt != e->acts_cnt) 2752 *do_chg_action = true; 2753 for (i = 0; i < p->acts_cnt; i++) { 2754 bool found_not_match = false; 2755 2756 for (j = 0; j < e->acts_cnt; j++) 2757 if (memcmp(&p->acts[i], &e->acts[j], 2758 sizeof(struct ice_flow_action))) { 2759 found_not_match = true; 2760 break; 2761 } 2762 2763 if (found_not_match) { 2764 *do_chg_action = true; 2765 break; 2766 } 2767 } 2768 2769 /* (do_chg_action = true) means : 2770 * matching_data && priority && !result_action 2771 * (do_chg_action = false) means : 2772 * matching_data && priority && result_action 2773 */ 2774 break; 2775 } 2776 2777 return return_entry; 2778 } 2779 2780 /** 2781 * ice_flow_acl_convert_to_acl_prio - Convert to ACL priority 2782 * @p: flow priority 2783 */ 2784 static enum ice_acl_entry_prio 2785 ice_flow_acl_convert_to_acl_prio(enum ice_flow_priority p) 2786 { 2787 enum ice_acl_entry_prio acl_prio; 2788 2789 switch (p) { 2790 case ICE_FLOW_PRIO_LOW: 2791 acl_prio = ICE_ACL_PRIO_LOW; 2792 break; 2793 case ICE_FLOW_PRIO_NORMAL: 2794 acl_prio = ICE_ACL_PRIO_NORMAL; 2795 break; 2796 case ICE_FLOW_PRIO_HIGH: 2797 acl_prio = ICE_ACL_PRIO_HIGH; 2798 break; 2799 default: 2800 acl_prio = ICE_ACL_PRIO_NORMAL; 2801 break; 2802 } 2803 2804 return acl_prio; 2805 } 2806 2807 /** 2808 * ice_flow_acl_union_rng_chk - Perform union operation between two 2809 * range-range checker buffers 2810 * @dst_buf: pointer to destination range checker buffer 2811 * @src_buf: pointer to source range checker buffer 2812 * 2813 * For this function, we do the union between dst_buf and src_buf 2814 * range checker buffer, and we will save the result back to dst_buf 2815 */ 2816 static enum ice_status 2817 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf, 2818 struct ice_aqc_acl_profile_ranges *src_buf) 2819 { 2820 u8 i, j; 2821 2822 if (!dst_buf || !src_buf) 2823 return ICE_ERR_BAD_PTR; 2824 2825 for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) { 2826 struct ice_acl_rng_data *cfg_data = NULL, *in_data; 2827 bool will_populate = false; 2828 2829 in_data = &src_buf->checker_cfg[i]; 2830 2831 if (!in_data->mask) 2832 break; 2833 2834 for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) { 2835 cfg_data = &dst_buf->checker_cfg[j]; 2836 2837 if (!cfg_data->mask || 2838 !memcmp(cfg_data, in_data, 2839 sizeof(struct ice_acl_rng_data))) { 2840 will_populate = true; 2841 break; 2842 } 2843 } 2844 2845 if (will_populate) { 2846 ice_memcpy(cfg_data, in_data, 2847 sizeof(struct ice_acl_rng_data), 2848 ICE_NONDMA_TO_NONDMA); 2849 } else { 2850 /* No available slot left to program range checker */ 2851 return ICE_ERR_MAX_LIMIT; 2852 } 2853 } 2854 2855 return ICE_SUCCESS; 2856 } 2857 2858 /** 2859 * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync 2860 * @hw: pointer to the hardware structure 2861 * @prof: pointer to flow profile 2862 * @entry: double pointer to the flow entry 2863 * 2864 * For this function, we will look at the current added entries in the 2865 * corresponding ACL scenario. Then, we will perform matching logic to 2866 * see if we want to add/modify/do nothing with this new entry. 2867 */ 2868 static enum ice_status 2869 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof, 2870 struct ice_flow_entry **entry) 2871 { 2872 bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk; 2873 struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf; 2874 struct ice_acl_act_entry *acts = NULL; 2875 struct ice_flow_entry *exist; 2876 enum ice_status status = ICE_SUCCESS; 2877 struct ice_flow_entry *e; 2878 u8 i; 2879 2880 if (!entry || !(*entry) || !prof) 2881 return ICE_ERR_BAD_PTR; 2882 2883 e = *entry; 2884 2885 do_chg_rng_chk = false; 2886 if (e->range_buf) { 2887 u8 prof_id = 0; 2888 2889 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, 2890 &prof_id); 2891 if (status) 2892 return status; 2893 2894 /* Query the current range-checker value in FW */ 2895 status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf, 2896 NULL); 2897 if (status) 2898 return status; 2899 ice_memcpy(&cfg_rng_buf, &query_rng_buf, 2900 sizeof(struct ice_aqc_acl_profile_ranges), 2901 ICE_NONDMA_TO_NONDMA); 2902 2903 /* Generate the new range-checker value */ 2904 status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf); 2905 if (status) 2906 return status; 2907 2908 /* Reconfigure the range check if the buffer is changed. */ 2909 do_chg_rng_chk = false; 2910 if (memcmp(&query_rng_buf, &cfg_rng_buf, 2911 sizeof(struct ice_aqc_acl_profile_ranges))) { 2912 status = ice_prog_acl_prof_ranges(hw, prof_id, 2913 &cfg_rng_buf, NULL); 2914 if (status) 2915 return status; 2916 2917 do_chg_rng_chk = true; 2918 } 2919 } 2920 2921 /* Figure out if we want to (change the ACL action) and/or 2922 * (Add the new ACL entry) and/or (Remove the current ACL entry) 2923 */ 2924 exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action, 2925 &do_add_entry, &do_rem_entry); 2926 if (do_rem_entry) { 2927 status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist); 2928 if (status) 2929 return status; 2930 } 2931 2932 /* Prepare the result action buffer */ 2933 acts = (struct ice_acl_act_entry *) 2934 ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry)); 2935 if (!acts) 2936 return ICE_ERR_NO_MEMORY; 2937 2938 for (i = 0; i < e->acts_cnt; i++) 2939 ice_memcpy(&acts[i], &e->acts[i].data.acl_act, 2940 sizeof(struct ice_acl_act_entry), 2941 ICE_NONDMA_TO_NONDMA); 2942 2943 if (do_add_entry) { 2944 enum ice_acl_entry_prio prio; 2945 u8 *keys, *inverts; 2946 u16 entry_idx; 2947 2948 keys = (u8 *)e->entry; 2949 inverts = keys + (e->entry_sz / 2); 2950 prio = ice_flow_acl_convert_to_acl_prio(e->priority); 2951 2952 status = ice_acl_add_entry(hw, prof->cfg.scen, prio, keys, 2953 inverts, acts, e->acts_cnt, 2954 &entry_idx); 2955 if (status) 2956 goto out; 2957 2958 e->scen_entry_idx = entry_idx; 2959 LIST_ADD(&e->l_entry, &prof->entries); 2960 } else { 2961 if (do_chg_action) { 2962 /* For the action memory info, update the SW's copy of 2963 * exist entry with e's action memory info 2964 */ 2965 ice_free(hw, exist->acts); 2966 exist->acts_cnt = e->acts_cnt; 2967 exist->acts = (struct ice_flow_action *) 2968 ice_calloc(hw, exist->acts_cnt, 2969 sizeof(struct ice_flow_action)); 2970 if (!exist->acts) { 2971 status = ICE_ERR_NO_MEMORY; 2972 goto out; 2973 } 2974 2975 ice_memcpy(exist->acts, e->acts, 2976 sizeof(struct ice_flow_action) * e->acts_cnt, 2977 ICE_NONDMA_TO_NONDMA); 2978 2979 status = ice_acl_prog_act(hw, prof->cfg.scen, acts, 2980 e->acts_cnt, 2981 exist->scen_entry_idx); 2982 if (status) 2983 goto out; 2984 } 2985 2986 if (do_chg_rng_chk) { 2987 /* In this case, we want to update the range checker 2988 * information of the exist entry 2989 */ 2990 status = ice_flow_acl_union_rng_chk(exist->range_buf, 2991 e->range_buf); 2992 if (status) 2993 goto out; 2994 } 2995 2996 /* As we don't add the new entry to our SW DB, deallocate its 2997 * memories, and return the exist entry to the caller 2998 */ 2999 ice_dealloc_flow_entry(hw, e); 3000 *(entry) = exist; 3001 } 3002 out: 3003 ice_free(hw, acts); 3004 3005 return status; 3006 } 3007 3008 /** 3009 * ice_flow_acl_add_scen_entry - Add entry to ACL scenario 3010 * @hw: pointer to the hardware structure 3011 * @prof: pointer to flow profile 3012 * @e: double pointer to the flow entry 3013 */ 3014 static enum ice_status 3015 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof, 3016 struct ice_flow_entry **e) 3017 { 3018 enum ice_status status; 3019 3020 ice_acquire_lock(&prof->entries_lock); 3021 status = ice_flow_acl_add_scen_entry_sync(hw, prof, e); 3022 ice_release_lock(&prof->entries_lock); 3023 3024 return status; 3025 } 3026 3027 /** 3028 * ice_flow_add_entry - Add a flow entry 3029 * @hw: pointer to the HW struct 3030 * @blk: classification stage 3031 * @prof_id: ID of the profile to add a new flow entry to 3032 * @entry_id: unique ID to identify this flow entry 3033 * @vsi_handle: software VSI handle for the flow entry 3034 * @prio: priority of the flow entry 3035 * @data: pointer to a data buffer containing flow entry's match values/masks 3036 * @acts: arrays of actions to be performed on a match 3037 * @acts_cnt: number of actions 3038 * @entry_h: pointer to buffer that receives the new flow entry's handle 3039 */ 3040 enum ice_status 3041 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 3042 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, 3043 void *data, struct ice_flow_action *acts, u8 acts_cnt, 3044 u64 *entry_h) 3045 { 3046 struct ice_flow_entry *e = NULL; 3047 struct ice_flow_prof *prof; 3048 enum ice_status status = ICE_SUCCESS; 3049 3050 /* ACL entries must indicate an action */ 3051 if (blk == ICE_BLK_ACL && (!acts || !acts_cnt)) 3052 return ICE_ERR_PARAM; 3053 3054 /* No flow entry data is expected for RSS */ 3055 if (!entry_h || (!data && blk != ICE_BLK_RSS)) 3056 return ICE_ERR_BAD_PTR; 3057 3058 if (!ice_is_vsi_valid(hw, vsi_handle)) 3059 return ICE_ERR_PARAM; 3060 3061 ice_acquire_lock(&hw->fl_profs_locks[blk]); 3062 3063 prof = ice_flow_find_prof_id(hw, blk, prof_id); 3064 if (!prof) { 3065 status = ICE_ERR_DOES_NOT_EXIST; 3066 } else { 3067 /* Allocate memory for the entry being added and associate 3068 * the VSI to the found flow profile 3069 */ 3070 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e)); 3071 if (!e) 3072 status = ICE_ERR_NO_MEMORY; 3073 else 3074 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 3075 } 3076 3077 ice_release_lock(&hw->fl_profs_locks[blk]); 3078 if (status) 3079 goto out; 3080 3081 e->id = entry_id; 3082 e->vsi_handle = vsi_handle; 3083 e->prof = prof; 3084 e->priority = prio; 3085 3086 switch (blk) { 3087 case ICE_BLK_FD: 3088 case ICE_BLK_RSS: 3089 break; 3090 case ICE_BLK_ACL: 3091 /* ACL will handle the entry management */ 3092 status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts, 3093 acts_cnt); 3094 if (status) 3095 goto out; 3096 3097 status = ice_flow_acl_add_scen_entry(hw, prof, &e); 3098 if (status) 3099 goto out; 3100 3101 break; 3102 default: 3103 status = ICE_ERR_NOT_IMPL; 3104 goto out; 3105 } 3106 3107 if (blk != ICE_BLK_ACL) { 3108 /* ACL will handle the entry management */ 3109 ice_acquire_lock(&prof->entries_lock); 3110 LIST_ADD(&e->l_entry, &prof->entries); 3111 ice_release_lock(&prof->entries_lock); 3112 } 3113 3114 *entry_h = ICE_FLOW_ENTRY_HNDL(e); 3115 3116 out: 3117 if (status && e) { 3118 if (e->entry) 3119 ice_free(hw, e->entry); 3120 ice_free(hw, e); 3121 } 3122 3123 return status; 3124 } 3125 3126 /** 3127 * ice_flow_rem_entry - Remove a flow entry 3128 * @hw: pointer to the HW struct 3129 * @blk: classification stage 3130 * @entry_h: handle to the flow entry to be removed 3131 */ 3132 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, 3133 u64 entry_h) 3134 { 3135 struct ice_flow_entry *entry; 3136 struct ice_flow_prof *prof; 3137 enum ice_status status = ICE_SUCCESS; 3138 3139 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) 3140 return ICE_ERR_PARAM; 3141 3142 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h); 3143 3144 /* Retain the pointer to the flow profile as the entry will be freed */ 3145 prof = entry->prof; 3146 3147 if (prof) { 3148 ice_acquire_lock(&prof->entries_lock); 3149 status = ice_flow_rem_entry_sync(hw, blk, entry); 3150 ice_release_lock(&prof->entries_lock); 3151 } 3152 3153 return status; 3154 } 3155 3156 /** 3157 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 3158 * @seg: packet segment the field being set belongs to 3159 * @fld: field to be set 3160 * @field_type: type of the field 3161 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3162 * entry's input buffer 3163 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 3164 * input buffer 3165 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 3166 * entry's input buffer 3167 * 3168 * This helper function stores information of a field being matched, including 3169 * the type of the field and the locations of the value to match, the mask, and 3170 * the upper-bound value in the start of the input buffer for a flow entry. 3171 * This function should only be used for fixed-size data structures. 3172 * 3173 * This function also opportunistically determines the protocol headers to be 3174 * present based on the fields being set. Some fields cannot be used alone to 3175 * determine the protocol headers present. Sometimes, fields for particular 3176 * protocol headers are not matched. In those cases, the protocol headers 3177 * must be explicitly set. 3178 */ 3179 static void 3180 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3181 enum ice_flow_fld_match_type field_type, u16 val_loc, 3182 u16 mask_loc, u16 last_loc) 3183 { 3184 u64 bit = BIT_ULL(fld); 3185 3186 seg->match |= bit; 3187 if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 3188 seg->range |= bit; 3189 3190 seg->fields[fld].type = field_type; 3191 seg->fields[fld].src.val = val_loc; 3192 seg->fields[fld].src.mask = mask_loc; 3193 seg->fields[fld].src.last = last_loc; 3194 3195 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 3196 } 3197 3198 /** 3199 * ice_flow_set_fld - specifies locations of field from entry's input buffer 3200 * @seg: packet segment the field being set belongs to 3201 * @fld: field to be set 3202 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3203 * entry's input buffer 3204 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 3205 * input buffer 3206 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 3207 * entry's input buffer 3208 * @range: indicate if field being matched is to be in a range 3209 * 3210 * This function specifies the locations, in the form of byte offsets from the 3211 * start of the input buffer for a flow entry, from where the value to match, 3212 * the mask value, and upper value can be extracted. These locations are then 3213 * stored in the flow profile. When adding a flow entry associated with the 3214 * flow profile, these locations will be used to quickly extract the values and 3215 * create the content of a match entry. This function should only be used for 3216 * fixed-size data structures. 3217 */ 3218 void 3219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3220 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 3221 { 3222 enum ice_flow_fld_match_type t = range ? 3223 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 3224 3225 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 3226 } 3227 3228 /** 3229 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 3230 * @seg: packet segment the field being set belongs to 3231 * @fld: field to be set 3232 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3233 * entry's input buffer 3234 * @pref_loc: location of prefix value from entry's input buffer 3235 * @pref_sz: size of the location holding the prefix value 3236 * 3237 * This function specifies the locations, in the form of byte offsets from the 3238 * start of the input buffer for a flow entry, from where the value to match 3239 * and the IPv4 prefix value can be extracted. These locations are then stored 3240 * in the flow profile. When adding flow entries to the associated flow profile, 3241 * these locations can be used to quickly extract the values to create the 3242 * content of a match entry. This function should only be used for fixed-size 3243 * data structures. 3244 */ 3245 void 3246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3247 u16 val_loc, u16 pref_loc, u8 pref_sz) 3248 { 3249 /* For this type of field, the "mask" location is for the prefix value's 3250 * location and the "last" location is for the size of the location of 3251 * the prefix value. 3252 */ 3253 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 3254 pref_loc, (u16)pref_sz); 3255 } 3256 3257 /** 3258 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf 3259 * @seg: packet segment the field being set belongs to 3260 * @off: offset of the raw field from the beginning of the segment in bytes 3261 * @len: length of the raw pattern to be matched 3262 * @val_loc: location of the value to match from entry's input buffer 3263 * @mask_loc: location of mask value from entry's input buffer 3264 * 3265 * This function specifies the offset of the raw field to be match from the 3266 * beginning of the specified packet segment, and the locations, in the form of 3267 * byte offsets from the start of the input buffer for a flow entry, from where 3268 * the value to match and the mask value to be extracted. These locations are 3269 * then stored in the flow profile. When adding flow entries to the associated 3270 * flow profile, these locations can be used to quickly extract the values to 3271 * create the content of a match entry. This function should only be used for 3272 * fixed-size data structures. 3273 */ 3274 void 3275 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, 3276 u16 val_loc, u16 mask_loc) 3277 { 3278 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { 3279 seg->raws[seg->raws_cnt].off = off; 3280 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; 3281 seg->raws[seg->raws_cnt].info.src.val = val_loc; 3282 seg->raws[seg->raws_cnt].info.src.mask = mask_loc; 3283 /* The "last" field is used to store the length of the field */ 3284 seg->raws[seg->raws_cnt].info.src.last = len; 3285 } 3286 3287 /* Overflows of "raws" will be handled as an error condition later in 3288 * the flow when this information is processed. 3289 */ 3290 seg->raws_cnt++; 3291 } 3292 3293 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \ 3294 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 3295 3296 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 3297 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 3298 3299 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 3300 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 3301 3302 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 3303 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ 3304 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 3305 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 3306 3307 /** 3308 * ice_flow_set_rss_seg_info - setup packet segments for RSS 3309 * @segs: pointer to the flow field segment(s) 3310 * @seg_cnt: segment count 3311 * @cfg: configure parameters 3312 * 3313 * Helper function to extract fields from hash bitmap and use flow 3314 * header value to set flow field segment for further use in flow 3315 * profile entry or removal. 3316 */ 3317 static enum ice_status 3318 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, 3319 const struct ice_rss_hash_cfg *cfg) 3320 { 3321 struct ice_flow_seg_info *seg; 3322 u64 val; 3323 u8 i; 3324 3325 /* set inner most segment */ 3326 seg = &segs[seg_cnt - 1]; 3327 3328 ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds, 3329 ICE_FLOW_FIELD_IDX_MAX) 3330 ice_flow_set_fld(seg, (enum ice_flow_field)i, 3331 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 3332 ICE_FLOW_FLD_OFF_INVAL, false); 3333 3334 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); 3335 3336 /* set outer most header */ 3337 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) 3338 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 3339 ICE_FLOW_SEG_HDR_IPV_OTHER; 3340 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) 3341 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 3342 ICE_FLOW_SEG_HDR_IPV_OTHER; 3343 3344 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & 3345 ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) 3346 return ICE_ERR_PARAM; 3347 3348 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 3349 if (val && !ice_is_pow2(val)) 3350 return ICE_ERR_CFG; 3351 3352 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 3353 if (val && !ice_is_pow2(val)) 3354 return ICE_ERR_CFG; 3355 3356 return ICE_SUCCESS; 3357 } 3358 3359 /** 3360 * ice_rem_vsi_rss_list - remove VSI from RSS list 3361 * @hw: pointer to the hardware structure 3362 * @vsi_handle: software VSI handle 3363 * 3364 * Remove the VSI from all RSS configurations in the list. 3365 */ 3366 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 3367 { 3368 struct ice_rss_cfg *r, *tmp; 3369 3370 if (LIST_EMPTY(&hw->rss_list_head)) 3371 return; 3372 3373 ice_acquire_lock(&hw->rss_locks); 3374 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 3375 ice_rss_cfg, l_entry) 3376 if (ice_test_and_clear_bit(vsi_handle, r->vsis)) 3377 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 3378 LIST_DEL(&r->l_entry); 3379 ice_free(hw, r); 3380 } 3381 ice_release_lock(&hw->rss_locks); 3382 } 3383 3384 /** 3385 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 3386 * @hw: pointer to the hardware structure 3387 * @vsi_handle: software VSI handle 3388 * 3389 * This function will iterate through all flow profiles and disassociate 3390 * the VSI from that profile. If the flow profile has no VSIs it will 3391 * be removed. 3392 */ 3393 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 3394 { 3395 const enum ice_block blk = ICE_BLK_RSS; 3396 struct ice_flow_prof *p, *t; 3397 enum ice_status status = ICE_SUCCESS; 3398 3399 if (!ice_is_vsi_valid(hw, vsi_handle)) 3400 return ICE_ERR_PARAM; 3401 3402 if (LIST_EMPTY(&hw->fl_profs[blk])) 3403 return ICE_SUCCESS; 3404 3405 ice_acquire_lock(&hw->rss_locks); 3406 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 3407 l_entry) 3408 if (ice_is_bit_set(p->vsis, vsi_handle)) { 3409 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 3410 if (status) 3411 break; 3412 3413 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 3414 status = ice_flow_rem_prof(hw, blk, p->id); 3415 if (status) 3416 break; 3417 } 3418 } 3419 ice_release_lock(&hw->rss_locks); 3420 3421 return status; 3422 } 3423 3424 /** 3425 * ice_get_rss_hdr_type - get a RSS profile's header type 3426 * @prof: RSS flow profile 3427 */ 3428 static enum ice_rss_cfg_hdr_type 3429 ice_get_rss_hdr_type(struct ice_flow_prof *prof) 3430 { 3431 enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS; 3432 3433 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { 3434 hdr_type = ICE_RSS_OUTER_HEADERS; 3435 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { 3436 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE) 3437 hdr_type = ICE_RSS_INNER_HEADERS; 3438 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4) 3439 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; 3440 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6) 3441 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; 3442 } 3443 3444 return hdr_type; 3445 } 3446 3447 /** 3448 * ice_rem_rss_list - remove RSS configuration from list 3449 * @hw: pointer to the hardware structure 3450 * @vsi_handle: software VSI handle 3451 * @prof: pointer to flow profile 3452 * 3453 * Assumption: lock has already been acquired for RSS list 3454 */ 3455 static void 3456 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 3457 { 3458 enum ice_rss_cfg_hdr_type hdr_type; 3459 struct ice_rss_cfg *r, *tmp; 3460 3461 /* Search for RSS hash fields associated to the VSI that match the 3462 * hash configurations associated to the flow profile. If found 3463 * remove from the RSS entry list of the VSI context and delete entry. 3464 */ 3465 hdr_type = ice_get_rss_hdr_type(prof); 3466 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 3467 ice_rss_cfg, l_entry) 3468 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && 3469 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 3470 r->hash.hdr_type == hdr_type) { 3471 ice_clear_bit(vsi_handle, r->vsis); 3472 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 3473 LIST_DEL(&r->l_entry); 3474 ice_free(hw, r); 3475 } 3476 return; 3477 } 3478 } 3479 3480 /** 3481 * ice_add_rss_list - add RSS configuration to list 3482 * @hw: pointer to the hardware structure 3483 * @vsi_handle: software VSI handle 3484 * @prof: pointer to flow profile 3485 * 3486 * Assumption: lock has already been acquired for RSS list 3487 */ 3488 static enum ice_status 3489 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 3490 { 3491 enum ice_rss_cfg_hdr_type hdr_type; 3492 struct ice_rss_cfg *r, *rss_cfg; 3493 3494 hdr_type = ice_get_rss_hdr_type(prof); 3495 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3496 ice_rss_cfg, l_entry) 3497 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && 3498 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 3499 r->hash.hdr_type == hdr_type) { 3500 ice_set_bit(vsi_handle, r->vsis); 3501 return ICE_SUCCESS; 3502 } 3503 3504 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 3505 if (!rss_cfg) 3506 return ICE_ERR_NO_MEMORY; 3507 3508 rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match; 3509 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; 3510 rss_cfg->hash.hdr_type = hdr_type; 3511 rss_cfg->hash.symm = prof->cfg.symm; 3512 ice_set_bit(vsi_handle, rss_cfg->vsis); 3513 3514 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); 3515 3516 return ICE_SUCCESS; 3517 } 3518 3519 #define ICE_FLOW_PROF_HASH_S 0 3520 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 3521 #define ICE_FLOW_PROF_HDR_S 32 3522 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 3523 #define ICE_FLOW_PROF_ENCAP_S 62 3524 #define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S) 3525 3526 /* Flow profile ID format: 3527 * [0:31] - Packet match fields 3528 * [32:61] - Protocol header 3529 * [62:63] - Encapsulation flag: 3530 * 0 if non-tunneled 3531 * 1 if tunneled 3532 * 2 for tunneled with outer ipv4 3533 * 3 for tunneled with outer ipv6 3534 */ 3535 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ 3536 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 3537 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 3538 (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M)) 3539 3540 static void 3541 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst) 3542 { 3543 u32 s = ((src % 4) << 3); /* byte shift */ 3544 u32 v = dst | 0x80; /* value to program */ 3545 u8 i = src / 4; /* register index */ 3546 u32 reg; 3547 3548 reg = rd32(hw, GLQF_HSYMM(prof_id, i)); 3549 reg = (reg & ~(0xff << s)) | (v << s); 3550 wr32(hw, GLQF_HSYMM(prof_id, i), reg); 3551 } 3552 3553 static void 3554 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len) 3555 { 3556 int fv_last_word = 3557 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1; 3558 int i; 3559 3560 for (i = 0; i < len; i++) { 3561 ice_rss_config_xor_word(hw, prof_id, 3562 /* Yes, field vector in GLQF_HSYMM and 3563 * GLQF_HINSET is inversed! 3564 */ 3565 fv_last_word - (src + i), 3566 fv_last_word - (dst + i)); 3567 ice_rss_config_xor_word(hw, prof_id, 3568 fv_last_word - (dst + i), 3569 fv_last_word - (src + i)); 3570 } 3571 } 3572 3573 static void 3574 ice_rss_update_symm(struct ice_hw *hw, 3575 struct ice_flow_prof *prof) 3576 { 3577 struct ice_prof_map *map; 3578 u8 prof_id, m; 3579 3580 ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); 3581 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id); 3582 if (map) 3583 prof_id = map->prof_id; 3584 ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); 3585 if (!map) 3586 return; 3587 /* clear to default */ 3588 for (m = 0; m < 6; m++) 3589 wr32(hw, GLQF_HSYMM(prof_id, m), 0); 3590 if (prof->cfg.symm) { 3591 struct ice_flow_seg_info *seg = 3592 &prof->segs[prof->segs_cnt - 1]; 3593 3594 struct ice_flow_seg_xtrct *ipv4_src = 3595 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct; 3596 struct ice_flow_seg_xtrct *ipv4_dst = 3597 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct; 3598 struct ice_flow_seg_xtrct *ipv6_src = 3599 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct; 3600 struct ice_flow_seg_xtrct *ipv6_dst = 3601 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct; 3602 3603 struct ice_flow_seg_xtrct *tcp_src = 3604 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct; 3605 struct ice_flow_seg_xtrct *tcp_dst = 3606 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct; 3607 3608 struct ice_flow_seg_xtrct *udp_src = 3609 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct; 3610 struct ice_flow_seg_xtrct *udp_dst = 3611 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct; 3612 3613 struct ice_flow_seg_xtrct *sctp_src = 3614 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct; 3615 struct ice_flow_seg_xtrct *sctp_dst = 3616 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct; 3617 3618 /* xor IPv4 */ 3619 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0) 3620 ice_rss_config_xor(hw, prof_id, 3621 ipv4_src->idx, ipv4_dst->idx, 2); 3622 3623 /* xor IPv6 */ 3624 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0) 3625 ice_rss_config_xor(hw, prof_id, 3626 ipv6_src->idx, ipv6_dst->idx, 8); 3627 3628 /* xor TCP */ 3629 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0) 3630 ice_rss_config_xor(hw, prof_id, 3631 tcp_src->idx, tcp_dst->idx, 1); 3632 3633 /* xor UDP */ 3634 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0) 3635 ice_rss_config_xor(hw, prof_id, 3636 udp_src->idx, udp_dst->idx, 1); 3637 3638 /* xor SCTP */ 3639 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0) 3640 ice_rss_config_xor(hw, prof_id, 3641 sctp_src->idx, sctp_dst->idx, 1); 3642 } 3643 } 3644 3645 /** 3646 * ice_add_rss_cfg_sync - add an RSS configuration 3647 * @hw: pointer to the hardware structure 3648 * @vsi_handle: software VSI handle 3649 * @cfg: configure parameters 3650 * 3651 * Assumption: lock has already been acquired for RSS list 3652 */ 3653 static enum ice_status 3654 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 3655 const struct ice_rss_hash_cfg *cfg) 3656 { 3657 const enum ice_block blk = ICE_BLK_RSS; 3658 struct ice_flow_prof *prof = NULL; 3659 struct ice_flow_seg_info *segs; 3660 enum ice_status status; 3661 u8 segs_cnt; 3662 3663 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 3664 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; 3665 3666 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 3667 sizeof(*segs)); 3668 if (!segs) 3669 return ICE_ERR_NO_MEMORY; 3670 3671 /* Construct the packet segment info from the hashed fields */ 3672 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 3673 if (status) 3674 goto exit; 3675 3676 /* Don't do RSS for GTPU Outer */ 3677 if (segs_cnt == ICE_FLOW_SEG_SINGLE && 3678 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) { 3679 status = ICE_SUCCESS; 3680 goto exit; 3681 } 3682 3683 /* Search for a flow profile that has matching headers, hash fields 3684 * and has the input VSI associated to it. If found, no further 3685 * operations required and exit. 3686 */ 3687 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3688 vsi_handle, 3689 ICE_FLOW_FIND_PROF_CHK_FLDS | 3690 ICE_FLOW_FIND_PROF_CHK_VSI); 3691 if (prof) { 3692 if (prof->cfg.symm == cfg->symm) 3693 goto exit; 3694 prof->cfg.symm = cfg->symm; 3695 goto update_symm; 3696 } 3697 3698 /* Check if a flow profile exists with the same protocol headers and 3699 * associated with the input VSI. If so disassociate the VSI from 3700 * this profile. The VSI will be added to a new profile created with 3701 * the protocol header and new hash field configuration. 3702 */ 3703 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3704 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 3705 if (prof) { 3706 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 3707 if (!status) 3708 ice_rem_rss_list(hw, vsi_handle, prof); 3709 else 3710 goto exit; 3711 3712 /* Remove profile if it has no VSIs associated */ 3713 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 3714 status = ice_flow_rem_prof(hw, blk, prof->id); 3715 if (status) 3716 goto exit; 3717 } 3718 } 3719 3720 /* Search for a profile that has same match fields only. If this 3721 * exists then associate the VSI to this profile. 3722 */ 3723 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3724 vsi_handle, 3725 ICE_FLOW_FIND_PROF_CHK_FLDS); 3726 if (prof) { 3727 if (prof->cfg.symm == cfg->symm) { 3728 status = ice_flow_assoc_prof(hw, blk, prof, 3729 vsi_handle); 3730 if (!status) 3731 status = ice_add_rss_list(hw, vsi_handle, 3732 prof); 3733 } else { 3734 /* if a profile exist but with different symmetric 3735 * requirement, just return error. 3736 */ 3737 status = ICE_ERR_NOT_SUPPORTED; 3738 } 3739 goto exit; 3740 } 3741 3742 /* Create a new flow profile with generated profile and packet 3743 * segment information. 3744 */ 3745 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 3746 ICE_FLOW_GEN_PROFID(cfg->hash_flds, 3747 segs[segs_cnt - 1].hdrs, 3748 cfg->hdr_type), 3749 segs, segs_cnt, NULL, 0, &prof); 3750 if (status) 3751 goto exit; 3752 3753 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 3754 /* If association to a new flow profile failed then this profile can 3755 * be removed. 3756 */ 3757 if (status) { 3758 ice_flow_rem_prof(hw, blk, prof->id); 3759 goto exit; 3760 } 3761 3762 status = ice_add_rss_list(hw, vsi_handle, prof); 3763 3764 prof->cfg.symm = cfg->symm; 3765 update_symm: 3766 ice_rss_update_symm(hw, prof); 3767 3768 exit: 3769 ice_free(hw, segs); 3770 return status; 3771 } 3772 3773 /** 3774 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 3775 * @hw: pointer to the hardware structure 3776 * @vsi_handle: software VSI handle 3777 * @cfg: configure parameters 3778 * 3779 * This function will generate a flow profile based on fields associated with 3780 * the input fields to hash on, the flow type and use the VSI number to add 3781 * a flow entry to the profile. 3782 */ 3783 enum ice_status 3784 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 3785 const struct ice_rss_hash_cfg *cfg) 3786 { 3787 struct ice_rss_hash_cfg local_cfg; 3788 enum ice_status status; 3789 3790 if (!ice_is_vsi_valid(hw, vsi_handle) || 3791 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || 3792 cfg->hash_flds == ICE_HASH_INVALID) 3793 return ICE_ERR_PARAM; 3794 3795 local_cfg = *cfg; 3796 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 3797 ice_acquire_lock(&hw->rss_locks); 3798 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3799 ice_release_lock(&hw->rss_locks); 3800 } else { 3801 ice_acquire_lock(&hw->rss_locks); 3802 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 3803 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3804 if (!status) { 3805 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 3806 status = ice_add_rss_cfg_sync(hw, vsi_handle, 3807 &local_cfg); 3808 } 3809 ice_release_lock(&hw->rss_locks); 3810 } 3811 3812 return status; 3813 } 3814 3815 /** 3816 * ice_rem_rss_cfg_sync - remove an existing RSS configuration 3817 * @hw: pointer to the hardware structure 3818 * @vsi_handle: software VSI handle 3819 * @cfg: configure parameters 3820 * 3821 * Assumption: lock has already been acquired for RSS list 3822 */ 3823 static enum ice_status 3824 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 3825 const struct ice_rss_hash_cfg *cfg) 3826 { 3827 const enum ice_block blk = ICE_BLK_RSS; 3828 struct ice_flow_seg_info *segs; 3829 struct ice_flow_prof *prof; 3830 enum ice_status status; 3831 u8 segs_cnt; 3832 3833 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 3834 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; 3835 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 3836 sizeof(*segs)); 3837 if (!segs) 3838 return ICE_ERR_NO_MEMORY; 3839 3840 /* Construct the packet segment info from the hashed fields */ 3841 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 3842 if (status) 3843 goto out; 3844 3845 /* Don't do RSS for GTPU Outer */ 3846 if (segs_cnt == ICE_FLOW_SEG_SINGLE && 3847 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) { 3848 status = ICE_SUCCESS; 3849 goto out; 3850 } 3851 3852 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3853 vsi_handle, 3854 ICE_FLOW_FIND_PROF_CHK_FLDS); 3855 if (!prof) { 3856 status = ICE_ERR_DOES_NOT_EXIST; 3857 goto out; 3858 } 3859 3860 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 3861 if (status) 3862 goto out; 3863 3864 /* Remove RSS configuration from VSI context before deleting 3865 * the flow profile. 3866 */ 3867 ice_rem_rss_list(hw, vsi_handle, prof); 3868 3869 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 3870 status = ice_flow_rem_prof(hw, blk, prof->id); 3871 3872 out: 3873 ice_free(hw, segs); 3874 return status; 3875 } 3876 3877 /** 3878 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 3879 * @hw: pointer to the hardware structure 3880 * @vsi_handle: software VSI handle 3881 * @cfg: configure parameters 3882 * 3883 * This function will lookup the flow profile based on the input 3884 * hash field bitmap, iterate through the profile entry list of 3885 * that profile and find entry associated with input VSI to be 3886 * removed. Calls are made to underlying flow apis which will in 3887 * turn build or update buffers for RSS XLT1 section. 3888 */ 3889 enum ice_status 3890 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 3891 const struct ice_rss_hash_cfg *cfg) 3892 { 3893 struct ice_rss_hash_cfg local_cfg; 3894 enum ice_status status; 3895 3896 if (!ice_is_vsi_valid(hw, vsi_handle) || 3897 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || 3898 cfg->hash_flds == ICE_HASH_INVALID) 3899 return ICE_ERR_PARAM; 3900 3901 ice_acquire_lock(&hw->rss_locks); 3902 local_cfg = *cfg; 3903 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 3904 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3905 } else { 3906 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 3907 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3908 3909 if (!status) { 3910 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 3911 status = ice_rem_rss_cfg_sync(hw, vsi_handle, 3912 &local_cfg); 3913 } 3914 } 3915 ice_release_lock(&hw->rss_locks); 3916 3917 return status; 3918 } 3919 3920 /** 3921 * ice_replay_rss_cfg - replay RSS configurations associated with VSI 3922 * @hw: pointer to the hardware structure 3923 * @vsi_handle: software VSI handle 3924 */ 3925 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 3926 { 3927 enum ice_status status = ICE_SUCCESS; 3928 struct ice_rss_cfg *r; 3929 3930 if (!ice_is_vsi_valid(hw, vsi_handle)) 3931 return ICE_ERR_PARAM; 3932 3933 ice_acquire_lock(&hw->rss_locks); 3934 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3935 ice_rss_cfg, l_entry) { 3936 if (ice_is_bit_set(r->vsis, vsi_handle)) { 3937 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); 3938 if (status) 3939 break; 3940 } 3941 } 3942 ice_release_lock(&hw->rss_locks); 3943 3944 return status; 3945 } 3946 3947 /** 3948 * ice_get_rss_cfg - returns hashed fields for the given header types 3949 * @hw: pointer to the hardware structure 3950 * @vsi_handle: software VSI handle 3951 * @hdrs: protocol header type 3952 * 3953 * This function will return the match fields of the first instance of flow 3954 * profile having the given header types and containing input VSI 3955 */ 3956 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 3957 { 3958 u64 rss_hash = ICE_HASH_INVALID; 3959 struct ice_rss_cfg *r; 3960 3961 /* verify if the protocol header is non zero and VSI is valid */ 3962 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 3963 return ICE_HASH_INVALID; 3964 3965 ice_acquire_lock(&hw->rss_locks); 3966 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3967 ice_rss_cfg, l_entry) 3968 if (ice_is_bit_set(r->vsis, vsi_handle) && 3969 r->hash.addl_hdrs == hdrs) { 3970 rss_hash = r->hash.hash_flds; 3971 break; 3972 } 3973 ice_release_lock(&hw->rss_locks); 3974 3975 return rss_hash; 3976 } 3977