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