1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2019 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 23 /* Protocol header fields are extracted at the word boundaries as word-sized 24 * values. Specify the displacement value of some non-word-aligned fields needed 25 * to compute the offset of words containing the fields in the corresponding 26 * protocol headers. Displacement values are expressed in number of bits. 27 */ 28 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4) 29 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * 8) 30 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * 8) 31 32 /* Describe properties of a protocol header field */ 33 struct ice_flow_field_info { 34 enum ice_flow_seg_hdr hdr; 35 s16 off; /* Offset from start of a protocol header, in bits */ 36 u16 size; /* Size of fields in bits */ 37 }; 38 39 /* Table containing properties of supported protocol header fields */ 40 static const 41 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 42 /* Ether */ 43 /* ICE_FLOW_FIELD_IDX_ETH_DA */ 44 { ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 }, 45 /* ICE_FLOW_FIELD_IDX_ETH_SA */ 46 { ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 }, 47 /* ICE_FLOW_FIELD_IDX_S_VLAN */ 48 { ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 }, 49 /* ICE_FLOW_FIELD_IDX_C_VLAN */ 50 { ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 }, 51 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 52 { ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 }, 53 /* IPv4 */ 54 /* ICE_FLOW_FIELD_IDX_IP_DSCP */ 55 { ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 }, 56 /* ICE_FLOW_FIELD_IDX_IP_TTL */ 57 { ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 }, 58 /* ICE_FLOW_FIELD_IDX_IP_PROT */ 59 { ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 }, 60 /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 61 { ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, 62 /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 63 { ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, 64 /* IPv6 */ 65 /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 66 { ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 }, 67 /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 68 { ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 }, 69 /* Transport */ 70 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 71 { ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 72 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 73 { ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 74 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 75 { ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 76 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 77 { ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 78 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 79 { ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 80 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 81 { ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, 82 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 83 { ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 }, 84 /* ARP */ 85 /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 86 { ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, 87 /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 88 { ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, 89 /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 90 { ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 }, 91 /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 92 { ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 }, 93 /* ICE_FLOW_FIELD_IDX_ARP_OP */ 94 { ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 }, 95 /* ICMP */ 96 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 97 { ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 }, 98 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 99 { ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 }, 100 /* GRE */ 101 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 102 { ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 }, 103 }; 104 105 /* Bitmaps indicating relevant packet types for a particular protocol header 106 * 107 * Packet types for packets with an Outer/First/Single MAC header 108 */ 109 static const u32 ice_ptypes_mac_ofos[] = { 110 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB, 111 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000, 112 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000, 113 0x00000000, 0x00000000, 0x00000000, 0x00000000, 114 0x00000000, 0x00000000, 0x00000000, 0x00000000, 115 0x00000000, 0x00000000, 0x00000000, 0x00000000, 116 0x00000000, 0x00000000, 0x00000000, 0x00000000, 117 0x00000000, 0x00000000, 0x00000000, 0x00000000, 118 }; 119 120 /* Packet types for packets with an Innermost/Last MAC VLAN header */ 121 static const u32 ice_ptypes_macvlan_il[] = { 122 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 123 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 124 0x00000000, 0x00000000, 0x00000000, 0x00000000, 125 0x00000000, 0x00000000, 0x00000000, 0x00000000, 126 0x00000000, 0x00000000, 0x00000000, 0x00000000, 127 0x00000000, 0x00000000, 0x00000000, 0x00000000, 128 0x00000000, 0x00000000, 0x00000000, 0x00000000, 129 0x00000000, 0x00000000, 0x00000000, 0x00000000, 130 }; 131 132 /* Packet types for packets with an Outer/First/Single IPv4 header */ 133 static const u32 ice_ptypes_ipv4_ofos[] = { 134 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000, 135 0x00000000, 0x00000000, 0x00000000, 0x00000000, 136 0x0003000F, 0x00000000, 0x00000000, 0x00000000, 137 0x00000000, 0x00000000, 0x00000000, 0x00000000, 138 0x00000000, 0x00000000, 0x00000000, 0x00000000, 139 0x00000000, 0x00000000, 0x00000000, 0x00000000, 140 0x00000000, 0x00000000, 0x00000000, 0x00000000, 141 0x00000000, 0x00000000, 0x00000000, 0x00000000, 142 }; 143 144 /* Packet types for packets with an Innermost/Last IPv4 header */ 145 static const u32 ice_ptypes_ipv4_il[] = { 146 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B, 147 0x0007700E, 0x00000000, 0x00000000, 0x00000000, 148 0x00000000, 0x00000000, 0x00000000, 0x00000000, 149 0x00000000, 0x00000000, 0x00000000, 0x00000000, 150 0x00000000, 0x00000000, 0x00000000, 0x00000000, 151 0x00000000, 0x00000000, 0x00000000, 0x00000000, 152 0x00000000, 0x00000000, 0x00000000, 0x00000000, 153 0x00000000, 0x00000000, 0x00000000, 0x00000000, 154 }; 155 156 /* Packet types for packets with an Outer/First/Single IPv6 header */ 157 static const u32 ice_ptypes_ipv6_ofos[] = { 158 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB, 159 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000, 160 0x00080F00, 0x00000000, 0x00000000, 0x00000000, 161 0x00000000, 0x00000000, 0x00000000, 0x00000000, 162 0x00000000, 0x00000000, 0x00000000, 0x00000000, 163 0x00000000, 0x00000000, 0x00000000, 0x00000000, 164 0x00000000, 0x00000000, 0x00000000, 0x00000000, 165 0x00000000, 0x00000000, 0x00000000, 0x00000000, 166 }; 167 168 /* Packet types for packets with an Innermost/Last IPv6 header */ 169 static const u32 ice_ptypes_ipv6_il[] = { 170 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000, 171 0x03B80770, 0x00000000, 0x00000000, 0x00000000, 172 0x00000000, 0x00000000, 0x00000000, 0x00000000, 173 0x00000000, 0x00000000, 0x00000000, 0x00000000, 174 0x00000000, 0x00000000, 0x00000000, 0x00000000, 175 0x00000000, 0x00000000, 0x00000000, 0x00000000, 176 0x00000000, 0x00000000, 0x00000000, 0x00000000, 177 0x00000000, 0x00000000, 0x00000000, 0x00000000, 178 }; 179 180 /* Packet types for packets with an Outermost/First ARP header */ 181 static const u32 ice_ptypes_arp_of[] = { 182 0x00000800, 0x00000000, 0x00000000, 0x00000000, 183 0x00000000, 0x00000000, 0x00000000, 0x00000000, 184 0x00000000, 0x00000000, 0x00000000, 0x00000000, 185 0x00000000, 0x00000000, 0x00000000, 0x00000000, 186 0x00000000, 0x00000000, 0x00000000, 0x00000000, 187 0x00000000, 0x00000000, 0x00000000, 0x00000000, 188 0x00000000, 0x00000000, 0x00000000, 0x00000000, 189 0x00000000, 0x00000000, 0x00000000, 0x00000000, 190 }; 191 192 /* Packet types for packets with an Outermost/First UDP header */ 193 static const u32 ice_ptypes_udp_of[] = { 194 0x81000000, 0x00000000, 0x04000000, 0x00000000, 195 0x00000000, 0x00000000, 0x00000000, 0x00000000, 196 0x00000000, 0x00000000, 0x00000000, 0x00000000, 197 0x00000000, 0x00000000, 0x00000000, 0x00000000, 198 0x00000000, 0x00000000, 0x00000000, 0x00000000, 199 0x00000000, 0x00000000, 0x00000000, 0x00000000, 200 0x00000000, 0x00000000, 0x00000000, 0x00000000, 201 0x00000000, 0x00000000, 0x00000000, 0x00000000, 202 }; 203 204 /* Packet types for packets with an Innermost/Last UDP header */ 205 static const u32 ice_ptypes_udp_il[] = { 206 0x80000000, 0x20204040, 0x00081010, 0x80810102, 207 0x00204040, 0x00000000, 0x00000000, 0x00000000, 208 0x00000000, 0x00000000, 0x00000000, 0x00000000, 209 0x00000000, 0x00000000, 0x00000000, 0x00000000, 210 0x00000000, 0x00000000, 0x00000000, 0x00000000, 211 0x00000000, 0x00000000, 0x00000000, 0x00000000, 212 0x00000000, 0x00000000, 0x00000000, 0x00000000, 213 0x00000000, 0x00000000, 0x00000000, 0x00000000, 214 }; 215 216 /* Packet types for packets with an Innermost/Last TCP header */ 217 static const u32 ice_ptypes_tcp_il[] = { 218 0x04000000, 0x80810102, 0x10204040, 0x42040408, 219 0x00810002, 0x00000000, 0x00000000, 0x00000000, 220 0x00000000, 0x00000000, 0x00000000, 0x00000000, 221 0x00000000, 0x00000000, 0x00000000, 0x00000000, 222 0x00000000, 0x00000000, 0x00000000, 0x00000000, 223 0x00000000, 0x00000000, 0x00000000, 0x00000000, 224 0x00000000, 0x00000000, 0x00000000, 0x00000000, 225 0x00000000, 0x00000000, 0x00000000, 0x00000000, 226 }; 227 228 /* Packet types for packets with an Innermost/Last SCTP header */ 229 static const u32 ice_ptypes_sctp_il[] = { 230 0x08000000, 0x01020204, 0x20408081, 0x04080810, 231 0x01020204, 0x00000000, 0x00000000, 0x00000000, 232 0x00000000, 0x00000000, 0x00000000, 0x00000000, 233 0x00000000, 0x00000000, 0x00000000, 0x00000000, 234 0x00000000, 0x00000000, 0x00000000, 0x00000000, 235 0x00000000, 0x00000000, 0x00000000, 0x00000000, 236 0x00000000, 0x00000000, 0x00000000, 0x00000000, 237 0x00000000, 0x00000000, 0x00000000, 0x00000000, 238 }; 239 240 /* Packet types for packets with an Outermost/First ICMP header */ 241 static const u32 ice_ptypes_icmp_of[] = { 242 0x10000000, 0x00000000, 0x00000000, 0x00000000, 243 0x00000000, 0x00000000, 0x00000000, 0x00000000, 244 0x00000000, 0x00000000, 0x00000000, 0x00000000, 245 0x00000000, 0x00000000, 0x00000000, 0x00000000, 246 0x00000000, 0x00000000, 0x00000000, 0x00000000, 247 0x00000000, 0x00000000, 0x00000000, 0x00000000, 248 0x00000000, 0x00000000, 0x00000000, 0x00000000, 249 0x00000000, 0x00000000, 0x00000000, 0x00000000, 250 }; 251 252 /* Packet types for packets with an Innermost/Last ICMP header */ 253 static const u32 ice_ptypes_icmp_il[] = { 254 0x00000000, 0x02040408, 0x40810102, 0x08101020, 255 0x02040408, 0x00000000, 0x00000000, 0x00000000, 256 0x00000000, 0x00000000, 0x00000000, 0x00000000, 257 0x00000000, 0x00000000, 0x00000000, 0x00000000, 258 0x00000000, 0x00000000, 0x00000000, 0x00000000, 259 0x00000000, 0x00000000, 0x00000000, 0x00000000, 260 0x00000000, 0x00000000, 0x00000000, 0x00000000, 261 0x00000000, 0x00000000, 0x00000000, 0x00000000, 262 }; 263 264 /* Packet types for packets with an Outermost/First GRE header */ 265 static const u32 ice_ptypes_gre_of[] = { 266 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000, 267 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000, 268 0x00000000, 0x00000000, 0x00000000, 0x00000000, 269 0x00000000, 0x00000000, 0x00000000, 0x00000000, 270 0x00000000, 0x00000000, 0x00000000, 0x00000000, 271 0x00000000, 0x00000000, 0x00000000, 0x00000000, 272 0x00000000, 0x00000000, 0x00000000, 0x00000000, 273 0x00000000, 0x00000000, 0x00000000, 0x00000000, 274 }; 275 276 /* Packet types for packets with an Innermost/Last MAC header */ 277 static const u32 ice_ptypes_mac_il[] = { 278 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000, 279 0x03BF7800, 0x00000000, 0x00000000, 0x00000000, 280 0x00000000, 0x00000000, 0x00000000, 0x00000000, 281 0x00000000, 0x00000000, 0x00000000, 0x00000000, 282 0x00000000, 0x00000000, 0x00000000, 0x00000000, 283 0x00000000, 0x00000000, 0x00000000, 0x00000000, 284 0x00000000, 0x00000000, 0x00000000, 0x00000000, 285 0x00000000, 0x00000000, 0x00000000, 0x00000000, 286 }; 287 288 /* Manage parameters and info. used during the creation of a flow profile */ 289 struct ice_flow_prof_params { 290 enum ice_block blk; 291 struct ice_flow_prof *prof; 292 293 u16 entry_length; /* # of bytes formatted entry will require */ 294 u8 es_cnt; 295 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 296 * This will give us the direction flags. 297 */ 298 struct ice_fv_word es[ICE_MAX_FV_WORDS]; 299 300 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX); 301 }; 302 303 /** 304 * ice_is_pow2 - check if integer value is a power of 2 305 * @val: unsigned integer to be validated 306 */ 307 static bool ice_is_pow2(u64 val) 308 { 309 return (val && !(val & (val - 1))); 310 } 311 312 #define ICE_FLOW_SEG_HDRS_L2_MASK \ 313 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) 314 #define ICE_FLOW_SEG_HDRS_L3_MASK \ 315 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) 316 #define ICE_FLOW_SEG_HDRS_L4_MASK \ 317 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 318 ICE_FLOW_SEG_HDR_SCTP) 319 320 /** 321 * ice_flow_val_hdrs - validates packet segments for valid protocol headers 322 * @segs: array of one or more packet segments that describe the flow 323 * @segs_cnt: number of packet segments provided 324 */ 325 static enum ice_status 326 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 327 { 328 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK | 329 ICE_FLOW_SEG_HDRS_L3_MASK | 330 ICE_FLOW_SEG_HDRS_L4_MASK); 331 u8 i; 332 333 for (i = 0; i < segs_cnt; i++) { 334 /* No header specified */ 335 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks)) 336 return ICE_ERR_PARAM; 337 338 /* Multiple L3 headers */ 339 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 340 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 341 return ICE_ERR_PARAM; 342 343 /* Multiple L4 headers */ 344 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 345 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 346 return ICE_ERR_PARAM; 347 } 348 349 return ICE_SUCCESS; 350 } 351 352 /* Sizes of fixed known protocol headers without header options */ 353 #define ICE_FLOW_PROT_HDR_SZ_MAC 14 354 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2) 355 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20 356 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40 357 #define ICE_FLOW_PROT_HDR_SZ_ARP 28 358 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8 359 #define ICE_FLOW_PROT_HDR_SZ_TCP 20 360 #define ICE_FLOW_PROT_HDR_SZ_UDP 8 361 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12 362 363 /** 364 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers 365 * @params: information about the flow to be processed 366 * @seg: index of packet segment whose header size is to be determined 367 */ 368 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg) 369 { 370 u16 sz; 371 372 /* L2 headers */ 373 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ? 374 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC; 375 376 /* L3 headers */ 377 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) 378 sz += ICE_FLOW_PROT_HDR_SZ_IPV4; 379 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) 380 sz += ICE_FLOW_PROT_HDR_SZ_IPV6; 381 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP) 382 sz += ICE_FLOW_PROT_HDR_SZ_ARP; 383 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK) 384 /* A L3 header is required if L4 is specified */ 385 return 0; 386 387 /* L4 headers */ 388 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP) 389 sz += ICE_FLOW_PROT_HDR_SZ_ICMP; 390 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP) 391 sz += ICE_FLOW_PROT_HDR_SZ_TCP; 392 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP) 393 sz += ICE_FLOW_PROT_HDR_SZ_UDP; 394 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP) 395 sz += ICE_FLOW_PROT_HDR_SZ_SCTP; 396 397 return sz; 398 } 399 400 /** 401 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 402 * @params: information about the flow to be processed 403 * 404 * This function identifies the packet types associated with the protocol 405 * headers being present in packet segments of the specified flow profile. 406 */ 407 static enum ice_status 408 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 409 { 410 struct ice_flow_prof *prof; 411 u8 i; 412 413 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes), 414 ICE_NONDMA_MEM); 415 416 prof = params->prof; 417 418 for (i = 0; i < params->prof->segs_cnt; i++) { 419 const ice_bitmap_t *src; 420 u32 hdrs; 421 422 if (i > 0 && (i + 1) < prof->segs_cnt) 423 continue; 424 425 hdrs = prof->segs[i].hdrs; 426 427 if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 428 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos : 429 (const ice_bitmap_t *)ice_ptypes_mac_il; 430 ice_and_bitmap(params->ptypes, params->ptypes, src, 431 ICE_FLOW_PTYPE_MAX); 432 hdrs &= ~ICE_FLOW_SEG_HDR_ETH; 433 } 434 435 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 436 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; 437 ice_and_bitmap(params->ptypes, params->ptypes, src, 438 ICE_FLOW_PTYPE_MAX); 439 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN; 440 } 441 442 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 443 ice_and_bitmap(params->ptypes, params->ptypes, 444 (const ice_bitmap_t *)ice_ptypes_arp_of, 445 ICE_FLOW_PTYPE_MAX); 446 hdrs &= ~ICE_FLOW_SEG_HDR_ARP; 447 } 448 449 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 450 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos : 451 (const ice_bitmap_t *)ice_ptypes_ipv4_il; 452 ice_and_bitmap(params->ptypes, params->ptypes, src, 453 ICE_FLOW_PTYPE_MAX); 454 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4; 455 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 456 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : 457 (const ice_bitmap_t *)ice_ptypes_ipv6_il; 458 ice_and_bitmap(params->ptypes, params->ptypes, src, 459 ICE_FLOW_PTYPE_MAX); 460 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6; 461 } 462 463 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 464 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of : 465 (const ice_bitmap_t *)ice_ptypes_icmp_il; 466 ice_and_bitmap(params->ptypes, params->ptypes, src, 467 ICE_FLOW_PTYPE_MAX); 468 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP; 469 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 470 src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of : 471 (const ice_bitmap_t *)ice_ptypes_udp_il; 472 ice_and_bitmap(params->ptypes, params->ptypes, src, 473 ICE_FLOW_PTYPE_MAX); 474 hdrs &= ~ICE_FLOW_SEG_HDR_UDP; 475 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 476 ice_and_bitmap(params->ptypes, params->ptypes, 477 (const ice_bitmap_t *)ice_ptypes_tcp_il, 478 ICE_FLOW_PTYPE_MAX); 479 hdrs &= ~ICE_FLOW_SEG_HDR_TCP; 480 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 481 src = (const ice_bitmap_t *)ice_ptypes_sctp_il; 482 ice_and_bitmap(params->ptypes, params->ptypes, src, 483 ICE_FLOW_PTYPE_MAX); 484 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP; 485 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 486 if (!i) { 487 src = (const ice_bitmap_t *)ice_ptypes_gre_of; 488 ice_and_bitmap(params->ptypes, params->ptypes, 489 src, ICE_FLOW_PTYPE_MAX); 490 } 491 hdrs &= ~ICE_FLOW_SEG_HDR_GRE; 492 } 493 } 494 495 return ICE_SUCCESS; 496 } 497 498 /** 499 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 500 * @hw: pointer to the HW struct 501 * @params: information about the flow to be processed 502 * @seg: packet segment index of the field to be extracted 503 * @fld: ID of field to be extracted 504 * 505 * This function determines the protocol ID, offset, and size of the given 506 * field. It then allocates one or more extraction sequence entries for the 507 * given field, and fill the entries with protocol ID and offset information. 508 */ 509 static enum ice_status 510 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 511 u8 seg, enum ice_flow_field fld) 512 { 513 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 514 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 515 u8 fv_words = hw->blk[params->blk].es.fvw; 516 struct ice_flow_fld_info *flds; 517 u16 cnt, ese_bits, i; 518 s16 adj = 0; 519 u16 off; 520 521 flds = params->prof->segs[seg].fields; 522 523 switch (fld) { 524 case ICE_FLOW_FIELD_IDX_ETH_DA: 525 case ICE_FLOW_FIELD_IDX_ETH_SA: 526 case ICE_FLOW_FIELD_IDX_S_VLAN: 527 case ICE_FLOW_FIELD_IDX_C_VLAN: 528 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 529 break; 530 case ICE_FLOW_FIELD_IDX_ETH_TYPE: 531 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 532 break; 533 case ICE_FLOW_FIELD_IDX_IP_DSCP: 534 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) 535 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP; 536 /* Fall through */ 537 case ICE_FLOW_FIELD_IDX_IP_TTL: 538 case ICE_FLOW_FIELD_IDX_IP_PROT: 539 /* Some fields are located at different offsets in IPv4 and 540 * IPv6 541 */ 542 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) { 543 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : 544 ICE_PROT_IPV4_IL; 545 /* TTL and PROT share the same extraction seq. entry. 546 * Each is considered a sibling to the other in term 547 * sharing the same extraction sequence entry. 548 */ 549 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL) 550 sib = ICE_FLOW_FIELD_IDX_IP_PROT; 551 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT) 552 sib = ICE_FLOW_FIELD_IDX_IP_TTL; 553 } else if (params->prof->segs[seg].hdrs & 554 ICE_FLOW_SEG_HDR_IPV6) { 555 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : 556 ICE_PROT_IPV6_IL; 557 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL) 558 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP; 559 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT) 560 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP; 561 } 562 break; 563 case ICE_FLOW_FIELD_IDX_IPV4_SA: 564 case ICE_FLOW_FIELD_IDX_IPV4_DA: 565 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 566 break; 567 case ICE_FLOW_FIELD_IDX_IPV6_SA: 568 case ICE_FLOW_FIELD_IDX_IPV6_DA: 569 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 570 break; 571 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 572 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 573 case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 574 prot_id = ICE_PROT_TCP_IL; 575 break; 576 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 577 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 578 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF; 579 break; 580 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 581 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 582 prot_id = ICE_PROT_SCTP_IL; 583 break; 584 case ICE_FLOW_FIELD_IDX_ARP_SIP: 585 case ICE_FLOW_FIELD_IDX_ARP_DIP: 586 case ICE_FLOW_FIELD_IDX_ARP_SHA: 587 case ICE_FLOW_FIELD_IDX_ARP_DHA: 588 case ICE_FLOW_FIELD_IDX_ARP_OP: 589 prot_id = ICE_PROT_ARP_OF; 590 break; 591 case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 592 case ICE_FLOW_FIELD_IDX_ICMP_CODE: 593 /* ICMP type and code share the same extraction seq. entry */ 594 prot_id = (params->prof->segs[seg].hdrs & 595 ICE_FLOW_SEG_HDR_IPV4) ? 596 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 597 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 598 ICE_FLOW_FIELD_IDX_ICMP_CODE : 599 ICE_FLOW_FIELD_IDX_ICMP_TYPE; 600 break; 601 case ICE_FLOW_FIELD_IDX_GRE_KEYID: 602 prot_id = ICE_PROT_GRE_OF; 603 break; 604 default: 605 return ICE_ERR_NOT_IMPL; 606 } 607 608 /* Each extraction sequence entry is a word in size, and extracts a 609 * word-aligned offset from a protocol header. 610 */ 611 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8; 612 613 flds[fld].xtrct.prot_id = prot_id; 614 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 615 ICE_FLOW_FV_EXTRACT_SZ; 616 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits); 617 flds[fld].xtrct.idx = params->es_cnt; 618 619 /* Adjust the next field-entry index after accommodating the number of 620 * entries this field consumes 621 */ 622 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp + 623 ice_flds_info[fld].size, ese_bits); 624 625 /* Fill in the extraction sequence entries needed for this field */ 626 off = flds[fld].xtrct.off; 627 for (i = 0; i < cnt; i++) { 628 /* Only consume an extraction sequence entry if there is no 629 * sibling field associated with this field or the sibling entry 630 * already extracts the word shared with this field. 631 */ 632 if (sib == ICE_FLOW_FIELD_IDX_MAX || 633 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 634 flds[sib].xtrct.off != off) { 635 u8 idx; 636 637 /* Make sure the number of extraction sequence required 638 * does not exceed the block's capability 639 */ 640 if (params->es_cnt >= fv_words) 641 return ICE_ERR_MAX_LIMIT; 642 643 /* some blocks require a reversed field vector layout */ 644 if (hw->blk[params->blk].es.reverse) 645 idx = fv_words - params->es_cnt - 1; 646 else 647 idx = params->es_cnt; 648 649 params->es[idx].prot_id = prot_id; 650 params->es[idx].off = off; 651 params->es_cnt++; 652 } 653 654 off += ICE_FLOW_FV_EXTRACT_SZ; 655 } 656 657 return ICE_SUCCESS; 658 } 659 660 /** 661 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes 662 * @hw: pointer to the HW struct 663 * @params: information about the flow to be processed 664 * @seg: index of packet segment whose raw fields are to be be extracted 665 */ 666 static enum ice_status 667 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, 668 u8 seg) 669 { 670 u16 hdrs_sz; 671 u8 i; 672 673 if (!params->prof->segs[seg].raws_cnt) 674 return ICE_SUCCESS; 675 676 if (params->prof->segs[seg].raws_cnt > 677 ARRAY_SIZE(params->prof->segs[seg].raws)) 678 return ICE_ERR_MAX_LIMIT; 679 680 /* Offsets within the segment headers are not supported */ 681 hdrs_sz = ice_flow_calc_seg_sz(params, seg); 682 if (!hdrs_sz) 683 return ICE_ERR_PARAM; 684 685 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) { 686 struct ice_flow_seg_fld_raw *raw; 687 u16 off, cnt, j; 688 689 raw = ¶ms->prof->segs[seg].raws[i]; 690 691 /* Only support matching raw fields in the payload */ 692 if (raw->off < hdrs_sz) 693 return ICE_ERR_PARAM; 694 695 /* Convert the segment-relative offset into payload-relative 696 * offset. 697 */ 698 off = raw->off - hdrs_sz; 699 700 /* Storing extraction information */ 701 raw->info.xtrct.prot_id = ICE_PROT_PAY; 702 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) * 703 ICE_FLOW_FV_EXTRACT_SZ; 704 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8; 705 raw->info.xtrct.idx = params->es_cnt; 706 707 /* Determine the number of field vector entries this raw field 708 * consumes. 709 */ 710 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp + 711 (raw->info.src.last * 8), 712 ICE_FLOW_FV_EXTRACT_SZ * 8); 713 off = raw->info.xtrct.off; 714 for (j = 0; j < cnt; j++) { 715 /* Make sure the number of extraction sequence required 716 * does not exceed the block's capability 717 */ 718 if (params->es_cnt >= hw->blk[params->blk].es.count || 719 params->es_cnt >= ICE_MAX_FV_WORDS) 720 return ICE_ERR_MAX_LIMIT; 721 722 params->es[params->es_cnt].prot_id = ICE_PROT_PAY; 723 params->es[params->es_cnt].off = off; 724 params->es_cnt++; 725 off += ICE_FLOW_FV_EXTRACT_SZ; 726 } 727 } 728 729 return ICE_SUCCESS; 730 } 731 732 /** 733 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 734 * @hw: pointer to the HW struct 735 * @params: information about the flow to be processed 736 * 737 * This function iterates through all matched fields in the given segments, and 738 * creates an extraction sequence for the fields. 739 */ 740 static enum ice_status 741 ice_flow_create_xtrct_seq(struct ice_hw *hw, 742 struct ice_flow_prof_params *params) 743 { 744 enum ice_status status = ICE_SUCCESS; 745 u8 i; 746 747 for (i = 0; i < params->prof->segs_cnt; i++) { 748 u64 match = params->prof->segs[i].match; 749 u16 j; 750 751 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) { 752 const u64 bit = BIT_ULL(j); 753 754 if (match & bit) { 755 status = ice_flow_xtract_fld 756 (hw, params, i, (enum ice_flow_field)j); 757 if (status) 758 return status; 759 match &= ~bit; 760 } 761 } 762 763 /* Process raw matching bytes */ 764 status = ice_flow_xtract_raws(hw, params, i); 765 if (status) 766 return status; 767 } 768 769 return status; 770 } 771 772 /** 773 * ice_flow_proc_segs - process all packet segments associated with a profile 774 * @hw: pointer to the HW struct 775 * @params: information about the flow to be processed 776 */ 777 static enum ice_status 778 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 779 { 780 enum ice_status status; 781 782 status = ice_flow_proc_seg_hdrs(params); 783 if (status) 784 return status; 785 786 status = ice_flow_create_xtrct_seq(hw, params); 787 if (status) 788 return status; 789 790 switch (params->blk) { 791 case ICE_BLK_RSS: 792 /* Only header information is provided for RSS configuration. 793 * No further processing is needed. 794 */ 795 status = ICE_SUCCESS; 796 break; 797 case ICE_BLK_FD: 798 status = ICE_SUCCESS; 799 break; 800 case ICE_BLK_SW: 801 default: 802 return ICE_ERR_NOT_IMPL; 803 } 804 805 return status; 806 } 807 808 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 809 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 810 811 /** 812 * ice_flow_find_prof_conds - Find a profile matching headers and conditions 813 * @hw: pointer to the HW struct 814 * @blk: classification stage 815 * @dir: flow direction 816 * @segs: array of one or more packet segments that describe the flow 817 * @segs_cnt: number of packet segments provided 818 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 819 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 820 */ 821 static struct ice_flow_prof * 822 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 823 enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 824 u8 segs_cnt, u16 vsi_handle, u32 conds) 825 { 826 struct ice_flow_prof *p; 827 828 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { 829 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) { 830 u8 i; 831 832 /* Check for profile-VSI association if specified */ 833 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 834 ice_is_vsi_valid(hw, vsi_handle) && 835 !ice_is_bit_set(p->vsis, vsi_handle)) 836 continue; 837 838 /* Protocol headers must be checked. Matched fields are 839 * checked if specified. 840 */ 841 for (i = 0; i < segs_cnt; i++) 842 if (segs[i].hdrs != p->segs[i].hdrs || 843 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 844 segs[i].match != p->segs[i].match)) 845 break; 846 847 /* A match is found if all segments are matched */ 848 if (i == segs_cnt) 849 return p; 850 } 851 } 852 853 return NULL; 854 } 855 856 /** 857 * ice_flow_find_prof - Look up a profile matching headers and matched fields 858 * @hw: pointer to the HW struct 859 * @blk: classification stage 860 * @dir: flow direction 861 * @segs: array of one or more packet segments that describe the flow 862 * @segs_cnt: number of packet segments provided 863 */ 864 u64 865 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 866 struct ice_flow_seg_info *segs, u8 segs_cnt) 867 { 868 struct ice_flow_prof *p; 869 870 ice_acquire_lock(&hw->fl_profs_locks[blk]); 871 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, 872 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); 873 ice_release_lock(&hw->fl_profs_locks[blk]); 874 875 return p ? p->id : ICE_FLOW_PROF_ID_INVAL; 876 } 877 878 /** 879 * ice_flow_find_prof_id - Look up a profile with given profile ID 880 * @hw: pointer to the HW struct 881 * @blk: classification stage 882 * @prof_id: unique ID to identify this flow profile 883 */ 884 static struct ice_flow_prof * 885 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 886 { 887 struct ice_flow_prof *p; 888 889 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { 890 if (p->id == prof_id) 891 return p; 892 } 893 894 return NULL; 895 } 896 897 /** 898 * ice_flow_rem_entry_sync - Remove a flow entry 899 * @hw: pointer to the HW struct 900 * @entry: flow entry to be removed 901 */ 902 static enum ice_status 903 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry) 904 { 905 if (!entry) 906 return ICE_ERR_BAD_PTR; 907 908 LIST_DEL(&entry->l_entry); 909 910 if (entry->entry) 911 ice_free(hw, entry->entry); 912 913 if (entry->acts) { 914 ice_free(hw, entry->acts); 915 entry->acts = NULL; 916 entry->acts_cnt = 0; 917 } 918 919 ice_free(hw, entry); 920 921 return ICE_SUCCESS; 922 } 923 924 /** 925 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 926 * @hw: pointer to the HW struct 927 * @blk: classification stage 928 * @dir: flow direction 929 * @prof_id: unique ID to identify this flow profile 930 * @segs: array of one or more packet segments that describe the flow 931 * @segs_cnt: number of packet segments provided 932 * @acts: array of default actions 933 * @acts_cnt: number of default actions 934 * @prof: stores the returned flow profile added 935 * 936 * Assumption: the caller has acquired the lock to the profile list 937 */ 938 static enum ice_status 939 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 940 enum ice_flow_dir dir, u64 prof_id, 941 struct ice_flow_seg_info *segs, u8 segs_cnt, 942 struct ice_flow_action *acts, u8 acts_cnt, 943 struct ice_flow_prof **prof) 944 { 945 struct ice_flow_prof_params params; 946 enum ice_status status = ICE_SUCCESS; 947 u8 i; 948 949 if (!prof || (acts_cnt && !acts)) 950 return ICE_ERR_BAD_PTR; 951 952 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM); 953 params.prof = (struct ice_flow_prof *) 954 ice_malloc(hw, sizeof(*params.prof)); 955 if (!params.prof) 956 return ICE_ERR_NO_MEMORY; 957 958 /* initialize extraction sequence to all invalid (0xff) */ 959 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 960 params.es[i].prot_id = ICE_PROT_INVALID; 961 params.es[i].off = ICE_FV_OFFSET_INVAL; 962 } 963 964 params.blk = blk; 965 params.prof->id = prof_id; 966 params.prof->dir = dir; 967 params.prof->segs_cnt = segs_cnt; 968 969 /* Make a copy of the segments that need to be persistent in the flow 970 * profile instance 971 */ 972 for (i = 0; i < segs_cnt; i++) 973 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs), 974 ICE_NONDMA_TO_NONDMA); 975 976 /* Make a copy of the actions that need to be persistent in the flow 977 * profile instance. 978 */ 979 if (acts_cnt) { 980 params.prof->acts = (struct ice_flow_action *) 981 ice_memdup(hw, acts, acts_cnt * sizeof(*acts), 982 ICE_NONDMA_TO_NONDMA); 983 984 if (!params.prof->acts) { 985 status = ICE_ERR_NO_MEMORY; 986 goto out; 987 } 988 } 989 990 status = ice_flow_proc_segs(hw, ¶ms); 991 if (status) { 992 ice_debug(hw, ICE_DBG_FLOW, 993 "Error processing a flow's packet segments\n"); 994 goto out; 995 } 996 997 /* Add a HW profile for this flow profile */ 998 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es); 999 if (status) { 1000 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 1001 goto out; 1002 } 1003 1004 INIT_LIST_HEAD(¶ms.prof->entries); 1005 ice_init_lock(¶ms.prof->entries_lock); 1006 *prof = params.prof; 1007 1008 out: 1009 if (status) { 1010 if (params.prof->acts) 1011 ice_free(hw, params.prof->acts); 1012 ice_free(hw, params.prof); 1013 } 1014 1015 return status; 1016 } 1017 1018 /** 1019 * ice_flow_rem_prof_sync - remove a flow profile 1020 * @hw: pointer to the hardware structure 1021 * @blk: classification stage 1022 * @prof: pointer to flow profile to remove 1023 * 1024 * Assumption: the caller has acquired the lock to the profile list 1025 */ 1026 static enum ice_status 1027 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 1028 struct ice_flow_prof *prof) 1029 { 1030 enum ice_status status = ICE_SUCCESS; 1031 1032 /* Remove all remaining flow entries before removing the flow profile */ 1033 if (!LIST_EMPTY(&prof->entries)) { 1034 struct ice_flow_entry *e, *t; 1035 1036 ice_acquire_lock(&prof->entries_lock); 1037 1038 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry, 1039 l_entry) { 1040 status = ice_flow_rem_entry_sync(hw, e); 1041 if (status) 1042 break; 1043 } 1044 1045 ice_release_lock(&prof->entries_lock); 1046 } 1047 1048 /* Remove all hardware profiles associated with this flow profile */ 1049 status = ice_rem_prof(hw, blk, prof->id); 1050 if (!status) { 1051 LIST_DEL(&prof->l_entry); 1052 ice_destroy_lock(&prof->entries_lock); 1053 if (prof->acts) 1054 ice_free(hw, prof->acts); 1055 ice_free(hw, prof); 1056 } 1057 1058 return status; 1059 } 1060 1061 /** 1062 * ice_flow_assoc_prof - associate a VSI with a flow profile 1063 * @hw: pointer to the hardware structure 1064 * @blk: classification stage 1065 * @prof: pointer to flow profile 1066 * @vsi_handle: software VSI handle 1067 * 1068 * Assumption: the caller has acquired the lock to the profile list 1069 * and the software VSI handle has been validated 1070 */ 1071 static enum ice_status 1072 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 1073 struct ice_flow_prof *prof, u16 vsi_handle) 1074 { 1075 enum ice_status status = ICE_SUCCESS; 1076 1077 if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 1078 status = ice_add_prof_id_flow(hw, blk, 1079 ice_get_hw_vsi_num(hw, 1080 vsi_handle), 1081 prof->id); 1082 if (!status) 1083 ice_set_bit(vsi_handle, prof->vsis); 1084 else 1085 ice_debug(hw, ICE_DBG_FLOW, 1086 "HW profile add failed, %d\n", 1087 status); 1088 } 1089 1090 return status; 1091 } 1092 1093 /** 1094 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 1095 * @hw: pointer to the hardware structure 1096 * @blk: classification stage 1097 * @prof: pointer to flow profile 1098 * @vsi_handle: software VSI handle 1099 * 1100 * Assumption: the caller has acquired the lock to the profile list 1101 * and the software VSI handle has been validated 1102 */ 1103 static enum ice_status 1104 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 1105 struct ice_flow_prof *prof, u16 vsi_handle) 1106 { 1107 enum ice_status status = ICE_SUCCESS; 1108 1109 if (ice_is_bit_set(prof->vsis, vsi_handle)) { 1110 status = ice_rem_prof_id_flow(hw, blk, 1111 ice_get_hw_vsi_num(hw, 1112 vsi_handle), 1113 prof->id); 1114 if (!status) 1115 ice_clear_bit(vsi_handle, prof->vsis); 1116 else 1117 ice_debug(hw, ICE_DBG_FLOW, 1118 "HW profile remove failed, %d\n", 1119 status); 1120 } 1121 1122 return status; 1123 } 1124 1125 /** 1126 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 1127 * @hw: pointer to the HW struct 1128 * @blk: classification stage 1129 * @dir: flow direction 1130 * @prof_id: unique ID to identify this flow profile 1131 * @segs: array of one or more packet segments that describe the flow 1132 * @segs_cnt: number of packet segments provided 1133 * @acts: array of default actions 1134 * @acts_cnt: number of default actions 1135 * @prof: stores the returned flow profile added 1136 */ 1137 enum ice_status 1138 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 1139 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 1140 struct ice_flow_action *acts, u8 acts_cnt, 1141 struct ice_flow_prof **prof) 1142 { 1143 enum ice_status status; 1144 1145 if (segs_cnt > ICE_FLOW_SEG_MAX) 1146 return ICE_ERR_MAX_LIMIT; 1147 1148 if (!segs_cnt) 1149 return ICE_ERR_PARAM; 1150 1151 if (!segs) 1152 return ICE_ERR_BAD_PTR; 1153 1154 status = ice_flow_val_hdrs(segs, segs_cnt); 1155 if (status) 1156 return status; 1157 1158 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1159 1160 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 1161 acts, acts_cnt, prof); 1162 if (!status) 1163 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 1164 1165 ice_release_lock(&hw->fl_profs_locks[blk]); 1166 1167 return status; 1168 } 1169 1170 /** 1171 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 1172 * @hw: pointer to the HW struct 1173 * @blk: the block for which the flow profile is to be removed 1174 * @prof_id: unique ID of the flow profile to be removed 1175 */ 1176 enum ice_status 1177 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 1178 { 1179 struct ice_flow_prof *prof; 1180 enum ice_status status; 1181 1182 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1183 1184 prof = ice_flow_find_prof_id(hw, blk, prof_id); 1185 if (!prof) { 1186 status = ICE_ERR_DOES_NOT_EXIST; 1187 goto out; 1188 } 1189 1190 /* prof becomes invalid after the call */ 1191 status = ice_flow_rem_prof_sync(hw, blk, prof); 1192 1193 out: 1194 ice_release_lock(&hw->fl_profs_locks[blk]); 1195 1196 return status; 1197 } 1198 1199 /** 1200 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle 1201 * @hw: pointer to the HW struct 1202 * @blk: classification stage 1203 * @prof_id: the profile ID handle 1204 * @hw_prof_id: pointer to variable to receive the HW profile ID 1205 */ 1206 enum ice_status 1207 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 1208 u8 *hw_prof_id) 1209 { 1210 struct ice_prof_map *map; 1211 1212 map = ice_search_prof_id(hw, blk, prof_id); 1213 if (map) { 1214 *hw_prof_id = map->prof_id; 1215 return ICE_SUCCESS; 1216 } 1217 1218 return ICE_ERR_DOES_NOT_EXIST; 1219 } 1220 1221 /** 1222 * ice_flow_find_entry - look for a flow entry using its unique ID 1223 * @hw: pointer to the HW struct 1224 * @blk: classification stage 1225 * @entry_id: unique ID to identify this flow entry 1226 * 1227 * This function looks for the flow entry with the specified unique ID in all 1228 * flow profiles of the specified classification stage. If the entry is found, 1229 * and it returns the handle to the flow entry. Otherwise, it returns 1230 * ICE_FLOW_ENTRY_ID_INVAL. 1231 */ 1232 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id) 1233 { 1234 struct ice_flow_entry *found = NULL; 1235 struct ice_flow_prof *p; 1236 1237 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1238 1239 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { 1240 struct ice_flow_entry *e; 1241 1242 ice_acquire_lock(&p->entries_lock); 1243 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry) 1244 if (e->id == entry_id) { 1245 found = e; 1246 break; 1247 } 1248 ice_release_lock(&p->entries_lock); 1249 1250 if (found) 1251 break; 1252 } 1253 1254 ice_release_lock(&hw->fl_profs_locks[blk]); 1255 1256 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL; 1257 } 1258 1259 /** 1260 * ice_flow_add_entry - Add a flow entry 1261 * @hw: pointer to the HW struct 1262 * @blk: classification stage 1263 * @prof_id: ID of the profile to add a new flow entry to 1264 * @entry_id: unique ID to identify this flow entry 1265 * @vsi_handle: software VSI handle for the flow entry 1266 * @prio: priority of the flow entry 1267 * @data: pointer to a data buffer containing flow entry's match values/masks 1268 * @acts: arrays of actions to be performed on a match 1269 * @acts_cnt: number of actions 1270 * @entry_h: pointer to buffer that receives the new flow entry's handle 1271 */ 1272 enum ice_status 1273 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 1274 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, 1275 void *data, struct ice_flow_action *acts, u8 acts_cnt, 1276 u64 *entry_h) 1277 { 1278 struct ice_flow_prof *prof = NULL; 1279 struct ice_flow_entry *e = NULL; 1280 enum ice_status status = ICE_SUCCESS; 1281 1282 if (acts_cnt && !acts) 1283 return ICE_ERR_PARAM; 1284 1285 /* No flow entry data is expected for RSS */ 1286 if (!entry_h || (!data && blk != ICE_BLK_RSS)) 1287 return ICE_ERR_BAD_PTR; 1288 1289 if (!ice_is_vsi_valid(hw, vsi_handle)) 1290 return ICE_ERR_PARAM; 1291 1292 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1293 1294 prof = ice_flow_find_prof_id(hw, blk, prof_id); 1295 if (!prof) { 1296 status = ICE_ERR_DOES_NOT_EXIST; 1297 } else { 1298 /* Allocate memory for the entry being added and associate 1299 * the VSI to the found flow profile 1300 */ 1301 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e)); 1302 if (!e) 1303 status = ICE_ERR_NO_MEMORY; 1304 else 1305 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1306 } 1307 1308 ice_release_lock(&hw->fl_profs_locks[blk]); 1309 if (status) 1310 goto out; 1311 1312 e->id = entry_id; 1313 e->vsi_handle = vsi_handle; 1314 e->prof = prof; 1315 e->priority = prio; 1316 1317 switch (blk) { 1318 case ICE_BLK_RSS: 1319 /* RSS will add only one entry per VSI per profile */ 1320 break; 1321 case ICE_BLK_FD: 1322 break; 1323 case ICE_BLK_SW: 1324 case ICE_BLK_PE: 1325 default: 1326 status = ICE_ERR_NOT_IMPL; 1327 goto out; 1328 } 1329 1330 ice_acquire_lock(&prof->entries_lock); 1331 LIST_ADD(&e->l_entry, &prof->entries); 1332 ice_release_lock(&prof->entries_lock); 1333 1334 *entry_h = ICE_FLOW_ENTRY_HNDL(e); 1335 1336 out: 1337 if (status && e) { 1338 if (e->entry) 1339 ice_free(hw, e->entry); 1340 ice_free(hw, e); 1341 } 1342 1343 return status; 1344 } 1345 1346 /** 1347 * ice_flow_rem_entry - Remove a flow entry 1348 * @hw: pointer to the HW struct 1349 * @entry_h: handle to the flow entry to be removed 1350 */ 1351 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h) 1352 { 1353 struct ice_flow_entry *entry; 1354 struct ice_flow_prof *prof; 1355 enum ice_status status; 1356 1357 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) 1358 return ICE_ERR_PARAM; 1359 1360 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h); 1361 1362 /* Retain the pointer to the flow profile as the entry will be freed */ 1363 prof = entry->prof; 1364 1365 ice_acquire_lock(&prof->entries_lock); 1366 status = ice_flow_rem_entry_sync(hw, entry); 1367 ice_release_lock(&prof->entries_lock); 1368 1369 return status; 1370 } 1371 1372 /** 1373 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 1374 * @seg: packet segment the field being set belongs to 1375 * @fld: field to be set 1376 * @type: type of the field 1377 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1378 * entry's input buffer 1379 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1380 * input buffer 1381 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1382 * entry's input buffer 1383 * 1384 * This helper function stores information of a field being matched, including 1385 * the type of the field and the locations of the value to match, the mask, and 1386 * and the upper-bound value in the start of the input buffer for a flow entry. 1387 * This function should only be used for fixed-size data structures. 1388 * 1389 * This function also opportunistically determines the protocol headers to be 1390 * present based on the fields being set. Some fields cannot be used alone to 1391 * determine the protocol headers present. Sometimes, fields for particular 1392 * protocol headers are not matched. In those cases, the protocol headers 1393 * must be explicitly set. 1394 */ 1395 static void 1396 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1397 enum ice_flow_fld_match_type type, u16 val_loc, 1398 u16 mask_loc, u16 last_loc) 1399 { 1400 u64 bit = BIT_ULL(fld); 1401 1402 seg->match |= bit; 1403 if (type == ICE_FLOW_FLD_TYPE_RANGE) 1404 seg->range |= bit; 1405 1406 seg->fields[fld].type = type; 1407 seg->fields[fld].src.val = val_loc; 1408 seg->fields[fld].src.mask = mask_loc; 1409 seg->fields[fld].src.last = last_loc; 1410 1411 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 1412 } 1413 1414 /** 1415 * ice_flow_set_fld - specifies locations of field from entry's input buffer 1416 * @seg: packet segment the field being set belongs to 1417 * @fld: field to be set 1418 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1419 * entry's input buffer 1420 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1421 * input buffer 1422 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1423 * entry's input buffer 1424 * @range: indicate if field being matched is to be in a range 1425 * 1426 * This function specifies the locations, in the form of byte offsets from the 1427 * start of the input buffer for a flow entry, from where the value to match, 1428 * the mask value, and upper value can be extracted. These locations are then 1429 * stored in the flow profile. When adding a flow entry associated with the 1430 * flow profile, these locations will be used to quickly extract the values and 1431 * create the content of a match entry. This function should only be used for 1432 * fixed-size data structures. 1433 */ 1434 void 1435 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1436 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 1437 { 1438 enum ice_flow_fld_match_type t = range ? 1439 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 1440 1441 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 1442 } 1443 1444 /** 1445 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 1446 * @seg: packet segment the field being set belongs to 1447 * @fld: field to be set 1448 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1449 * entry's input buffer 1450 * @pref_loc: location of prefix value from entry's input buffer 1451 * @pref_sz: size of the location holding the prefix value 1452 * 1453 * This function specifies the locations, in the form of byte offsets from the 1454 * start of the input buffer for a flow entry, from where the value to match 1455 * and the IPv4 prefix value can be extracted. These locations are then stored 1456 * in the flow profile. When adding flow entries to the associated flow profile, 1457 * these locations can be used to quickly extract the values to create the 1458 * content of a match entry. This function should only be used for fixed-size 1459 * data structures. 1460 */ 1461 void 1462 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1463 u16 val_loc, u16 pref_loc, u8 pref_sz) 1464 { 1465 /* For this type of field, the "mask" location is for the prefix value's 1466 * location and the "last" location is for the size of the location of 1467 * the prefix value. 1468 */ 1469 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 1470 pref_loc, (u16)pref_sz); 1471 } 1472 1473 /** 1474 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf 1475 * @seg: packet segment the field being set belongs to 1476 * @off: offset of the raw field from the beginning of the segment in bytes 1477 * @len: length of the raw pattern to be matched 1478 * @val_loc: location of the value to match from entry's input buffer 1479 * @mask_loc: location of mask value from entry's input buffer 1480 * 1481 * This function specifies the offset of the raw field to be match from the 1482 * beginning of the specified packet segment, and the locations, in the form of 1483 * byte offsets from the start of the input buffer for a flow entry, from where 1484 * the value to match and the mask value to be extracted. These locations are 1485 * then stored in the flow profile. When adding flow entries to the associated 1486 * flow profile, these locations can be used to quickly extract the values to 1487 * create the content of a match entry. This function should only be used for 1488 * fixed-size data structures. 1489 */ 1490 void 1491 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, 1492 u16 val_loc, u16 mask_loc) 1493 { 1494 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { 1495 seg->raws[seg->raws_cnt].off = off; 1496 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; 1497 seg->raws[seg->raws_cnt].info.src.val = val_loc; 1498 seg->raws[seg->raws_cnt].info.src.mask = mask_loc; 1499 /* The "last" field is used to store the length of the field */ 1500 seg->raws[seg->raws_cnt].info.src.last = len; 1501 } 1502 1503 /* Overflows of "raws" will be handled as an error condition later in 1504 * the flow when this information is processed. 1505 */ 1506 seg->raws_cnt++; 1507 } 1508 1509 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 1510 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 1511 1512 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 1513 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 1514 ICE_FLOW_SEG_HDR_SCTP) 1515 1516 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 1517 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 1518 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 1519 1520 /** 1521 * ice_flow_set_rss_seg_info - setup packet segments for RSS 1522 * @segs: pointer to the flow field segment(s) 1523 * @hash_fields: fields to be hashed on for the segment(s) 1524 * @flow_hdr: protocol header fields within a packet segment 1525 * 1526 * Helper function to extract fields from hash bitmap and use flow 1527 * header value to set flow field segment for further use in flow 1528 * profile entry or removal. 1529 */ 1530 static enum ice_status 1531 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, 1532 u32 flow_hdr) 1533 { 1534 u64 val = hash_fields; 1535 u8 i; 1536 1537 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) { 1538 u64 bit = BIT_ULL(i); 1539 1540 if (val & bit) { 1541 ice_flow_set_fld(segs, (enum ice_flow_field)i, 1542 ICE_FLOW_FLD_OFF_INVAL, 1543 ICE_FLOW_FLD_OFF_INVAL, 1544 ICE_FLOW_FLD_OFF_INVAL, false); 1545 val &= ~bit; 1546 } 1547 } 1548 ICE_FLOW_SET_HDRS(segs, flow_hdr); 1549 1550 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) 1551 return ICE_ERR_PARAM; 1552 1553 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 1554 if (!ice_is_pow2(val)) 1555 return ICE_ERR_CFG; 1556 1557 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 1558 if (val && !ice_is_pow2(val)) 1559 return ICE_ERR_CFG; 1560 1561 return ICE_SUCCESS; 1562 } 1563 1564 /** 1565 * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context 1566 * @hw: pointer to the hardware structure 1567 * @vsi_handle: software VSI handle 1568 * 1569 */ 1570 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) 1571 { 1572 struct ice_rss_cfg *r, *tmp; 1573 1574 if (!ice_is_vsi_valid(hw, vsi_handle) || 1575 LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head)) 1576 return; 1577 1578 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1579 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, 1580 &hw->vsi_ctx[vsi_handle]->rss_list_head, 1581 ice_rss_cfg, l_entry) { 1582 LIST_DEL(&r->l_entry); 1583 ice_free(hw, r); 1584 } 1585 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1586 } 1587 1588 /** 1589 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 1590 * @hw: pointer to the hardware structure 1591 * @vsi_handle: software VSI handle 1592 * 1593 * This function will iterate through all flow profiles and disassociate 1594 * the VSI from that profile. If the flow profile has no VSIs it will 1595 * be removed. 1596 */ 1597 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1598 { 1599 const enum ice_block blk = ICE_BLK_RSS; 1600 struct ice_flow_prof *p, *t; 1601 enum ice_status status = ICE_SUCCESS; 1602 1603 if (!ice_is_vsi_valid(hw, vsi_handle)) 1604 return ICE_ERR_PARAM; 1605 1606 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1607 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 1608 l_entry) { 1609 if (ice_is_bit_set(p->vsis, vsi_handle)) { 1610 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 1611 if (status) 1612 break; 1613 1614 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 1615 status = ice_flow_rem_prof_sync(hw, blk, p); 1616 if (status) 1617 break; 1618 } 1619 } 1620 } 1621 ice_release_lock(&hw->fl_profs_locks[blk]); 1622 1623 return status; 1624 } 1625 1626 /** 1627 * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context 1628 * @hw: pointer to the hardware structure 1629 * @vsi_handle: software VSI handle 1630 * @prof: pointer to flow profile 1631 * 1632 * Assumption: lock has already been acquired for RSS list 1633 */ 1634 static void 1635 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, 1636 struct ice_flow_prof *prof) 1637 { 1638 struct ice_rss_cfg *r, *tmp; 1639 1640 /* Search for RSS hash fields associated to the VSI that match the 1641 * hash configurations associated to the flow profile. If found 1642 * remove from the RSS entry list of the VSI context and delete entry. 1643 */ 1644 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, 1645 &hw->vsi_ctx[vsi_handle]->rss_list_head, 1646 ice_rss_cfg, l_entry) { 1647 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 1648 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { 1649 LIST_DEL(&r->l_entry); 1650 ice_free(hw, r); 1651 return; 1652 } 1653 } 1654 } 1655 1656 /** 1657 * ice_add_rss_vsi_ctx - add RSS configuration to VSI context 1658 * @hw: pointer to the hardware structure 1659 * @vsi_handle: software VSI handle 1660 * @prof: pointer to flow profile 1661 * 1662 * Assumption: lock has already been acquired for RSS list 1663 */ 1664 static enum ice_status 1665 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, 1666 struct ice_flow_prof *prof) 1667 { 1668 struct ice_rss_cfg *r, *rss_cfg; 1669 1670 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, 1671 ice_rss_cfg, l_entry) 1672 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && 1673 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) 1674 return ICE_SUCCESS; 1675 1676 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 1677 if (!rss_cfg) 1678 return ICE_ERR_NO_MEMORY; 1679 1680 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; 1681 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; 1682 LIST_ADD_TAIL(&rss_cfg->l_entry, 1683 &hw->vsi_ctx[vsi_handle]->rss_list_head); 1684 1685 return ICE_SUCCESS; 1686 } 1687 1688 #define ICE_FLOW_PROF_HASH_S 0 1689 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 1690 #define ICE_FLOW_PROF_HDR_S 32 1691 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S) 1692 1693 #define ICE_FLOW_GEN_PROFID(hash, hdr) \ 1694 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 1695 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M)) 1696 1697 /** 1698 * ice_add_rss_cfg_sync - add an RSS configuration 1699 * @hw: pointer to the hardware structure 1700 * @vsi_handle: software VSI handle 1701 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 1702 * @addl_hdrs: protocol header fields 1703 * 1704 * Assumption: lock has already been acquired for RSS list 1705 */ 1706 static enum ice_status 1707 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1708 u32 addl_hdrs) 1709 { 1710 const enum ice_block blk = ICE_BLK_RSS; 1711 struct ice_flow_prof *prof = NULL; 1712 struct ice_flow_seg_info *segs; 1713 enum ice_status status = ICE_SUCCESS; 1714 1715 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs)); 1716 if (!segs) 1717 return ICE_ERR_NO_MEMORY; 1718 1719 /* Construct the packet segment info from the hashed fields */ 1720 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs); 1721 if (status) 1722 goto exit; 1723 1724 /* Search for a flow profile that has matching headers, hash fields 1725 * and has the input VSI associated to it. If found, no further 1726 * operations required and exit. 1727 */ 1728 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1, 1729 vsi_handle, 1730 ICE_FLOW_FIND_PROF_CHK_FLDS | 1731 ICE_FLOW_FIND_PROF_CHK_VSI); 1732 if (prof) 1733 goto exit; 1734 1735 /* Check if a flow profile exists with the same protocol headers and 1736 * associated with the input VSI. If so disasscociate the VSI from 1737 * this profile. The VSI will be added to a new profile created with 1738 * the protocol header and new hash field configuration. 1739 */ 1740 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1, 1741 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 1742 if (prof) { 1743 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1744 if (!status) 1745 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof); 1746 else 1747 goto exit; 1748 1749 /* Remove profile if it has no VSIs associated */ 1750 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 1751 status = ice_flow_rem_prof_sync(hw, blk, prof); 1752 if (status) 1753 goto exit; 1754 } 1755 } 1756 1757 /* Search for a profile that has same match fields only. If this 1758 * exists then associate the VSI to this profile. 1759 */ 1760 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1, 1761 vsi_handle, 1762 ICE_FLOW_FIND_PROF_CHK_FLDS); 1763 if (prof) { 1764 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1765 if (!status) 1766 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof); 1767 goto exit; 1768 } 1769 1770 /* Create a new flow profile with generated profile and packet 1771 * segment information. 1772 */ 1773 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 1774 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs), 1775 segs, 1, NULL, 0, &prof); 1776 if (status) 1777 goto exit; 1778 1779 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1780 /* If association to a new flow profile failed then this profile can 1781 * be removed. 1782 */ 1783 if (status) { 1784 ice_flow_rem_prof_sync(hw, blk, prof); 1785 goto exit; 1786 } 1787 1788 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof); 1789 1790 exit: 1791 ice_free(hw, segs); 1792 return status; 1793 } 1794 1795 /** 1796 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 1797 * @hw: pointer to the hardware structure 1798 * @vsi_handle: software VSI handle 1799 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 1800 * @addl_hdrs: protocol header fields 1801 * 1802 * This function will generate a flow profile based on fields associated with 1803 * the input fields to hash on, the flow type and use the VSI number to add 1804 * a flow entry to the profile. 1805 */ 1806 enum ice_status 1807 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1808 u32 addl_hdrs) 1809 { 1810 enum ice_status status; 1811 1812 if (hashed_flds == ICE_HASH_INVALID || 1813 !ice_is_vsi_valid(hw, vsi_handle)) 1814 return ICE_ERR_PARAM; 1815 1816 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1817 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs); 1818 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1819 1820 return status; 1821 } 1822 1823 /** 1824 * ice_rem_rss_cfg_sync - remove an existing RSS configuration 1825 * @hw: pointer to the hardware structure 1826 * @vsi_handle: software VSI handle 1827 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove 1828 * @addl_hdrs: Protocol header fields within a packet segment 1829 * 1830 * Assumption: lock has already been acquired for RSS list 1831 */ 1832 static enum ice_status 1833 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1834 u32 addl_hdrs) 1835 { 1836 const enum ice_block blk = ICE_BLK_RSS; 1837 struct ice_flow_seg_info *segs; 1838 struct ice_flow_prof *prof; 1839 enum ice_status status; 1840 1841 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs)); 1842 if (!segs) 1843 return ICE_ERR_NO_MEMORY; 1844 1845 /* Construct the packet segment info from the hashed fields */ 1846 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs); 1847 if (status) 1848 goto out; 1849 1850 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1, 1851 vsi_handle, 1852 ICE_FLOW_FIND_PROF_CHK_FLDS); 1853 if (!prof) { 1854 status = ICE_ERR_DOES_NOT_EXIST; 1855 goto out; 1856 } 1857 1858 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1859 if (status) 1860 goto out; 1861 1862 /* Remove RSS configuration from VSI context before deleting 1863 * the flow profile. 1864 */ 1865 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof); 1866 1867 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 1868 status = ice_flow_rem_prof_sync(hw, blk, prof); 1869 1870 out: 1871 ice_free(hw, segs); 1872 return status; 1873 } 1874 1875 /** 1876 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 1877 * @hw: pointer to the hardware structure 1878 * @vsi_handle: software VSI handle 1879 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove 1880 * @addl_hdrs: Protocol header fields within a packet segment 1881 * 1882 * This function will lookup the flow profile based on the input 1883 * hash field bitmap, iterate through the profile entry list of 1884 * that profile and find entry associated with input VSI to be 1885 * removed. Calls are made to underlying flow apis which will in 1886 * turn build or update buffers for RSS XLT1 section. 1887 */ 1888 enum ice_status 1889 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, 1890 u32 addl_hdrs) 1891 { 1892 enum ice_status status; 1893 1894 if (hashed_flds == ICE_HASH_INVALID || 1895 !ice_is_vsi_valid(hw, vsi_handle)) 1896 return ICE_ERR_PARAM; 1897 1898 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1899 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs); 1900 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1901 1902 return status; 1903 } 1904 1905 /** 1906 * ice_replay_rss_cfg - remove RSS configurations associated with VSI 1907 * @hw: pointer to the hardware structure 1908 * @vsi_handle: software VSI handle 1909 */ 1910 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1911 { 1912 enum ice_status status = ICE_SUCCESS; 1913 struct ice_rss_cfg *r; 1914 1915 if (!ice_is_vsi_valid(hw, vsi_handle)) 1916 return ICE_ERR_PARAM; 1917 1918 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1919 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, 1920 ice_rss_cfg, l_entry) { 1921 status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds, 1922 r->packet_hdr); 1923 if (status) 1924 break; 1925 } 1926 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1927 1928 return status; 1929 } 1930 1931 /** 1932 * ice_get_rss_cfg - returns hashed fields for the given header types 1933 * @hw: pointer to the hardware structure 1934 * @vsi_handle: software VSI handle 1935 * @hdrs: protocol header type 1936 * 1937 * This function will return the match fields of the first instance of flow 1938 * profile having the given header types and containing input VSI 1939 */ 1940 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 1941 { 1942 struct ice_rss_cfg *r, *rss_cfg = NULL; 1943 1944 /* verify if the protocol header is non zero and VSI is valid */ 1945 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 1946 return ICE_HASH_INVALID; 1947 1948 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1949 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, 1950 ice_rss_cfg, l_entry) 1951 if (r->packet_hdr == hdrs) { 1952 rss_cfg = r; 1953 break; 1954 } 1955 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); 1956 1957 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID; 1958 } 1959