1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2021 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 = { 0 }; 1799 enum ice_status status; 1800 1801 /* amount is unused in the dealloc path but the common 1802 * parameter check routine wants a value set, as zero 1803 * is invalid for the check. Just set it. 1804 */ 1805 cntrs.amount = 1; 1806 cntrs.bank = 0; /* Only bank0 for the moment */ 1807 cntrs.first_cntr = 1808 LE16_TO_CPU(acts[i].data.acl_act.value); 1809 cntrs.last_cntr = 1810 LE16_TO_CPU(acts[i].data.acl_act.value); 1811 1812 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) 1813 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL; 1814 else 1815 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE; 1816 1817 status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL); 1818 if (status) 1819 return status; 1820 } 1821 } 1822 return ICE_SUCCESS; 1823 } 1824 1825 /** 1826 * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile 1827 * @hw: pointer to the hardware structure 1828 * @prof: pointer to flow profile 1829 * 1830 * Disassociate the scenario from the profile for the PF of the VSI. 1831 */ 1832 static enum ice_status 1833 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof) 1834 { 1835 struct ice_aqc_acl_prof_generic_frmt buf; 1836 enum ice_status status = ICE_SUCCESS; 1837 u8 prof_id = 0; 1838 1839 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 1840 1841 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 1842 if (status) 1843 return status; 1844 1845 status = ice_query_acl_prof(hw, prof_id, &buf, NULL); 1846 if (status) 1847 return status; 1848 1849 /* Clear scenario for this PF */ 1850 buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN; 1851 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL); 1852 1853 return status; 1854 } 1855 1856 /** 1857 * ice_flow_rem_entry_sync - Remove a flow entry 1858 * @hw: pointer to the HW struct 1859 * @blk: classification stage 1860 * @entry: flow entry to be removed 1861 */ 1862 static enum ice_status 1863 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk, 1864 struct ice_flow_entry *entry) 1865 { 1866 if (!entry) 1867 return ICE_ERR_BAD_PTR; 1868 1869 if (blk == ICE_BLK_ACL) { 1870 enum ice_status status; 1871 1872 if (!entry->prof) 1873 return ICE_ERR_BAD_PTR; 1874 1875 status = ice_acl_rem_entry(hw, entry->prof->cfg.scen, 1876 entry->scen_entry_idx); 1877 if (status) 1878 return status; 1879 1880 /* Checks if we need to release an ACL counter. */ 1881 if (entry->acts_cnt && entry->acts) 1882 ice_flow_acl_free_act_cntr(hw, entry->acts, 1883 entry->acts_cnt); 1884 } 1885 1886 LIST_DEL(&entry->l_entry); 1887 1888 ice_dealloc_flow_entry(hw, entry); 1889 1890 return ICE_SUCCESS; 1891 } 1892 1893 /** 1894 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 1895 * @hw: pointer to the HW struct 1896 * @blk: classification stage 1897 * @dir: flow direction 1898 * @prof_id: unique ID to identify this flow profile 1899 * @segs: array of one or more packet segments that describe the flow 1900 * @segs_cnt: number of packet segments provided 1901 * @acts: array of default actions 1902 * @acts_cnt: number of default actions 1903 * @prof: stores the returned flow profile added 1904 * 1905 * Assumption: the caller has acquired the lock to the profile list 1906 */ 1907 static enum ice_status 1908 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 1909 enum ice_flow_dir dir, u64 prof_id, 1910 struct ice_flow_seg_info *segs, u8 segs_cnt, 1911 struct ice_flow_action *acts, u8 acts_cnt, 1912 struct ice_flow_prof **prof) 1913 { 1914 struct ice_flow_prof_params *params; 1915 enum ice_status status; 1916 u8 i; 1917 1918 if (!prof || (acts_cnt && !acts)) 1919 return ICE_ERR_BAD_PTR; 1920 1921 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params)); 1922 if (!params) 1923 return ICE_ERR_NO_MEMORY; 1924 1925 params->prof = (struct ice_flow_prof *) 1926 ice_malloc(hw, sizeof(*params->prof)); 1927 if (!params->prof) { 1928 status = ICE_ERR_NO_MEMORY; 1929 goto free_params; 1930 } 1931 1932 /* initialize extraction sequence to all invalid (0xff) */ 1933 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 1934 params->es[i].prot_id = ICE_PROT_INVALID; 1935 params->es[i].off = ICE_FV_OFFSET_INVAL; 1936 } 1937 1938 params->blk = blk; 1939 params->prof->id = prof_id; 1940 params->prof->dir = dir; 1941 params->prof->segs_cnt = segs_cnt; 1942 1943 /* Make a copy of the segments that need to be persistent in the flow 1944 * profile instance 1945 */ 1946 for (i = 0; i < segs_cnt; i++) 1947 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs), 1948 ICE_NONDMA_TO_NONDMA); 1949 1950 /* Make a copy of the actions that need to be persistent in the flow 1951 * profile instance. 1952 */ 1953 if (acts_cnt) { 1954 params->prof->acts = (struct ice_flow_action *) 1955 ice_memdup(hw, acts, acts_cnt * sizeof(*acts), 1956 ICE_NONDMA_TO_NONDMA); 1957 1958 if (!params->prof->acts) { 1959 status = ICE_ERR_NO_MEMORY; 1960 goto out; 1961 } 1962 } 1963 1964 status = ice_flow_proc_segs(hw, params); 1965 if (status) { 1966 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 1967 goto out; 1968 } 1969 1970 /* Add a HW profile for this flow profile */ 1971 status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes, 1972 params->attr, params->attr_cnt, params->es, 1973 params->mask); 1974 if (status) { 1975 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 1976 goto out; 1977 } 1978 1979 INIT_LIST_HEAD(¶ms->prof->entries); 1980 ice_init_lock(¶ms->prof->entries_lock); 1981 *prof = params->prof; 1982 1983 out: 1984 if (status) { 1985 if (params->prof->acts) 1986 ice_free(hw, params->prof->acts); 1987 ice_free(hw, params->prof); 1988 } 1989 free_params: 1990 ice_free(hw, params); 1991 1992 return status; 1993 } 1994 1995 /** 1996 * ice_flow_rem_prof_sync - remove a flow profile 1997 * @hw: pointer to the hardware structure 1998 * @blk: classification stage 1999 * @prof: pointer to flow profile to remove 2000 * 2001 * Assumption: the caller has acquired the lock to the profile list 2002 */ 2003 static enum ice_status 2004 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 2005 struct ice_flow_prof *prof) 2006 { 2007 enum ice_status status; 2008 2009 /* Remove all remaining flow entries before removing the flow profile */ 2010 if (!LIST_EMPTY(&prof->entries)) { 2011 struct ice_flow_entry *e, *t; 2012 2013 ice_acquire_lock(&prof->entries_lock); 2014 2015 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry, 2016 l_entry) { 2017 status = ice_flow_rem_entry_sync(hw, blk, e); 2018 if (status) 2019 break; 2020 } 2021 2022 ice_release_lock(&prof->entries_lock); 2023 } 2024 2025 if (blk == ICE_BLK_ACL) { 2026 struct ice_aqc_acl_profile_ranges query_rng_buf; 2027 struct ice_aqc_acl_prof_generic_frmt buf; 2028 u8 prof_id = 0; 2029 2030 /* Disassociate the scenario from the profile for the PF */ 2031 status = ice_flow_acl_disassoc_scen(hw, prof); 2032 if (status) 2033 return status; 2034 2035 /* Clear the range-checker if the profile ID is no longer 2036 * used by any PF 2037 */ 2038 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf); 2039 if (status && status != ICE_ERR_IN_USE) { 2040 return status; 2041 } else if (!status) { 2042 /* Clear the range-checker value for profile ID */ 2043 ice_memset(&query_rng_buf, 0, 2044 sizeof(struct ice_aqc_acl_profile_ranges), 2045 ICE_NONDMA_MEM); 2046 2047 status = ice_flow_get_hw_prof(hw, blk, prof->id, 2048 &prof_id); 2049 if (status) 2050 return status; 2051 2052 status = ice_prog_acl_prof_ranges(hw, prof_id, 2053 &query_rng_buf, NULL); 2054 if (status) 2055 return status; 2056 } 2057 } 2058 2059 /* Remove all hardware profiles associated with this flow profile */ 2060 status = ice_rem_prof(hw, blk, prof->id); 2061 if (!status) { 2062 LIST_DEL(&prof->l_entry); 2063 ice_destroy_lock(&prof->entries_lock); 2064 if (prof->acts) 2065 ice_free(hw, prof->acts); 2066 ice_free(hw, prof); 2067 } 2068 2069 return status; 2070 } 2071 2072 /** 2073 * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field 2074 * @buf: Destination buffer function writes partial xtrct sequence to 2075 * @info: Info about field 2076 */ 2077 static void 2078 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf, 2079 struct ice_flow_fld_info *info) 2080 { 2081 u16 dst, i; 2082 u8 src; 2083 2084 src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ + 2085 info->xtrct.disp / BITS_PER_BYTE; 2086 dst = info->entry.val; 2087 for (i = 0; i < info->entry.last; i++) 2088 /* HW stores field vector words in LE, convert words back to BE 2089 * so constructed entries will end up in network order 2090 */ 2091 buf->byte_selection[dst++] = src++ ^ 1; 2092 } 2093 2094 /** 2095 * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence 2096 * @hw: pointer to the hardware structure 2097 * @prof: pointer to flow profile 2098 */ 2099 static enum ice_status 2100 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof) 2101 { 2102 struct ice_aqc_acl_prof_generic_frmt buf; 2103 struct ice_flow_fld_info *info; 2104 enum ice_status status; 2105 u8 prof_id = 0; 2106 u16 i; 2107 2108 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 2109 2110 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 2111 if (status) 2112 return status; 2113 2114 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf); 2115 if (status && status != ICE_ERR_IN_USE) 2116 return status; 2117 2118 if (!status) { 2119 /* Program the profile dependent configuration. This is done 2120 * only once regardless of the number of PFs using that profile 2121 */ 2122 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 2123 2124 for (i = 0; i < prof->segs_cnt; i++) { 2125 struct ice_flow_seg_info *seg = &prof->segs[i]; 2126 u16 j; 2127 2128 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match, 2129 ICE_FLOW_FIELD_IDX_MAX) { 2130 info = &seg->fields[j]; 2131 2132 if (info->type == ICE_FLOW_FLD_TYPE_RANGE) 2133 buf.word_selection[info->entry.val] = 2134 info->xtrct.idx; 2135 else 2136 ice_flow_acl_set_xtrct_seq_fld(&buf, 2137 info); 2138 } 2139 2140 for (j = 0; j < seg->raws_cnt; j++) { 2141 info = &seg->raws[j].info; 2142 ice_flow_acl_set_xtrct_seq_fld(&buf, info); 2143 } 2144 } 2145 2146 ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN, 2147 ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS, 2148 ICE_NONDMA_MEM); 2149 } 2150 2151 /* Update the current PF */ 2152 buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id; 2153 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL); 2154 2155 return status; 2156 } 2157 2158 /** 2159 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG 2160 * @hw: pointer to the hardware structure 2161 * @blk: classification stage 2162 * @vsi_handle: software VSI handle 2163 * @vsig: target VSI group 2164 * 2165 * Assumption: the caller has already verified that the VSI to 2166 * be added has the same characteristics as the VSIG and will 2167 * thereby have access to all resources added to that VSIG. 2168 */ 2169 enum ice_status 2170 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, 2171 u16 vsig) 2172 { 2173 enum ice_status status; 2174 2175 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) 2176 return ICE_ERR_PARAM; 2177 2178 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2179 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), 2180 vsig); 2181 ice_release_lock(&hw->fl_profs_locks[blk]); 2182 2183 return status; 2184 } 2185 2186 /** 2187 * ice_flow_assoc_prof - associate a VSI with a flow profile 2188 * @hw: pointer to the hardware structure 2189 * @blk: classification stage 2190 * @prof: pointer to flow profile 2191 * @vsi_handle: software VSI handle 2192 * 2193 * Assumption: the caller has acquired the lock to the profile list 2194 * and the software VSI handle has been validated 2195 */ 2196 enum ice_status 2197 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 2198 struct ice_flow_prof *prof, u16 vsi_handle) 2199 { 2200 enum ice_status status = ICE_SUCCESS; 2201 2202 if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 2203 if (blk == ICE_BLK_ACL) { 2204 status = ice_flow_acl_set_xtrct_seq(hw, prof); 2205 if (status) 2206 return status; 2207 } 2208 status = ice_add_prof_id_flow(hw, blk, 2209 ice_get_hw_vsi_num(hw, 2210 vsi_handle), 2211 prof->id); 2212 if (!status) 2213 ice_set_bit(vsi_handle, prof->vsis); 2214 else 2215 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 2216 status); 2217 } 2218 2219 return status; 2220 } 2221 2222 /** 2223 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 2224 * @hw: pointer to the hardware structure 2225 * @blk: classification stage 2226 * @prof: pointer to flow profile 2227 * @vsi_handle: software VSI handle 2228 * 2229 * Assumption: the caller has acquired the lock to the profile list 2230 * and the software VSI handle has been validated 2231 */ 2232 static enum ice_status 2233 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 2234 struct ice_flow_prof *prof, u16 vsi_handle) 2235 { 2236 enum ice_status status = ICE_SUCCESS; 2237 2238 if (ice_is_bit_set(prof->vsis, vsi_handle)) { 2239 status = ice_rem_prof_id_flow(hw, blk, 2240 ice_get_hw_vsi_num(hw, 2241 vsi_handle), 2242 prof->id); 2243 if (!status) 2244 ice_clear_bit(vsi_handle, prof->vsis); 2245 else 2246 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 2247 status); 2248 } 2249 2250 return status; 2251 } 2252 2253 /** 2254 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 2255 * @hw: pointer to the HW struct 2256 * @blk: classification stage 2257 * @dir: flow direction 2258 * @prof_id: unique ID to identify this flow profile 2259 * @segs: array of one or more packet segments that describe the flow 2260 * @segs_cnt: number of packet segments provided 2261 * @acts: array of default actions 2262 * @acts_cnt: number of default actions 2263 * @prof: stores the returned flow profile added 2264 */ 2265 enum ice_status 2266 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 2267 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 2268 struct ice_flow_action *acts, u8 acts_cnt, 2269 struct ice_flow_prof **prof) 2270 { 2271 enum ice_status status; 2272 2273 if (segs_cnt > ICE_FLOW_SEG_MAX) 2274 return ICE_ERR_MAX_LIMIT; 2275 2276 if (!segs_cnt) 2277 return ICE_ERR_PARAM; 2278 2279 if (!segs) 2280 return ICE_ERR_BAD_PTR; 2281 2282 status = ice_flow_val_hdrs(segs, segs_cnt); 2283 if (status) 2284 return status; 2285 2286 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2287 2288 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 2289 acts, acts_cnt, prof); 2290 if (!status) 2291 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 2292 2293 ice_release_lock(&hw->fl_profs_locks[blk]); 2294 2295 return status; 2296 } 2297 2298 /** 2299 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 2300 * @hw: pointer to the HW struct 2301 * @blk: the block for which the flow profile is to be removed 2302 * @prof_id: unique ID of the flow profile to be removed 2303 */ 2304 enum ice_status 2305 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 2306 { 2307 struct ice_flow_prof *prof; 2308 enum ice_status status; 2309 2310 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2311 2312 prof = ice_flow_find_prof_id(hw, blk, prof_id); 2313 if (!prof) { 2314 status = ICE_ERR_DOES_NOT_EXIST; 2315 goto out; 2316 } 2317 2318 /* prof becomes invalid after the call */ 2319 status = ice_flow_rem_prof_sync(hw, blk, prof); 2320 2321 out: 2322 ice_release_lock(&hw->fl_profs_locks[blk]); 2323 2324 return status; 2325 } 2326 2327 /** 2328 * ice_flow_find_entry - look for a flow entry using its unique ID 2329 * @hw: pointer to the HW struct 2330 * @blk: classification stage 2331 * @entry_id: unique ID to identify this flow entry 2332 * 2333 * This function looks for the flow entry with the specified unique ID in all 2334 * flow profiles of the specified classification stage. If the entry is found, 2335 * and it returns the handle to the flow entry. Otherwise, it returns 2336 * ICE_FLOW_ENTRY_ID_INVAL. 2337 */ 2338 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id) 2339 { 2340 struct ice_flow_entry *found = NULL; 2341 struct ice_flow_prof *p; 2342 2343 ice_acquire_lock(&hw->fl_profs_locks[blk]); 2344 2345 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { 2346 struct ice_flow_entry *e; 2347 2348 ice_acquire_lock(&p->entries_lock); 2349 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry) 2350 if (e->id == entry_id) { 2351 found = e; 2352 break; 2353 } 2354 ice_release_lock(&p->entries_lock); 2355 2356 if (found) 2357 break; 2358 } 2359 2360 ice_release_lock(&hw->fl_profs_locks[blk]); 2361 2362 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL; 2363 } 2364 2365 /** 2366 * ice_flow_acl_check_actions - Checks the ACL rule's actions 2367 * @hw: pointer to the hardware structure 2368 * @acts: array of actions to be performed on a match 2369 * @acts_cnt: number of actions 2370 * @cnt_alloc: indicates if an ACL counter has been allocated. 2371 */ 2372 static enum ice_status 2373 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts, 2374 u8 acts_cnt, bool *cnt_alloc) 2375 { 2376 ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2); 2377 int i; 2378 2379 ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2); 2380 *cnt_alloc = false; 2381 2382 if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT) 2383 return ICE_ERR_OUT_OF_RANGE; 2384 2385 for (i = 0; i < acts_cnt; i++) { 2386 if (acts[i].type != ICE_FLOW_ACT_NOP && 2387 acts[i].type != ICE_FLOW_ACT_DROP && 2388 acts[i].type != ICE_FLOW_ACT_CNTR_PKT && 2389 acts[i].type != ICE_FLOW_ACT_FWD_QUEUE) 2390 return ICE_ERR_CFG; 2391 2392 /* If the caller want to add two actions of the same type, then 2393 * it is considered invalid configuration. 2394 */ 2395 if (ice_test_and_set_bit(acts[i].type, dup_check)) 2396 return ICE_ERR_PARAM; 2397 } 2398 2399 /* Checks if ACL counters are needed. */ 2400 for (i = 0; i < acts_cnt; i++) { 2401 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT || 2402 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES || 2403 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) { 2404 struct ice_acl_cntrs cntrs = { 0 }; 2405 enum ice_status status; 2406 2407 cntrs.amount = 1; 2408 cntrs.bank = 0; /* Only bank0 for the moment */ 2409 2410 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) 2411 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL; 2412 else 2413 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE; 2414 2415 status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL); 2416 if (status) 2417 return status; 2418 /* Counter index within the bank */ 2419 acts[i].data.acl_act.value = 2420 CPU_TO_LE16(cntrs.first_cntr); 2421 *cnt_alloc = true; 2422 } 2423 } 2424 2425 return ICE_SUCCESS; 2426 } 2427 2428 /** 2429 * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field 2430 * @fld: number of the given field 2431 * @info: info about field 2432 * @range_buf: range checker configuration buffer 2433 * @data: pointer to a data buffer containing flow entry's match values/masks 2434 * @range: Input/output param indicating which range checkers are being used 2435 */ 2436 static void 2437 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info, 2438 struct ice_aqc_acl_profile_ranges *range_buf, 2439 u8 *data, u8 *range) 2440 { 2441 u16 new_mask; 2442 2443 /* If not specified, default mask is all bits in field */ 2444 new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ? 2445 BIT(ice_flds_info[fld].size) - 1 : 2446 (*(u16 *)(data + info->src.mask))) << info->xtrct.disp; 2447 2448 /* If the mask is 0, then we don't need to worry about this input 2449 * range checker value. 2450 */ 2451 if (new_mask) { 2452 u16 new_high = 2453 (*(u16 *)(data + info->src.last)) << info->xtrct.disp; 2454 u16 new_low = 2455 (*(u16 *)(data + info->src.val)) << info->xtrct.disp; 2456 u8 range_idx = info->entry.val; 2457 2458 range_buf->checker_cfg[range_idx].low_boundary = 2459 CPU_TO_BE16(new_low); 2460 range_buf->checker_cfg[range_idx].high_boundary = 2461 CPU_TO_BE16(new_high); 2462 range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask); 2463 2464 /* Indicate which range checker is being used */ 2465 *range |= BIT(range_idx); 2466 } 2467 } 2468 2469 /** 2470 * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field 2471 * @fld: number of the given field 2472 * @info: info about the field 2473 * @buf: buffer containing the entry 2474 * @dontcare: buffer containing don't care mask for entry 2475 * @data: pointer to a data buffer containing flow entry's match values/masks 2476 */ 2477 static void 2478 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf, 2479 u8 *dontcare, u8 *data) 2480 { 2481 u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0; 2482 bool use_mask = false; 2483 u8 disp; 2484 2485 src = info->src.val; 2486 mask = info->src.mask; 2487 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2488 disp = info->xtrct.disp % BITS_PER_BYTE; 2489 2490 if (mask != ICE_FLOW_FLD_OFF_INVAL) 2491 use_mask = true; 2492 2493 for (k = 0; k < info->entry.last; k++, dst++) { 2494 /* Add overflow bits from previous byte */ 2495 buf[dst] = (tmp_s & 0xff00) >> 8; 2496 2497 /* If mask is not valid, tmp_m is always zero, so just setting 2498 * dontcare to 0 (no masked bits). If mask is valid, pulls in 2499 * overflow bits of mask from prev byte 2500 */ 2501 dontcare[dst] = (tmp_m & 0xff00) >> 8; 2502 2503 /* If there is displacement, last byte will only contain 2504 * displaced data, but there is no more data to read from user 2505 * buffer, so skip so as not to potentially read beyond end of 2506 * user buffer 2507 */ 2508 if (!disp || k < info->entry.last - 1) { 2509 /* Store shifted data to use in next byte */ 2510 tmp_s = data[src++] << disp; 2511 2512 /* Add current (shifted) byte */ 2513 buf[dst] |= tmp_s & 0xff; 2514 2515 /* Handle mask if valid */ 2516 if (use_mask) { 2517 tmp_m = (~data[mask++] & 0xff) << disp; 2518 dontcare[dst] |= tmp_m & 0xff; 2519 } 2520 } 2521 } 2522 2523 /* Fill in don't care bits at beginning of field */ 2524 if (disp) { 2525 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2526 for (k = 0; k < disp; k++) 2527 dontcare[dst] |= BIT(k); 2528 } 2529 2530 end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE; 2531 2532 /* Fill in don't care bits at end of field */ 2533 if (end_disp) { 2534 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX + 2535 info->entry.last - 1; 2536 for (k = end_disp; k < BITS_PER_BYTE; k++) 2537 dontcare[dst] |= BIT(k); 2538 } 2539 } 2540 2541 /** 2542 * ice_flow_acl_frmt_entry - Format ACL entry 2543 * @hw: pointer to the hardware structure 2544 * @prof: pointer to flow profile 2545 * @e: pointer to the flow entry 2546 * @data: pointer to a data buffer containing flow entry's match values/masks 2547 * @acts: array of actions to be performed on a match 2548 * @acts_cnt: number of actions 2549 * 2550 * Formats the key (and key_inverse) to be matched from the data passed in, 2551 * along with data from the flow profile. This key/key_inverse pair makes up 2552 * the 'entry' for an ACL flow entry. 2553 */ 2554 static enum ice_status 2555 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof, 2556 struct ice_flow_entry *e, u8 *data, 2557 struct ice_flow_action *acts, u8 acts_cnt) 2558 { 2559 u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk; 2560 struct ice_aqc_acl_profile_ranges *range_buf = NULL; 2561 enum ice_status status; 2562 bool cnt_alloc; 2563 u8 prof_id = 0; 2564 u16 i, buf_sz; 2565 2566 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id); 2567 if (status) 2568 return status; 2569 2570 /* Format the result action */ 2571 2572 status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc); 2573 if (status) 2574 return status; 2575 2576 status = ICE_ERR_NO_MEMORY; 2577 2578 e->acts = (struct ice_flow_action *) 2579 ice_memdup(hw, acts, acts_cnt * sizeof(*acts), 2580 ICE_NONDMA_TO_NONDMA); 2581 if (!e->acts) 2582 goto out; 2583 2584 e->acts_cnt = acts_cnt; 2585 2586 /* Format the matching data */ 2587 buf_sz = prof->cfg.scen->width; 2588 buf = (u8 *)ice_malloc(hw, buf_sz); 2589 if (!buf) 2590 goto out; 2591 2592 dontcare = (u8 *)ice_malloc(hw, buf_sz); 2593 if (!dontcare) 2594 goto out; 2595 2596 /* 'key' buffer will store both key and key_inverse, so must be twice 2597 * size of buf 2598 */ 2599 key = (u8 *)ice_malloc(hw, buf_sz * 2); 2600 if (!key) 2601 goto out; 2602 2603 range_buf = (struct ice_aqc_acl_profile_ranges *) 2604 ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges)); 2605 if (!range_buf) 2606 goto out; 2607 2608 /* Set don't care mask to all 1's to start, will zero out used bytes */ 2609 ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM); 2610 2611 for (i = 0; i < prof->segs_cnt; i++) { 2612 struct ice_flow_seg_info *seg = &prof->segs[i]; 2613 u8 j; 2614 2615 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match, 2616 ICE_FLOW_FIELD_IDX_MAX) { 2617 struct ice_flow_fld_info *info = &seg->fields[j]; 2618 2619 if (info->type == ICE_FLOW_FLD_TYPE_RANGE) 2620 ice_flow_acl_frmt_entry_range(j, info, 2621 range_buf, data, 2622 &range); 2623 else 2624 ice_flow_acl_frmt_entry_fld(j, info, buf, 2625 dontcare, data); 2626 } 2627 2628 for (j = 0; j < seg->raws_cnt; j++) { 2629 struct ice_flow_fld_info *info = &seg->raws[j].info; 2630 u16 dst, src, mask, k; 2631 bool use_mask = false; 2632 2633 src = info->src.val; 2634 dst = info->entry.val - 2635 ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX; 2636 mask = info->src.mask; 2637 2638 if (mask != ICE_FLOW_FLD_OFF_INVAL) 2639 use_mask = true; 2640 2641 for (k = 0; k < info->entry.last; k++, dst++) { 2642 buf[dst] = data[src++]; 2643 if (use_mask) 2644 dontcare[dst] = ~data[mask++]; 2645 else 2646 dontcare[dst] = 0; 2647 } 2648 } 2649 } 2650 2651 buf[prof->cfg.scen->pid_idx] = (u8)prof_id; 2652 dontcare[prof->cfg.scen->pid_idx] = 0; 2653 2654 /* Format the buffer for direction flags */ 2655 dir_flag_msk = BIT(ICE_FLG_PKT_DIR); 2656 2657 if (prof->dir == ICE_FLOW_RX) 2658 buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk; 2659 2660 if (range) { 2661 buf[prof->cfg.scen->rng_chk_idx] = range; 2662 /* Mark any unused range checkers as don't care */ 2663 dontcare[prof->cfg.scen->rng_chk_idx] = ~range; 2664 e->range_buf = range_buf; 2665 } else { 2666 ice_free(hw, range_buf); 2667 } 2668 2669 status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0, 2670 buf_sz); 2671 if (status) 2672 goto out; 2673 2674 e->entry = key; 2675 e->entry_sz = buf_sz * 2; 2676 2677 out: 2678 if (buf) 2679 ice_free(hw, buf); 2680 2681 if (dontcare) 2682 ice_free(hw, dontcare); 2683 2684 if (status && key) 2685 ice_free(hw, key); 2686 2687 if (status && range_buf) { 2688 ice_free(hw, range_buf); 2689 e->range_buf = NULL; 2690 } 2691 2692 if (status && e->acts) { 2693 ice_free(hw, e->acts); 2694 e->acts = NULL; 2695 e->acts_cnt = 0; 2696 } 2697 2698 if (status && cnt_alloc) 2699 ice_flow_acl_free_act_cntr(hw, acts, acts_cnt); 2700 2701 return status; 2702 } 2703 2704 /** 2705 * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches 2706 * the compared data. 2707 * @prof: pointer to flow profile 2708 * @e: pointer to the comparing flow entry 2709 * @do_chg_action: decide if we want to change the ACL action 2710 * @do_add_entry: decide if we want to add the new ACL entry 2711 * @do_rem_entry: decide if we want to remove the current ACL entry 2712 * 2713 * Find an ACL scenario entry that matches the compared data. In the same time, 2714 * this function also figure out: 2715 * a/ If we want to change the ACL action 2716 * b/ If we want to add the new ACL entry 2717 * c/ If we want to remove the current ACL entry 2718 */ 2719 static struct ice_flow_entry * 2720 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof, 2721 struct ice_flow_entry *e, bool *do_chg_action, 2722 bool *do_add_entry, bool *do_rem_entry) 2723 { 2724 struct ice_flow_entry *p, *return_entry = NULL; 2725 u8 i, j; 2726 2727 /* Check if: 2728 * a/ There exists an entry with same matching data, but different 2729 * priority, then we remove this existing ACL entry. Then, we 2730 * will add the new entry to the ACL scenario. 2731 * b/ There exists an entry with same matching data, priority, and 2732 * result action, then we do nothing 2733 * c/ There exists an entry with same matching data, priority, but 2734 * different, action, then do only change the action's entry. 2735 * d/ Else, we add this new entry to the ACL scenario. 2736 */ 2737 *do_chg_action = false; 2738 *do_add_entry = true; 2739 *do_rem_entry = false; 2740 LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) { 2741 if (memcmp(p->entry, e->entry, p->entry_sz)) 2742 continue; 2743 2744 /* From this point, we have the same matching_data. */ 2745 *do_add_entry = false; 2746 return_entry = p; 2747 2748 if (p->priority != e->priority) { 2749 /* matching data && !priority */ 2750 *do_add_entry = true; 2751 *do_rem_entry = true; 2752 break; 2753 } 2754 2755 /* From this point, we will have matching_data && priority */ 2756 if (p->acts_cnt != e->acts_cnt) 2757 *do_chg_action = true; 2758 for (i = 0; i < p->acts_cnt; i++) { 2759 bool found_not_match = false; 2760 2761 for (j = 0; j < e->acts_cnt; j++) 2762 if (memcmp(&p->acts[i], &e->acts[j], 2763 sizeof(struct ice_flow_action))) { 2764 found_not_match = true; 2765 break; 2766 } 2767 2768 if (found_not_match) { 2769 *do_chg_action = true; 2770 break; 2771 } 2772 } 2773 2774 /* (do_chg_action = true) means : 2775 * matching_data && priority && !result_action 2776 * (do_chg_action = false) means : 2777 * matching_data && priority && result_action 2778 */ 2779 break; 2780 } 2781 2782 return return_entry; 2783 } 2784 2785 /** 2786 * ice_flow_acl_convert_to_acl_prio - Convert to ACL priority 2787 * @p: flow priority 2788 */ 2789 static enum ice_acl_entry_prio 2790 ice_flow_acl_convert_to_acl_prio(enum ice_flow_priority p) 2791 { 2792 enum ice_acl_entry_prio acl_prio; 2793 2794 switch (p) { 2795 case ICE_FLOW_PRIO_LOW: 2796 acl_prio = ICE_ACL_PRIO_LOW; 2797 break; 2798 case ICE_FLOW_PRIO_NORMAL: 2799 acl_prio = ICE_ACL_PRIO_NORMAL; 2800 break; 2801 case ICE_FLOW_PRIO_HIGH: 2802 acl_prio = ICE_ACL_PRIO_HIGH; 2803 break; 2804 default: 2805 acl_prio = ICE_ACL_PRIO_NORMAL; 2806 break; 2807 } 2808 2809 return acl_prio; 2810 } 2811 2812 /** 2813 * ice_flow_acl_union_rng_chk - Perform union operation between two 2814 * range-range checker buffers 2815 * @dst_buf: pointer to destination range checker buffer 2816 * @src_buf: pointer to source range checker buffer 2817 * 2818 * For this function, we do the union between dst_buf and src_buf 2819 * range checker buffer, and we will save the result back to dst_buf 2820 */ 2821 static enum ice_status 2822 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf, 2823 struct ice_aqc_acl_profile_ranges *src_buf) 2824 { 2825 u8 i, j; 2826 2827 if (!dst_buf || !src_buf) 2828 return ICE_ERR_BAD_PTR; 2829 2830 for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) { 2831 struct ice_acl_rng_data *cfg_data = NULL, *in_data; 2832 bool will_populate = false; 2833 2834 in_data = &src_buf->checker_cfg[i]; 2835 2836 if (!in_data->mask) 2837 break; 2838 2839 for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) { 2840 cfg_data = &dst_buf->checker_cfg[j]; 2841 2842 if (!cfg_data->mask || 2843 !memcmp(cfg_data, in_data, 2844 sizeof(struct ice_acl_rng_data))) { 2845 will_populate = true; 2846 break; 2847 } 2848 } 2849 2850 if (will_populate) { 2851 ice_memcpy(cfg_data, in_data, 2852 sizeof(struct ice_acl_rng_data), 2853 ICE_NONDMA_TO_NONDMA); 2854 } else { 2855 /* No available slot left to program range checker */ 2856 return ICE_ERR_MAX_LIMIT; 2857 } 2858 } 2859 2860 return ICE_SUCCESS; 2861 } 2862 2863 /** 2864 * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync 2865 * @hw: pointer to the hardware structure 2866 * @prof: pointer to flow profile 2867 * @entry: double pointer to the flow entry 2868 * 2869 * For this function, we will look at the current added entries in the 2870 * corresponding ACL scenario. Then, we will perform matching logic to 2871 * see if we want to add/modify/do nothing with this new entry. 2872 */ 2873 static enum ice_status 2874 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof, 2875 struct ice_flow_entry **entry) 2876 { 2877 bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk; 2878 struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf; 2879 struct ice_acl_act_entry *acts = NULL; 2880 struct ice_flow_entry *exist; 2881 enum ice_status status = ICE_SUCCESS; 2882 struct ice_flow_entry *e; 2883 u8 i; 2884 2885 if (!entry || !(*entry) || !prof) 2886 return ICE_ERR_BAD_PTR; 2887 2888 e = *entry; 2889 2890 do_chg_rng_chk = false; 2891 if (e->range_buf) { 2892 u8 prof_id = 0; 2893 2894 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, 2895 &prof_id); 2896 if (status) 2897 return status; 2898 2899 /* Query the current range-checker value in FW */ 2900 status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf, 2901 NULL); 2902 if (status) 2903 return status; 2904 ice_memcpy(&cfg_rng_buf, &query_rng_buf, 2905 sizeof(struct ice_aqc_acl_profile_ranges), 2906 ICE_NONDMA_TO_NONDMA); 2907 2908 /* Generate the new range-checker value */ 2909 status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf); 2910 if (status) 2911 return status; 2912 2913 /* Reconfigure the range check if the buffer is changed. */ 2914 do_chg_rng_chk = false; 2915 if (memcmp(&query_rng_buf, &cfg_rng_buf, 2916 sizeof(struct ice_aqc_acl_profile_ranges))) { 2917 status = ice_prog_acl_prof_ranges(hw, prof_id, 2918 &cfg_rng_buf, NULL); 2919 if (status) 2920 return status; 2921 2922 do_chg_rng_chk = true; 2923 } 2924 } 2925 2926 /* Figure out if we want to (change the ACL action) and/or 2927 * (Add the new ACL entry) and/or (Remove the current ACL entry) 2928 */ 2929 exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action, 2930 &do_add_entry, &do_rem_entry); 2931 if (do_rem_entry) { 2932 status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist); 2933 if (status) 2934 return status; 2935 } 2936 2937 /* Prepare the result action buffer */ 2938 acts = (struct ice_acl_act_entry *) 2939 ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry)); 2940 if (!acts) 2941 return ICE_ERR_NO_MEMORY; 2942 2943 for (i = 0; i < e->acts_cnt; i++) 2944 ice_memcpy(&acts[i], &e->acts[i].data.acl_act, 2945 sizeof(struct ice_acl_act_entry), 2946 ICE_NONDMA_TO_NONDMA); 2947 2948 if (do_add_entry) { 2949 enum ice_acl_entry_prio prio; 2950 u8 *keys, *inverts; 2951 u16 entry_idx; 2952 2953 keys = (u8 *)e->entry; 2954 inverts = keys + (e->entry_sz / 2); 2955 prio = ice_flow_acl_convert_to_acl_prio(e->priority); 2956 2957 status = ice_acl_add_entry(hw, prof->cfg.scen, prio, keys, 2958 inverts, acts, e->acts_cnt, 2959 &entry_idx); 2960 if (status) 2961 goto out; 2962 2963 e->scen_entry_idx = entry_idx; 2964 LIST_ADD(&e->l_entry, &prof->entries); 2965 } else { 2966 if (do_chg_action) { 2967 /* For the action memory info, update the SW's copy of 2968 * exist entry with e's action memory info 2969 */ 2970 ice_free(hw, exist->acts); 2971 exist->acts_cnt = e->acts_cnt; 2972 exist->acts = (struct ice_flow_action *) 2973 ice_calloc(hw, exist->acts_cnt, 2974 sizeof(struct ice_flow_action)); 2975 if (!exist->acts) { 2976 status = ICE_ERR_NO_MEMORY; 2977 goto out; 2978 } 2979 2980 ice_memcpy(exist->acts, e->acts, 2981 sizeof(struct ice_flow_action) * e->acts_cnt, 2982 ICE_NONDMA_TO_NONDMA); 2983 2984 status = ice_acl_prog_act(hw, prof->cfg.scen, acts, 2985 e->acts_cnt, 2986 exist->scen_entry_idx); 2987 if (status) 2988 goto out; 2989 } 2990 2991 if (do_chg_rng_chk) { 2992 /* In this case, we want to update the range checker 2993 * information of the exist entry 2994 */ 2995 status = ice_flow_acl_union_rng_chk(exist->range_buf, 2996 e->range_buf); 2997 if (status) 2998 goto out; 2999 } 3000 3001 /* As we don't add the new entry to our SW DB, deallocate its 3002 * memories, and return the exist entry to the caller 3003 */ 3004 ice_dealloc_flow_entry(hw, e); 3005 *(entry) = exist; 3006 } 3007 out: 3008 ice_free(hw, acts); 3009 3010 return status; 3011 } 3012 3013 /** 3014 * ice_flow_acl_add_scen_entry - Add entry to ACL scenario 3015 * @hw: pointer to the hardware structure 3016 * @prof: pointer to flow profile 3017 * @e: double pointer to the flow entry 3018 */ 3019 static enum ice_status 3020 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof, 3021 struct ice_flow_entry **e) 3022 { 3023 enum ice_status status; 3024 3025 ice_acquire_lock(&prof->entries_lock); 3026 status = ice_flow_acl_add_scen_entry_sync(hw, prof, e); 3027 ice_release_lock(&prof->entries_lock); 3028 3029 return status; 3030 } 3031 3032 /** 3033 * ice_flow_add_entry - Add a flow entry 3034 * @hw: pointer to the HW struct 3035 * @blk: classification stage 3036 * @prof_id: ID of the profile to add a new flow entry to 3037 * @entry_id: unique ID to identify this flow entry 3038 * @vsi_handle: software VSI handle for the flow entry 3039 * @prio: priority of the flow entry 3040 * @data: pointer to a data buffer containing flow entry's match values/masks 3041 * @acts: arrays of actions to be performed on a match 3042 * @acts_cnt: number of actions 3043 * @entry_h: pointer to buffer that receives the new flow entry's handle 3044 */ 3045 enum ice_status 3046 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 3047 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, 3048 void *data, struct ice_flow_action *acts, u8 acts_cnt, 3049 u64 *entry_h) 3050 { 3051 struct ice_flow_entry *e = NULL; 3052 struct ice_flow_prof *prof; 3053 enum ice_status status = ICE_SUCCESS; 3054 3055 /* ACL entries must indicate an action */ 3056 if (blk == ICE_BLK_ACL && (!acts || !acts_cnt)) 3057 return ICE_ERR_PARAM; 3058 3059 /* No flow entry data is expected for RSS */ 3060 if (!entry_h || (!data && blk != ICE_BLK_RSS)) 3061 return ICE_ERR_BAD_PTR; 3062 3063 if (!ice_is_vsi_valid(hw, vsi_handle)) 3064 return ICE_ERR_PARAM; 3065 3066 ice_acquire_lock(&hw->fl_profs_locks[blk]); 3067 3068 prof = ice_flow_find_prof_id(hw, blk, prof_id); 3069 if (!prof) { 3070 status = ICE_ERR_DOES_NOT_EXIST; 3071 } else { 3072 /* Allocate memory for the entry being added and associate 3073 * the VSI to the found flow profile 3074 */ 3075 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e)); 3076 if (!e) 3077 status = ICE_ERR_NO_MEMORY; 3078 else 3079 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 3080 } 3081 3082 ice_release_lock(&hw->fl_profs_locks[blk]); 3083 if (status) 3084 goto out; 3085 3086 e->id = entry_id; 3087 e->vsi_handle = vsi_handle; 3088 e->prof = prof; 3089 e->priority = prio; 3090 3091 switch (blk) { 3092 case ICE_BLK_FD: 3093 case ICE_BLK_RSS: 3094 break; 3095 case ICE_BLK_ACL: 3096 /* ACL will handle the entry management */ 3097 status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts, 3098 acts_cnt); 3099 if (status) 3100 goto out; 3101 3102 status = ice_flow_acl_add_scen_entry(hw, prof, &e); 3103 if (status) 3104 goto out; 3105 3106 break; 3107 default: 3108 status = ICE_ERR_NOT_IMPL; 3109 goto out; 3110 } 3111 3112 if (blk != ICE_BLK_ACL) { 3113 /* ACL will handle the entry management */ 3114 ice_acquire_lock(&prof->entries_lock); 3115 LIST_ADD(&e->l_entry, &prof->entries); 3116 ice_release_lock(&prof->entries_lock); 3117 } 3118 3119 *entry_h = ICE_FLOW_ENTRY_HNDL(e); 3120 3121 out: 3122 if (status && e) { 3123 if (e->entry) 3124 ice_free(hw, e->entry); 3125 ice_free(hw, e); 3126 } 3127 3128 return status; 3129 } 3130 3131 /** 3132 * ice_flow_rem_entry - Remove a flow entry 3133 * @hw: pointer to the HW struct 3134 * @blk: classification stage 3135 * @entry_h: handle to the flow entry to be removed 3136 */ 3137 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, 3138 u64 entry_h) 3139 { 3140 struct ice_flow_entry *entry; 3141 struct ice_flow_prof *prof; 3142 enum ice_status status = ICE_SUCCESS; 3143 3144 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) 3145 return ICE_ERR_PARAM; 3146 3147 entry = ICE_FLOW_ENTRY_PTR((intptr_t)entry_h); 3148 3149 /* Retain the pointer to the flow profile as the entry will be freed */ 3150 prof = entry->prof; 3151 3152 if (prof) { 3153 ice_acquire_lock(&prof->entries_lock); 3154 status = ice_flow_rem_entry_sync(hw, blk, entry); 3155 ice_release_lock(&prof->entries_lock); 3156 } 3157 3158 return status; 3159 } 3160 3161 /** 3162 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 3163 * @seg: packet segment the field being set belongs to 3164 * @fld: field to be set 3165 * @field_type: type of the field 3166 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3167 * entry's input buffer 3168 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 3169 * input buffer 3170 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 3171 * entry's input buffer 3172 * 3173 * This helper function stores information of a field being matched, including 3174 * the type of the field and the locations of the value to match, the mask, and 3175 * the upper-bound value in the start of the input buffer for a flow entry. 3176 * This function should only be used for fixed-size data structures. 3177 * 3178 * This function also opportunistically determines the protocol headers to be 3179 * present based on the fields being set. Some fields cannot be used alone to 3180 * determine the protocol headers present. Sometimes, fields for particular 3181 * protocol headers are not matched. In those cases, the protocol headers 3182 * must be explicitly set. 3183 */ 3184 static void 3185 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3186 enum ice_flow_fld_match_type field_type, u16 val_loc, 3187 u16 mask_loc, u16 last_loc) 3188 { 3189 u64 bit = BIT_ULL(fld); 3190 3191 seg->match |= bit; 3192 if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 3193 seg->range |= bit; 3194 3195 seg->fields[fld].type = field_type; 3196 seg->fields[fld].src.val = val_loc; 3197 seg->fields[fld].src.mask = mask_loc; 3198 seg->fields[fld].src.last = last_loc; 3199 3200 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 3201 } 3202 3203 /** 3204 * ice_flow_set_fld - specifies locations of field from entry's input buffer 3205 * @seg: packet segment the field being set belongs to 3206 * @fld: field to be set 3207 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3208 * entry's input buffer 3209 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 3210 * input buffer 3211 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 3212 * entry's input buffer 3213 * @range: indicate if field being matched is to be in a range 3214 * 3215 * This function specifies the locations, in the form of byte offsets from the 3216 * start of the input buffer for a flow entry, from where the value to match, 3217 * the mask value, and upper value can be extracted. These locations are then 3218 * stored in the flow profile. When adding a flow entry associated with the 3219 * flow profile, these locations will be used to quickly extract the values and 3220 * create the content of a match entry. This function should only be used for 3221 * fixed-size data structures. 3222 */ 3223 void 3224 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3225 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 3226 { 3227 enum ice_flow_fld_match_type t = range ? 3228 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 3229 3230 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 3231 } 3232 3233 /** 3234 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 3235 * @seg: packet segment the field being set belongs to 3236 * @fld: field to be set 3237 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 3238 * entry's input buffer 3239 * @pref_loc: location of prefix value from entry's input buffer 3240 * @pref_sz: size of the location holding the prefix value 3241 * 3242 * This function specifies the locations, in the form of byte offsets from the 3243 * start of the input buffer for a flow entry, from where the value to match 3244 * and the IPv4 prefix value can be extracted. These locations are then stored 3245 * in the flow profile. When adding flow entries to the associated flow profile, 3246 * these locations can be used to quickly extract the values to create the 3247 * content of a match entry. This function should only be used for fixed-size 3248 * data structures. 3249 */ 3250 void 3251 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 3252 u16 val_loc, u16 pref_loc, u8 pref_sz) 3253 { 3254 /* For this type of field, the "mask" location is for the prefix value's 3255 * location and the "last" location is for the size of the location of 3256 * the prefix value. 3257 */ 3258 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 3259 pref_loc, (u16)pref_sz); 3260 } 3261 3262 /** 3263 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf 3264 * @seg: packet segment the field being set belongs to 3265 * @off: offset of the raw field from the beginning of the segment in bytes 3266 * @len: length of the raw pattern to be matched 3267 * @val_loc: location of the value to match from entry's input buffer 3268 * @mask_loc: location of mask value from entry's input buffer 3269 * 3270 * This function specifies the offset of the raw field to be match from the 3271 * beginning of the specified packet segment, and the locations, in the form of 3272 * byte offsets from the start of the input buffer for a flow entry, from where 3273 * the value to match and the mask value to be extracted. These locations are 3274 * then stored in the flow profile. When adding flow entries to the associated 3275 * flow profile, these locations can be used to quickly extract the values to 3276 * create the content of a match entry. This function should only be used for 3277 * fixed-size data structures. 3278 */ 3279 void 3280 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, 3281 u16 val_loc, u16 mask_loc) 3282 { 3283 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { 3284 seg->raws[seg->raws_cnt].off = off; 3285 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; 3286 seg->raws[seg->raws_cnt].info.src.val = val_loc; 3287 seg->raws[seg->raws_cnt].info.src.mask = mask_loc; 3288 /* The "last" field is used to store the length of the field */ 3289 seg->raws[seg->raws_cnt].info.src.last = len; 3290 } 3291 3292 /* Overflows of "raws" will be handled as an error condition later in 3293 * the flow when this information is processed. 3294 */ 3295 seg->raws_cnt++; 3296 } 3297 3298 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \ 3299 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 3300 3301 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 3302 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 3303 3304 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 3305 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 3306 3307 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 3308 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ 3309 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 3310 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 3311 3312 /** 3313 * ice_flow_set_rss_seg_info - setup packet segments for RSS 3314 * @segs: pointer to the flow field segment(s) 3315 * @seg_cnt: segment count 3316 * @cfg: configure parameters 3317 * 3318 * Helper function to extract fields from hash bitmap and use flow 3319 * header value to set flow field segment for further use in flow 3320 * profile entry or removal. 3321 */ 3322 static enum ice_status 3323 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, 3324 const struct ice_rss_hash_cfg *cfg) 3325 { 3326 struct ice_flow_seg_info *seg; 3327 u64 val; 3328 u8 i; 3329 3330 /* set inner most segment */ 3331 seg = &segs[seg_cnt - 1]; 3332 3333 ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds, 3334 ICE_FLOW_FIELD_IDX_MAX) 3335 ice_flow_set_fld(seg, (enum ice_flow_field)i, 3336 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 3337 ICE_FLOW_FLD_OFF_INVAL, false); 3338 3339 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); 3340 3341 /* set outer most header */ 3342 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) 3343 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 3344 ICE_FLOW_SEG_HDR_IPV_OTHER; 3345 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) 3346 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 3347 ICE_FLOW_SEG_HDR_IPV_OTHER; 3348 3349 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & 3350 ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) 3351 return ICE_ERR_PARAM; 3352 3353 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 3354 if (val && !ice_is_pow2(val)) 3355 return ICE_ERR_CFG; 3356 3357 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 3358 if (val && !ice_is_pow2(val)) 3359 return ICE_ERR_CFG; 3360 3361 return ICE_SUCCESS; 3362 } 3363 3364 /** 3365 * ice_rem_vsi_rss_list - remove VSI from RSS list 3366 * @hw: pointer to the hardware structure 3367 * @vsi_handle: software VSI handle 3368 * 3369 * Remove the VSI from all RSS configurations in the list. 3370 */ 3371 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 3372 { 3373 struct ice_rss_cfg *r, *tmp; 3374 3375 if (LIST_EMPTY(&hw->rss_list_head)) 3376 return; 3377 3378 ice_acquire_lock(&hw->rss_locks); 3379 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 3380 ice_rss_cfg, l_entry) 3381 if (ice_test_and_clear_bit(vsi_handle, r->vsis)) 3382 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 3383 LIST_DEL(&r->l_entry); 3384 ice_free(hw, r); 3385 } 3386 ice_release_lock(&hw->rss_locks); 3387 } 3388 3389 /** 3390 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 3391 * @hw: pointer to the hardware structure 3392 * @vsi_handle: software VSI handle 3393 * 3394 * This function will iterate through all flow profiles and disassociate 3395 * the VSI from that profile. If the flow profile has no VSIs it will 3396 * be removed. 3397 */ 3398 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 3399 { 3400 const enum ice_block blk = ICE_BLK_RSS; 3401 struct ice_flow_prof *p, *t; 3402 enum ice_status status = ICE_SUCCESS; 3403 3404 if (!ice_is_vsi_valid(hw, vsi_handle)) 3405 return ICE_ERR_PARAM; 3406 3407 if (LIST_EMPTY(&hw->fl_profs[blk])) 3408 return ICE_SUCCESS; 3409 3410 ice_acquire_lock(&hw->rss_locks); 3411 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 3412 l_entry) 3413 if (ice_is_bit_set(p->vsis, vsi_handle)) { 3414 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 3415 if (status) 3416 break; 3417 3418 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 3419 status = ice_flow_rem_prof(hw, blk, p->id); 3420 if (status) 3421 break; 3422 } 3423 } 3424 ice_release_lock(&hw->rss_locks); 3425 3426 return status; 3427 } 3428 3429 /** 3430 * ice_get_rss_hdr_type - get a RSS profile's header type 3431 * @prof: RSS flow profile 3432 */ 3433 static enum ice_rss_cfg_hdr_type 3434 ice_get_rss_hdr_type(struct ice_flow_prof *prof) 3435 { 3436 enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS; 3437 3438 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { 3439 hdr_type = ICE_RSS_OUTER_HEADERS; 3440 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { 3441 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE) 3442 hdr_type = ICE_RSS_INNER_HEADERS; 3443 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4) 3444 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; 3445 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6) 3446 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; 3447 } 3448 3449 return hdr_type; 3450 } 3451 3452 /** 3453 * ice_rem_rss_list - remove RSS configuration from list 3454 * @hw: pointer to the hardware structure 3455 * @vsi_handle: software VSI handle 3456 * @prof: pointer to flow profile 3457 * 3458 * Assumption: lock has already been acquired for RSS list 3459 */ 3460 static void 3461 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 3462 { 3463 enum ice_rss_cfg_hdr_type hdr_type; 3464 struct ice_rss_cfg *r, *tmp; 3465 3466 /* Search for RSS hash fields associated to the VSI that match the 3467 * hash configurations associated to the flow profile. If found 3468 * remove from the RSS entry list of the VSI context and delete entry. 3469 */ 3470 hdr_type = ice_get_rss_hdr_type(prof); 3471 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 3472 ice_rss_cfg, l_entry) 3473 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && 3474 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 3475 r->hash.hdr_type == hdr_type) { 3476 ice_clear_bit(vsi_handle, r->vsis); 3477 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 3478 LIST_DEL(&r->l_entry); 3479 ice_free(hw, r); 3480 } 3481 return; 3482 } 3483 } 3484 3485 /** 3486 * ice_add_rss_list - add RSS configuration to list 3487 * @hw: pointer to the hardware structure 3488 * @vsi_handle: software VSI handle 3489 * @prof: pointer to flow profile 3490 * 3491 * Assumption: lock has already been acquired for RSS list 3492 */ 3493 static enum ice_status 3494 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 3495 { 3496 enum ice_rss_cfg_hdr_type hdr_type; 3497 struct ice_rss_cfg *r, *rss_cfg; 3498 3499 hdr_type = ice_get_rss_hdr_type(prof); 3500 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3501 ice_rss_cfg, l_entry) 3502 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && 3503 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 3504 r->hash.hdr_type == hdr_type) { 3505 ice_set_bit(vsi_handle, r->vsis); 3506 return ICE_SUCCESS; 3507 } 3508 3509 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 3510 if (!rss_cfg) 3511 return ICE_ERR_NO_MEMORY; 3512 3513 rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match; 3514 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; 3515 rss_cfg->hash.hdr_type = hdr_type; 3516 rss_cfg->hash.symm = prof->cfg.symm; 3517 ice_set_bit(vsi_handle, rss_cfg->vsis); 3518 3519 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); 3520 3521 return ICE_SUCCESS; 3522 } 3523 3524 #define ICE_FLOW_PROF_HASH_S 0 3525 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 3526 #define ICE_FLOW_PROF_HDR_S 32 3527 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 3528 #define ICE_FLOW_PROF_ENCAP_S 62 3529 #define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S) 3530 3531 /* Flow profile ID format: 3532 * [0:31] - Packet match fields 3533 * [32:61] - Protocol header 3534 * [62:63] - Encapsulation flag: 3535 * 0 if non-tunneled 3536 * 1 if tunneled 3537 * 2 for tunneled with outer ipv4 3538 * 3 for tunneled with outer ipv6 3539 */ 3540 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ 3541 ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 3542 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 3543 (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M))) 3544 3545 static void 3546 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst) 3547 { 3548 u32 s = ((src % 4) << 3); /* byte shift */ 3549 u32 v = dst | 0x80; /* value to program */ 3550 u8 i = src / 4; /* register index */ 3551 u32 reg; 3552 3553 reg = rd32(hw, GLQF_HSYMM(prof_id, i)); 3554 reg = (reg & ~(0xff << s)) | (v << s); 3555 wr32(hw, GLQF_HSYMM(prof_id, i), reg); 3556 } 3557 3558 static void 3559 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len) 3560 { 3561 int fv_last_word = 3562 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1; 3563 int i; 3564 3565 for (i = 0; i < len; i++) { 3566 ice_rss_config_xor_word(hw, prof_id, 3567 /* Yes, field vector in GLQF_HSYMM and 3568 * GLQF_HINSET is inversed! 3569 */ 3570 fv_last_word - (src + i), 3571 fv_last_word - (dst + i)); 3572 ice_rss_config_xor_word(hw, prof_id, 3573 fv_last_word - (dst + i), 3574 fv_last_word - (src + i)); 3575 } 3576 } 3577 3578 static void 3579 ice_rss_update_symm(struct ice_hw *hw, 3580 struct ice_flow_prof *prof) 3581 { 3582 struct ice_prof_map *map; 3583 u8 prof_id, m; 3584 3585 ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); 3586 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id); 3587 if (map) 3588 prof_id = map->prof_id; 3589 ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); 3590 if (!map) 3591 return; 3592 /* clear to default */ 3593 for (m = 0; m < 6; m++) 3594 wr32(hw, GLQF_HSYMM(prof_id, m), 0); 3595 if (prof->cfg.symm) { 3596 struct ice_flow_seg_info *seg = 3597 &prof->segs[prof->segs_cnt - 1]; 3598 3599 struct ice_flow_seg_xtrct *ipv4_src = 3600 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct; 3601 struct ice_flow_seg_xtrct *ipv4_dst = 3602 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct; 3603 struct ice_flow_seg_xtrct *ipv6_src = 3604 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct; 3605 struct ice_flow_seg_xtrct *ipv6_dst = 3606 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct; 3607 3608 struct ice_flow_seg_xtrct *tcp_src = 3609 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct; 3610 struct ice_flow_seg_xtrct *tcp_dst = 3611 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct; 3612 3613 struct ice_flow_seg_xtrct *udp_src = 3614 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct; 3615 struct ice_flow_seg_xtrct *udp_dst = 3616 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct; 3617 3618 struct ice_flow_seg_xtrct *sctp_src = 3619 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct; 3620 struct ice_flow_seg_xtrct *sctp_dst = 3621 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct; 3622 3623 /* xor IPv4 */ 3624 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0) 3625 ice_rss_config_xor(hw, prof_id, 3626 ipv4_src->idx, ipv4_dst->idx, 2); 3627 3628 /* xor IPv6 */ 3629 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0) 3630 ice_rss_config_xor(hw, prof_id, 3631 ipv6_src->idx, ipv6_dst->idx, 8); 3632 3633 /* xor TCP */ 3634 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0) 3635 ice_rss_config_xor(hw, prof_id, 3636 tcp_src->idx, tcp_dst->idx, 1); 3637 3638 /* xor UDP */ 3639 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0) 3640 ice_rss_config_xor(hw, prof_id, 3641 udp_src->idx, udp_dst->idx, 1); 3642 3643 /* xor SCTP */ 3644 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0) 3645 ice_rss_config_xor(hw, prof_id, 3646 sctp_src->idx, sctp_dst->idx, 1); 3647 } 3648 } 3649 3650 /** 3651 * ice_add_rss_cfg_sync - add an RSS configuration 3652 * @hw: pointer to the hardware structure 3653 * @vsi_handle: software VSI handle 3654 * @cfg: configure parameters 3655 * 3656 * Assumption: lock has already been acquired for RSS list 3657 */ 3658 static enum ice_status 3659 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 3660 const struct ice_rss_hash_cfg *cfg) 3661 { 3662 const enum ice_block blk = ICE_BLK_RSS; 3663 struct ice_flow_prof *prof = NULL; 3664 struct ice_flow_seg_info *segs; 3665 enum ice_status status; 3666 u8 segs_cnt; 3667 3668 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 3669 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; 3670 3671 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 3672 sizeof(*segs)); 3673 if (!segs) 3674 return ICE_ERR_NO_MEMORY; 3675 3676 /* Construct the packet segment info from the hashed fields */ 3677 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 3678 if (status) 3679 goto exit; 3680 3681 /* Search for a flow profile that has matching headers, hash fields 3682 * and has the input VSI associated to it. If found, no further 3683 * operations required and exit. 3684 */ 3685 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3686 vsi_handle, 3687 ICE_FLOW_FIND_PROF_CHK_FLDS | 3688 ICE_FLOW_FIND_PROF_CHK_VSI); 3689 if (prof) { 3690 if (prof->cfg.symm == cfg->symm) 3691 goto exit; 3692 prof->cfg.symm = cfg->symm; 3693 goto update_symm; 3694 } 3695 3696 /* Check if a flow profile exists with the same protocol headers and 3697 * associated with the input VSI. If so disassociate the VSI from 3698 * this profile. The VSI will be added to a new profile created with 3699 * the protocol header and new hash field configuration. 3700 */ 3701 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3702 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 3703 if (prof) { 3704 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 3705 if (!status) 3706 ice_rem_rss_list(hw, vsi_handle, prof); 3707 else 3708 goto exit; 3709 3710 /* Remove profile if it has no VSIs associated */ 3711 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 3712 status = ice_flow_rem_prof(hw, blk, prof->id); 3713 if (status) 3714 goto exit; 3715 } 3716 } 3717 3718 /* Search for a profile that has same match fields only. If this 3719 * exists then associate the VSI to this profile. 3720 */ 3721 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3722 vsi_handle, 3723 ICE_FLOW_FIND_PROF_CHK_FLDS); 3724 if (prof) { 3725 if (prof->cfg.symm == cfg->symm) { 3726 status = ice_flow_assoc_prof(hw, blk, prof, 3727 vsi_handle); 3728 if (!status) 3729 status = ice_add_rss_list(hw, vsi_handle, 3730 prof); 3731 } else { 3732 /* if a profile exist but with different symmetric 3733 * requirement, just return error. 3734 */ 3735 status = ICE_ERR_NOT_SUPPORTED; 3736 } 3737 goto exit; 3738 } 3739 3740 /* Create a new flow profile with generated profile and packet 3741 * segment information. 3742 */ 3743 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 3744 ICE_FLOW_GEN_PROFID(cfg->hash_flds, 3745 segs[segs_cnt - 1].hdrs, 3746 cfg->hdr_type), 3747 segs, segs_cnt, NULL, 0, &prof); 3748 if (status) 3749 goto exit; 3750 3751 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 3752 /* If association to a new flow profile failed then this profile can 3753 * be removed. 3754 */ 3755 if (status) { 3756 ice_flow_rem_prof(hw, blk, prof->id); 3757 goto exit; 3758 } 3759 3760 status = ice_add_rss_list(hw, vsi_handle, prof); 3761 3762 prof->cfg.symm = cfg->symm; 3763 update_symm: 3764 ice_rss_update_symm(hw, prof); 3765 3766 exit: 3767 ice_free(hw, segs); 3768 return status; 3769 } 3770 3771 /** 3772 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 3773 * @hw: pointer to the hardware structure 3774 * @vsi_handle: software VSI handle 3775 * @cfg: configure parameters 3776 * 3777 * This function will generate a flow profile based on fields associated with 3778 * the input fields to hash on, the flow type and use the VSI number to add 3779 * a flow entry to the profile. 3780 */ 3781 enum ice_status 3782 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 3783 const struct ice_rss_hash_cfg *cfg) 3784 { 3785 struct ice_rss_hash_cfg local_cfg; 3786 enum ice_status status; 3787 3788 if (!ice_is_vsi_valid(hw, vsi_handle) || 3789 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || 3790 cfg->hash_flds == ICE_HASH_INVALID) 3791 return ICE_ERR_PARAM; 3792 3793 local_cfg = *cfg; 3794 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 3795 ice_acquire_lock(&hw->rss_locks); 3796 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3797 ice_release_lock(&hw->rss_locks); 3798 } else { 3799 ice_acquire_lock(&hw->rss_locks); 3800 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 3801 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3802 if (!status) { 3803 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 3804 status = ice_add_rss_cfg_sync(hw, vsi_handle, 3805 &local_cfg); 3806 } 3807 ice_release_lock(&hw->rss_locks); 3808 } 3809 3810 return status; 3811 } 3812 3813 /** 3814 * ice_rem_rss_cfg_sync - remove an existing RSS configuration 3815 * @hw: pointer to the hardware structure 3816 * @vsi_handle: software VSI handle 3817 * @cfg: configure parameters 3818 * 3819 * Assumption: lock has already been acquired for RSS list 3820 */ 3821 static enum ice_status 3822 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 3823 const struct ice_rss_hash_cfg *cfg) 3824 { 3825 const enum ice_block blk = ICE_BLK_RSS; 3826 struct ice_flow_seg_info *segs; 3827 struct ice_flow_prof *prof; 3828 enum ice_status status; 3829 u8 segs_cnt; 3830 3831 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 3832 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; 3833 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 3834 sizeof(*segs)); 3835 if (!segs) 3836 return ICE_ERR_NO_MEMORY; 3837 3838 /* Construct the packet segment info from the hashed fields */ 3839 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 3840 if (status) 3841 goto out; 3842 3843 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 3844 vsi_handle, 3845 ICE_FLOW_FIND_PROF_CHK_FLDS); 3846 if (!prof) { 3847 status = ICE_ERR_DOES_NOT_EXIST; 3848 goto out; 3849 } 3850 3851 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 3852 if (status) 3853 goto out; 3854 3855 /* Remove RSS configuration from VSI context before deleting 3856 * the flow profile. 3857 */ 3858 ice_rem_rss_list(hw, vsi_handle, prof); 3859 3860 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 3861 status = ice_flow_rem_prof(hw, blk, prof->id); 3862 3863 out: 3864 ice_free(hw, segs); 3865 return status; 3866 } 3867 3868 /** 3869 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 3870 * @hw: pointer to the hardware structure 3871 * @vsi_handle: software VSI handle 3872 * @cfg: configure parameters 3873 * 3874 * This function will lookup the flow profile based on the input 3875 * hash field bitmap, iterate through the profile entry list of 3876 * that profile and find entry associated with input VSI to be 3877 * removed. Calls are made to underlying flow apis which will in 3878 * turn build or update buffers for RSS XLT1 section. 3879 */ 3880 enum ice_status 3881 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 3882 const struct ice_rss_hash_cfg *cfg) 3883 { 3884 struct ice_rss_hash_cfg local_cfg; 3885 enum ice_status status; 3886 3887 if (!ice_is_vsi_valid(hw, vsi_handle) || 3888 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || 3889 cfg->hash_flds == ICE_HASH_INVALID) 3890 return ICE_ERR_PARAM; 3891 3892 ice_acquire_lock(&hw->rss_locks); 3893 local_cfg = *cfg; 3894 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 3895 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3896 } else { 3897 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 3898 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 3899 3900 if (!status) { 3901 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 3902 status = ice_rem_rss_cfg_sync(hw, vsi_handle, 3903 &local_cfg); 3904 } 3905 } 3906 ice_release_lock(&hw->rss_locks); 3907 3908 return status; 3909 } 3910 3911 /** 3912 * ice_replay_rss_cfg - replay RSS configurations associated with VSI 3913 * @hw: pointer to the hardware structure 3914 * @vsi_handle: software VSI handle 3915 */ 3916 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 3917 { 3918 enum ice_status status = ICE_SUCCESS; 3919 struct ice_rss_cfg *r; 3920 3921 if (!ice_is_vsi_valid(hw, vsi_handle)) 3922 return ICE_ERR_PARAM; 3923 3924 ice_acquire_lock(&hw->rss_locks); 3925 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3926 ice_rss_cfg, l_entry) { 3927 if (ice_is_bit_set(r->vsis, vsi_handle)) { 3928 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); 3929 if (status) 3930 break; 3931 } 3932 } 3933 ice_release_lock(&hw->rss_locks); 3934 3935 return status; 3936 } 3937 3938 /** 3939 * ice_get_rss_cfg - returns hashed fields for the given header types 3940 * @hw: pointer to the hardware structure 3941 * @vsi_handle: software VSI handle 3942 * @hdrs: protocol header type 3943 * 3944 * This function will return the match fields of the first instance of flow 3945 * profile having the given header types and containing input VSI 3946 */ 3947 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 3948 { 3949 u64 rss_hash = ICE_HASH_INVALID; 3950 struct ice_rss_cfg *r; 3951 3952 /* verify if the protocol header is non zero and VSI is valid */ 3953 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 3954 return ICE_HASH_INVALID; 3955 3956 ice_acquire_lock(&hw->rss_locks); 3957 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 3958 ice_rss_cfg, l_entry) 3959 if (ice_is_bit_set(r->vsis, vsi_handle) && 3960 r->hash.addl_hdrs == hdrs) { 3961 rss_hash = r->hash.hash_flds; 3962 break; 3963 } 3964 ice_release_lock(&hw->rss_locks); 3965 3966 return rss_hash; 3967 } 3968