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