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