1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2019, Intel Corporation. */ |
3 | |
4 | #include "ice_common.h" |
5 | #include "ice_flow.h" |
6 | #include <net/gre.h> |
7 | |
8 | /* Describe properties of a protocol header field */ |
9 | struct ice_flow_field_info { |
10 | enum ice_flow_seg_hdr hdr; |
11 | s16 off; /* Offset from start of a protocol header, in bits */ |
12 | u16 size; /* Size of fields in bits */ |
13 | u16 mask; /* 16-bit mask for field */ |
14 | }; |
15 | |
16 | #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ |
17 | .hdr = _hdr, \ |
18 | .off = (_offset_bytes) * BITS_PER_BYTE, \ |
19 | .size = (_size_bytes) * BITS_PER_BYTE, \ |
20 | .mask = 0, \ |
21 | } |
22 | |
23 | #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \ |
24 | .hdr = _hdr, \ |
25 | .off = (_offset_bytes) * BITS_PER_BYTE, \ |
26 | .size = (_size_bytes) * BITS_PER_BYTE, \ |
27 | .mask = _mask, \ |
28 | } |
29 | |
30 | /* Table containing properties of supported protocol header fields */ |
31 | static const |
32 | struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { |
33 | /* Ether */ |
34 | /* ICE_FLOW_FIELD_IDX_ETH_DA */ |
35 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), |
36 | /* ICE_FLOW_FIELD_IDX_ETH_SA */ |
37 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), |
38 | /* ICE_FLOW_FIELD_IDX_S_VLAN */ |
39 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)), |
40 | /* ICE_FLOW_FIELD_IDX_C_VLAN */ |
41 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)), |
42 | /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ |
43 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)), |
44 | /* IPv4 / IPv6 */ |
45 | /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ |
46 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc), |
47 | /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ |
48 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0), |
49 | /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ |
50 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00), |
51 | /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ |
52 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff), |
53 | /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ |
54 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff), |
55 | /* ICE_FLOW_FIELD_IDX_IPV6_PROT */ |
56 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00), |
57 | /* ICE_FLOW_FIELD_IDX_IPV4_SA */ |
58 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)), |
59 | /* ICE_FLOW_FIELD_IDX_IPV4_DA */ |
60 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)), |
61 | /* ICE_FLOW_FIELD_IDX_IPV6_SA */ |
62 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)), |
63 | /* ICE_FLOW_FIELD_IDX_IPV6_DA */ |
64 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, sizeof(struct in6_addr)), |
65 | /* Transport */ |
66 | /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ |
67 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)), |
68 | /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ |
69 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)), |
70 | /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ |
71 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)), |
72 | /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ |
73 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)), |
74 | /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ |
75 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)), |
76 | /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ |
77 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)), |
78 | /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ |
79 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, 1), |
80 | /* ARP */ |
81 | /* ICE_FLOW_FIELD_IDX_ARP_SIP */ |
82 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)), |
83 | /* ICE_FLOW_FIELD_IDX_ARP_DIP */ |
84 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)), |
85 | /* ICE_FLOW_FIELD_IDX_ARP_SHA */ |
86 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), |
87 | /* ICE_FLOW_FIELD_IDX_ARP_DHA */ |
88 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), |
89 | /* ICE_FLOW_FIELD_IDX_ARP_OP */ |
90 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)), |
91 | /* ICMP */ |
92 | /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ |
93 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1), |
94 | /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ |
95 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1), |
96 | /* GRE */ |
97 | /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ |
98 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, |
99 | sizeof_field(struct gre_full_hdr, key)), |
100 | /* GTP */ |
101 | /* ICE_FLOW_FIELD_IDX_GTPC_TEID */ |
102 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)), |
103 | /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */ |
104 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)), |
105 | /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */ |
106 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)), |
107 | /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */ |
108 | ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16), |
109 | 0x3f00), |
110 | /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */ |
111 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, sizeof(__be32)), |
112 | /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */ |
113 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, sizeof(__be32)), |
114 | /* PPPoE */ |
115 | /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */ |
116 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)), |
117 | /* PFCP */ |
118 | /* ICE_FLOW_FIELD_IDX_PFCP_SEID */ |
119 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)), |
120 | /* L2TPv3 */ |
121 | /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */ |
122 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)), |
123 | /* ESP */ |
124 | /* ICE_FLOW_FIELD_IDX_ESP_SPI */ |
125 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)), |
126 | /* AH */ |
127 | /* ICE_FLOW_FIELD_IDX_AH_SPI */ |
128 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)), |
129 | /* NAT_T_ESP */ |
130 | /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */ |
131 | ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8, sizeof(__be32)), |
132 | }; |
133 | |
134 | /* Bitmaps indicating relevant packet types for a particular protocol header |
135 | * |
136 | * Packet types for packets with an Outer/First/Single MAC header |
137 | */ |
138 | static const u32 ice_ptypes_mac_ofos[] = { |
139 | 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, |
140 | 0x0000077E, 0x00000000, 0x00000000, 0x00000000, |
141 | 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000, |
142 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
143 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
144 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
145 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
146 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
147 | }; |
148 | |
149 | /* Packet types for packets with an Innermost/Last MAC VLAN header */ |
150 | static const u32 ice_ptypes_macvlan_il[] = { |
151 | 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, |
152 | 0x0000077E, 0x00000000, 0x00000000, 0x00000000, |
153 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
154 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
155 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
156 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
157 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
158 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
159 | }; |
160 | |
161 | /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT |
162 | * include IPv4 other PTYPEs |
163 | */ |
164 | static const u32 ice_ptypes_ipv4_ofos[] = { |
165 | 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, |
166 | 0x00000000, 0x00000155, 0x00000000, 0x00000000, |
167 | 0x00000000, 0x000FC000, 0x00000000, 0x00000000, |
168 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
169 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
170 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
171 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
172 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
173 | }; |
174 | |
175 | /* Packet types for packets with an Outer/First/Single IPv4 header, includes |
176 | * IPv4 other PTYPEs |
177 | */ |
178 | static const u32 ice_ptypes_ipv4_ofos_all[] = { |
179 | 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, |
180 | 0x00000000, 0x00000155, 0x00000000, 0x00000000, |
181 | 0x00000000, 0x000FC000, 0x83E0F800, 0x00000101, |
182 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
183 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
184 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
185 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
186 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
187 | }; |
188 | |
189 | /* Packet types for packets with an Innermost/Last IPv4 header */ |
190 | static const u32 ice_ptypes_ipv4_il[] = { |
191 | 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, |
192 | 0x0000000E, 0x00000000, 0x00000000, 0x00000000, |
193 | 0x00000000, 0x00000000, 0x001FF800, 0x00000000, |
194 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
195 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
196 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
197 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
198 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
199 | }; |
200 | |
201 | /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT |
202 | * include IPv6 other PTYPEs |
203 | */ |
204 | static const u32 ice_ptypes_ipv6_ofos[] = { |
205 | 0x00000000, 0x00000000, 0x77000000, 0x10002000, |
206 | 0x00000000, 0x000002AA, 0x00000000, 0x00000000, |
207 | 0x00000000, 0x03F00000, 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 | }; |
214 | |
215 | /* Packet types for packets with an Outer/First/Single IPv6 header, includes |
216 | * IPv6 other PTYPEs |
217 | */ |
218 | static const u32 ice_ptypes_ipv6_ofos_all[] = { |
219 | 0x00000000, 0x00000000, 0x77000000, 0x10002000, |
220 | 0x00000000, 0x000002AA, 0x00000000, 0x00000000, |
221 | 0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000206, |
222 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
223 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
224 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
225 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
226 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
227 | }; |
228 | |
229 | /* Packet types for packets with an Innermost/Last IPv6 header */ |
230 | static const u32 ice_ptypes_ipv6_il[] = { |
231 | 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, |
232 | 0x00000770, 0x00000000, 0x00000000, 0x00000000, |
233 | 0x00000000, 0x00000000, 0x7FE00000, 0x00000000, |
234 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
235 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
236 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
237 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
238 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
239 | }; |
240 | |
241 | /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */ |
242 | static const u32 ice_ptypes_ipv4_ofos_no_l4[] = { |
243 | 0x10C00000, 0x04000800, 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 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
251 | }; |
252 | |
253 | /* Packet types for packets with an Outermost/First ARP header */ |
254 | static const u32 ice_ptypes_arp_of[] = { |
255 | 0x00000800, 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 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
263 | }; |
264 | |
265 | /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ |
266 | static const u32 ice_ptypes_ipv4_il_no_l4[] = { |
267 | 0x60000000, 0x18043008, 0x80000002, 0x6010c021, |
268 | 0x00000008, 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 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
275 | }; |
276 | |
277 | /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */ |
278 | static const u32 ice_ptypes_ipv6_ofos_no_l4[] = { |
279 | 0x00000000, 0x00000000, 0x43000000, 0x10002000, |
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 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
287 | }; |
288 | |
289 | /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ |
290 | static const u32 ice_ptypes_ipv6_il_no_l4[] = { |
291 | 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, |
292 | 0x00000430, 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 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
299 | }; |
300 | |
301 | /* UDP Packet types for non-tunneled packets or tunneled |
302 | * packets with inner UDP. |
303 | */ |
304 | static const u32 ice_ptypes_udp_il[] = { |
305 | 0x81000000, 0x20204040, 0x04000010, 0x80810102, |
306 | 0x00000040, 0x00000000, 0x00000000, 0x00000000, |
307 | 0x00000000, 0x00410000, 0x90842000, 0x00000007, |
308 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
309 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
310 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
311 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
312 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
313 | }; |
314 | |
315 | /* Packet types for packets with an Innermost/Last TCP header */ |
316 | static const u32 ice_ptypes_tcp_il[] = { |
317 | 0x04000000, 0x80810102, 0x10000040, 0x02040408, |
318 | 0x00000102, 0x00000000, 0x00000000, 0x00000000, |
319 | 0x00000000, 0x00820000, 0x21084000, 0x00000000, |
320 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
321 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
322 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
323 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
324 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
325 | }; |
326 | |
327 | /* Packet types for packets with an Innermost/Last SCTP header */ |
328 | static const u32 ice_ptypes_sctp_il[] = { |
329 | 0x08000000, 0x01020204, 0x20000081, 0x04080810, |
330 | 0x00000204, 0x00000000, 0x00000000, 0x00000000, |
331 | 0x00000000, 0x01040000, 0x00000000, 0x00000000, |
332 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
333 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
334 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
335 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
336 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
337 | }; |
338 | |
339 | /* Packet types for packets with an Outermost/First ICMP header */ |
340 | static const u32 ice_ptypes_icmp_of[] = { |
341 | 0x10000000, 0x00000000, 0x00000000, 0x00000000, |
342 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
343 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
344 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
345 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
346 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
347 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
348 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
349 | }; |
350 | |
351 | /* Packet types for packets with an Innermost/Last ICMP header */ |
352 | static const u32 ice_ptypes_icmp_il[] = { |
353 | 0x00000000, 0x02040408, 0x40000102, 0x08101020, |
354 | 0x00000408, 0x00000000, 0x00000000, 0x00000000, |
355 | 0x00000000, 0x00000000, 0x42108000, 0x00000000, |
356 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
357 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
358 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
359 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
360 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
361 | }; |
362 | |
363 | /* Packet types for packets with an Outermost/First GRE header */ |
364 | static const u32 ice_ptypes_gre_of[] = { |
365 | 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, |
366 | 0x0000017E, 0x00000000, 0x00000000, 0x00000000, |
367 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
368 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
369 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
370 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
371 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
372 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
373 | }; |
374 | |
375 | /* Packet types for packets with an Innermost/Last MAC header */ |
376 | static const u32 ice_ptypes_mac_il[] = { |
377 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
378 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
379 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
380 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
381 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
382 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
383 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
384 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
385 | }; |
386 | |
387 | /* Packet types for GTPC */ |
388 | static const u32 ice_ptypes_gtpc[] = { |
389 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
390 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
391 | 0x00000000, 0x00000000, 0x00000180, 0x00000000, |
392 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
393 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
394 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
395 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
396 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
397 | }; |
398 | |
399 | /* Packet types for GTPC with TEID */ |
400 | static const u32 ice_ptypes_gtpc_tid[] = { |
401 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
402 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
403 | 0x00000000, 0x00000000, 0x00000060, 0x00000000, |
404 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
405 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
406 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
407 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
408 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
409 | }; |
410 | |
411 | /* Packet types for GTPU */ |
412 | static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = { |
413 | { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
414 | { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
415 | { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
416 | { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
417 | { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
418 | { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
419 | { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
420 | { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
421 | { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
422 | { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
423 | { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
424 | { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
425 | { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
426 | { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
427 | { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
428 | { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
429 | { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
430 | { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
431 | { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
432 | { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH }, |
433 | }; |
434 | |
435 | static const struct ice_ptype_attributes ice_attr_gtpu_down[] = { |
436 | { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
437 | { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
438 | { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
439 | { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
440 | { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
441 | { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
442 | { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
443 | { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
444 | { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
445 | { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
446 | { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
447 | { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
448 | { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
449 | { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
450 | { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
451 | { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
452 | { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
453 | { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
454 | { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
455 | { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK }, |
456 | }; |
457 | |
458 | static const struct ice_ptype_attributes ice_attr_gtpu_up[] = { |
459 | { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, |
460 | { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
461 | { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
462 | { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
463 | { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
464 | { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, |
465 | { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
466 | { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
467 | { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
468 | { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
469 | { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, |
470 | { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
471 | { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
472 | { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
473 | { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, |
474 | { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK }, |
475 | { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
476 | { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK }, |
477 | { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK }, |
478 | { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK }, |
479 | }; |
480 | |
481 | static const u32 ice_ptypes_gtpu[] = { |
482 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
483 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
484 | 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000, |
485 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
486 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
487 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
488 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
489 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
490 | }; |
491 | |
492 | /* Packet types for PPPoE */ |
493 | static const u32 ice_ptypes_pppoe[] = { |
494 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
495 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
496 | 0x00000000, 0x03ffe000, 0x00000000, 0x00000000, |
497 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
498 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
499 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
500 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
501 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
502 | }; |
503 | |
504 | /* Packet types for packets with PFCP NODE header */ |
505 | static const u32 ice_ptypes_pfcp_node[] = { |
506 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
507 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
508 | 0x00000000, 0x00000000, 0x80000000, 0x00000002, |
509 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
510 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
511 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
512 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
513 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
514 | }; |
515 | |
516 | /* Packet types for packets with PFCP SESSION header */ |
517 | static const u32 ice_ptypes_pfcp_session[] = { |
518 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
519 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
520 | 0x00000000, 0x00000000, 0x00000000, 0x00000005, |
521 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
522 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
523 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
524 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
525 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
526 | }; |
527 | |
528 | /* Packet types for L2TPv3 */ |
529 | static const u32 ice_ptypes_l2tpv3[] = { |
530 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
531 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
532 | 0x00000000, 0x00000000, 0x00000000, 0x00000300, |
533 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
534 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
535 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
536 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
537 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
538 | }; |
539 | |
540 | /* Packet types for ESP */ |
541 | static const u32 ice_ptypes_esp[] = { |
542 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
543 | 0x00000000, 0x00000003, 0x00000000, 0x00000000, |
544 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
545 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
546 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
547 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
548 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
549 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
550 | }; |
551 | |
552 | /* Packet types for AH */ |
553 | static const u32 ice_ptypes_ah[] = { |
554 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
555 | 0x00000000, 0x0000000C, 0x00000000, 0x00000000, |
556 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
557 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
558 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
559 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
560 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
561 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
562 | }; |
563 | |
564 | /* Packet types for packets with NAT_T ESP header */ |
565 | static const u32 ice_ptypes_nat_t_esp[] = { |
566 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
567 | 0x00000000, 0x00000030, 0x00000000, 0x00000000, |
568 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
569 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
570 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
571 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
572 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
573 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
574 | }; |
575 | |
576 | static const u32 ice_ptypes_mac_non_ip_ofos[] = { |
577 | 0x00000846, 0x00000000, 0x00000000, 0x00000000, |
578 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
579 | 0x00400000, 0x03FFF000, 0x00000000, 0x00000000, |
580 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
581 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
582 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
583 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
584 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
585 | }; |
586 | |
587 | /* Manage parameters and info. used during the creation of a flow profile */ |
588 | struct ice_flow_prof_params { |
589 | enum ice_block blk; |
590 | u16 entry_length; /* # of bytes formatted entry will require */ |
591 | u8 es_cnt; |
592 | struct ice_flow_prof *prof; |
593 | |
594 | /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 |
595 | * This will give us the direction flags. |
596 | */ |
597 | struct ice_fv_word es[ICE_MAX_FV_WORDS]; |
598 | /* attributes can be used to add attributes to a particular PTYPE */ |
599 | const struct ice_ptype_attributes *attr; |
600 | u16 attr_cnt; |
601 | |
602 | u16 mask[ICE_MAX_FV_WORDS]; |
603 | DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); |
604 | }; |
605 | |
606 | #define \ |
607 | (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \ |
608 | ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \ |
609 | ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \ |
610 | ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \ |
611 | ICE_FLOW_SEG_HDR_NAT_T_ESP) |
612 | |
613 | #define ICE_FLOW_SEG_HDRS_L3_MASK \ |
614 | (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) |
615 | #define ICE_FLOW_SEG_HDRS_L4_MASK \ |
616 | (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ |
617 | ICE_FLOW_SEG_HDR_SCTP) |
618 | /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */ |
619 | #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \ |
620 | (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) |
621 | |
622 | /** |
623 | * ice_flow_val_hdrs - validates packet segments for valid protocol headers |
624 | * @segs: array of one or more packet segments that describe the flow |
625 | * @segs_cnt: number of packet segments provided |
626 | */ |
627 | static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) |
628 | { |
629 | u8 i; |
630 | |
631 | for (i = 0; i < segs_cnt; i++) { |
632 | /* Multiple L3 headers */ |
633 | if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && |
634 | !is_power_of_2(n: segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) |
635 | return -EINVAL; |
636 | |
637 | /* Multiple L4 headers */ |
638 | if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && |
639 | !is_power_of_2(n: segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) |
640 | return -EINVAL; |
641 | } |
642 | |
643 | return 0; |
644 | } |
645 | |
646 | /* Sizes of fixed known protocol headers without header options */ |
647 | #define ICE_FLOW_PROT_HDR_SZ_MAC 14 |
648 | #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2) |
649 | #define ICE_FLOW_PROT_HDR_SZ_IPV4 20 |
650 | #define ICE_FLOW_PROT_HDR_SZ_IPV6 40 |
651 | #define ICE_FLOW_PROT_HDR_SZ_ARP 28 |
652 | #define ICE_FLOW_PROT_HDR_SZ_ICMP 8 |
653 | #define ICE_FLOW_PROT_HDR_SZ_TCP 20 |
654 | #define ICE_FLOW_PROT_HDR_SZ_UDP 8 |
655 | #define ICE_FLOW_PROT_HDR_SZ_SCTP 12 |
656 | |
657 | /** |
658 | * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers |
659 | * @params: information about the flow to be processed |
660 | * @seg: index of packet segment whose header size is to be determined |
661 | */ |
662 | static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg) |
663 | { |
664 | u16 sz; |
665 | |
666 | /* L2 headers */ |
667 | sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ? |
668 | ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC; |
669 | |
670 | /* L3 headers */ |
671 | if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) |
672 | sz += ICE_FLOW_PROT_HDR_SZ_IPV4; |
673 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6) |
674 | sz += ICE_FLOW_PROT_HDR_SZ_IPV6; |
675 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP) |
676 | sz += ICE_FLOW_PROT_HDR_SZ_ARP; |
677 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK) |
678 | /* An L3 header is required if L4 is specified */ |
679 | return 0; |
680 | |
681 | /* L4 headers */ |
682 | if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP) |
683 | sz += ICE_FLOW_PROT_HDR_SZ_ICMP; |
684 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP) |
685 | sz += ICE_FLOW_PROT_HDR_SZ_TCP; |
686 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP) |
687 | sz += ICE_FLOW_PROT_HDR_SZ_UDP; |
688 | else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP) |
689 | sz += ICE_FLOW_PROT_HDR_SZ_SCTP; |
690 | |
691 | return sz; |
692 | } |
693 | |
694 | /** |
695 | * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments |
696 | * @params: information about the flow to be processed |
697 | * |
698 | * This function identifies the packet types associated with the protocol |
699 | * headers being present in packet segments of the specified flow profile. |
700 | */ |
701 | static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) |
702 | { |
703 | struct ice_flow_prof *prof; |
704 | u8 i; |
705 | |
706 | memset(params->ptypes, 0xff, sizeof(params->ptypes)); |
707 | |
708 | prof = params->prof; |
709 | |
710 | for (i = 0; i < params->prof->segs_cnt; i++) { |
711 | const unsigned long *src; |
712 | u32 hdrs; |
713 | |
714 | hdrs = prof->segs[i].hdrs; |
715 | |
716 | if (hdrs & ICE_FLOW_SEG_HDR_ETH) { |
717 | src = !i ? (const unsigned long *)ice_ptypes_mac_ofos : |
718 | (const unsigned long *)ice_ptypes_mac_il; |
719 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
720 | ICE_FLOW_PTYPE_MAX); |
721 | } |
722 | |
723 | if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { |
724 | src = (const unsigned long *)ice_ptypes_macvlan_il; |
725 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
726 | ICE_FLOW_PTYPE_MAX); |
727 | } |
728 | |
729 | if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { |
730 | bitmap_and(dst: params->ptypes, src1: params->ptypes, |
731 | src2: (const unsigned long *)ice_ptypes_arp_of, |
732 | ICE_FLOW_PTYPE_MAX); |
733 | } |
734 | |
735 | if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && |
736 | (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { |
737 | src = i ? (const unsigned long *)ice_ptypes_ipv4_il : |
738 | (const unsigned long *)ice_ptypes_ipv4_ofos_all; |
739 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
740 | ICE_FLOW_PTYPE_MAX); |
741 | } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && |
742 | (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { |
743 | src = i ? (const unsigned long *)ice_ptypes_ipv6_il : |
744 | (const unsigned long *)ice_ptypes_ipv6_ofos_all; |
745 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
746 | ICE_FLOW_PTYPE_MAX); |
747 | } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && |
748 | !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { |
749 | src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 : |
750 | (const unsigned long *)ice_ptypes_ipv4_il_no_l4; |
751 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
752 | ICE_FLOW_PTYPE_MAX); |
753 | } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { |
754 | src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos : |
755 | (const unsigned long *)ice_ptypes_ipv4_il; |
756 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
757 | ICE_FLOW_PTYPE_MAX); |
758 | } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && |
759 | !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { |
760 | src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 : |
761 | (const unsigned long *)ice_ptypes_ipv6_il_no_l4; |
762 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
763 | ICE_FLOW_PTYPE_MAX); |
764 | } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { |
765 | src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos : |
766 | (const unsigned long *)ice_ptypes_ipv6_il; |
767 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
768 | ICE_FLOW_PTYPE_MAX); |
769 | } |
770 | |
771 | if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) { |
772 | src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos; |
773 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
774 | ICE_FLOW_PTYPE_MAX); |
775 | } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) { |
776 | src = (const unsigned long *)ice_ptypes_pppoe; |
777 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
778 | ICE_FLOW_PTYPE_MAX); |
779 | } else { |
780 | src = (const unsigned long *)ice_ptypes_pppoe; |
781 | bitmap_andnot(dst: params->ptypes, src1: params->ptypes, src2: src, |
782 | ICE_FLOW_PTYPE_MAX); |
783 | } |
784 | |
785 | if (hdrs & ICE_FLOW_SEG_HDR_UDP) { |
786 | src = (const unsigned long *)ice_ptypes_udp_il; |
787 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
788 | ICE_FLOW_PTYPE_MAX); |
789 | } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { |
790 | bitmap_and(dst: params->ptypes, src1: params->ptypes, |
791 | src2: (const unsigned long *)ice_ptypes_tcp_il, |
792 | ICE_FLOW_PTYPE_MAX); |
793 | } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { |
794 | src = (const unsigned long *)ice_ptypes_sctp_il; |
795 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
796 | ICE_FLOW_PTYPE_MAX); |
797 | } |
798 | |
799 | if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { |
800 | src = !i ? (const unsigned long *)ice_ptypes_icmp_of : |
801 | (const unsigned long *)ice_ptypes_icmp_il; |
802 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
803 | ICE_FLOW_PTYPE_MAX); |
804 | } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { |
805 | if (!i) { |
806 | src = (const unsigned long *)ice_ptypes_gre_of; |
807 | bitmap_and(dst: params->ptypes, src1: params->ptypes, |
808 | src2: src, ICE_FLOW_PTYPE_MAX); |
809 | } |
810 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) { |
811 | src = (const unsigned long *)ice_ptypes_gtpc; |
812 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
813 | ICE_FLOW_PTYPE_MAX); |
814 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) { |
815 | src = (const unsigned long *)ice_ptypes_gtpc_tid; |
816 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
817 | ICE_FLOW_PTYPE_MAX); |
818 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) { |
819 | src = (const unsigned long *)ice_ptypes_gtpu; |
820 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
821 | ICE_FLOW_PTYPE_MAX); |
822 | |
823 | /* Attributes for GTP packet with downlink */ |
824 | params->attr = ice_attr_gtpu_down; |
825 | params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down); |
826 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) { |
827 | src = (const unsigned long *)ice_ptypes_gtpu; |
828 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
829 | ICE_FLOW_PTYPE_MAX); |
830 | |
831 | /* Attributes for GTP packet with uplink */ |
832 | params->attr = ice_attr_gtpu_up; |
833 | params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up); |
834 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) { |
835 | src = (const unsigned long *)ice_ptypes_gtpu; |
836 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
837 | ICE_FLOW_PTYPE_MAX); |
838 | |
839 | /* Attributes for GTP packet with Extension Header */ |
840 | params->attr = ice_attr_gtpu_eh; |
841 | params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh); |
842 | } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) { |
843 | src = (const unsigned long *)ice_ptypes_gtpu; |
844 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
845 | ICE_FLOW_PTYPE_MAX); |
846 | } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) { |
847 | src = (const unsigned long *)ice_ptypes_l2tpv3; |
848 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
849 | ICE_FLOW_PTYPE_MAX); |
850 | } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) { |
851 | src = (const unsigned long *)ice_ptypes_esp; |
852 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
853 | ICE_FLOW_PTYPE_MAX); |
854 | } else if (hdrs & ICE_FLOW_SEG_HDR_AH) { |
855 | src = (const unsigned long *)ice_ptypes_ah; |
856 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
857 | ICE_FLOW_PTYPE_MAX); |
858 | } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) { |
859 | src = (const unsigned long *)ice_ptypes_nat_t_esp; |
860 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
861 | ICE_FLOW_PTYPE_MAX); |
862 | } |
863 | |
864 | if (hdrs & ICE_FLOW_SEG_HDR_PFCP) { |
865 | if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE) |
866 | src = (const unsigned long *)ice_ptypes_pfcp_node; |
867 | else |
868 | src = (const unsigned long *)ice_ptypes_pfcp_session; |
869 | |
870 | bitmap_and(dst: params->ptypes, src1: params->ptypes, src2: src, |
871 | ICE_FLOW_PTYPE_MAX); |
872 | } else { |
873 | src = (const unsigned long *)ice_ptypes_pfcp_node; |
874 | bitmap_andnot(dst: params->ptypes, src1: params->ptypes, src2: src, |
875 | ICE_FLOW_PTYPE_MAX); |
876 | |
877 | src = (const unsigned long *)ice_ptypes_pfcp_session; |
878 | bitmap_andnot(dst: params->ptypes, src1: params->ptypes, src2: src, |
879 | ICE_FLOW_PTYPE_MAX); |
880 | } |
881 | } |
882 | |
883 | return 0; |
884 | } |
885 | |
886 | /** |
887 | * ice_flow_xtract_fld - Create an extraction sequence entry for the given field |
888 | * @hw: pointer to the HW struct |
889 | * @params: information about the flow to be processed |
890 | * @seg: packet segment index of the field to be extracted |
891 | * @fld: ID of field to be extracted |
892 | * @match: bit field of all fields |
893 | * |
894 | * This function determines the protocol ID, offset, and size of the given |
895 | * field. It then allocates one or more extraction sequence entries for the |
896 | * given field, and fill the entries with protocol ID and offset information. |
897 | */ |
898 | static int |
899 | ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, |
900 | u8 seg, enum ice_flow_field fld, u64 match) |
901 | { |
902 | enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; |
903 | enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; |
904 | u8 fv_words = hw->blk[params->blk].es.fvw; |
905 | struct ice_flow_fld_info *flds; |
906 | u16 cnt, ese_bits, i; |
907 | u16 sib_mask = 0; |
908 | u16 mask; |
909 | u16 off; |
910 | |
911 | flds = params->prof->segs[seg].fields; |
912 | |
913 | switch (fld) { |
914 | case ICE_FLOW_FIELD_IDX_ETH_DA: |
915 | case ICE_FLOW_FIELD_IDX_ETH_SA: |
916 | case ICE_FLOW_FIELD_IDX_S_VLAN: |
917 | case ICE_FLOW_FIELD_IDX_C_VLAN: |
918 | prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; |
919 | break; |
920 | case ICE_FLOW_FIELD_IDX_ETH_TYPE: |
921 | prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; |
922 | break; |
923 | case ICE_FLOW_FIELD_IDX_IPV4_DSCP: |
924 | prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; |
925 | break; |
926 | case ICE_FLOW_FIELD_IDX_IPV6_DSCP: |
927 | prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; |
928 | break; |
929 | case ICE_FLOW_FIELD_IDX_IPV4_TTL: |
930 | case ICE_FLOW_FIELD_IDX_IPV4_PROT: |
931 | prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; |
932 | |
933 | /* TTL and PROT share the same extraction seq. entry. |
934 | * Each is considered a sibling to the other in terms of sharing |
935 | * the same extraction sequence entry. |
936 | */ |
937 | if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) |
938 | sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; |
939 | else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT) |
940 | sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; |
941 | |
942 | /* If the sibling field is also included, that field's |
943 | * mask needs to be included. |
944 | */ |
945 | if (match & BIT(sib)) |
946 | sib_mask = ice_flds_info[sib].mask; |
947 | break; |
948 | case ICE_FLOW_FIELD_IDX_IPV6_TTL: |
949 | case ICE_FLOW_FIELD_IDX_IPV6_PROT: |
950 | prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; |
951 | |
952 | /* TTL and PROT share the same extraction seq. entry. |
953 | * Each is considered a sibling to the other in terms of sharing |
954 | * the same extraction sequence entry. |
955 | */ |
956 | if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) |
957 | sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; |
958 | else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT) |
959 | sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; |
960 | |
961 | /* If the sibling field is also included, that field's |
962 | * mask needs to be included. |
963 | */ |
964 | if (match & BIT(sib)) |
965 | sib_mask = ice_flds_info[sib].mask; |
966 | break; |
967 | case ICE_FLOW_FIELD_IDX_IPV4_SA: |
968 | case ICE_FLOW_FIELD_IDX_IPV4_DA: |
969 | prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; |
970 | break; |
971 | case ICE_FLOW_FIELD_IDX_IPV6_SA: |
972 | case ICE_FLOW_FIELD_IDX_IPV6_DA: |
973 | prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; |
974 | break; |
975 | case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: |
976 | case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: |
977 | case ICE_FLOW_FIELD_IDX_TCP_FLAGS: |
978 | prot_id = ICE_PROT_TCP_IL; |
979 | break; |
980 | case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: |
981 | case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: |
982 | prot_id = ICE_PROT_UDP_IL_OR_S; |
983 | break; |
984 | case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: |
985 | case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: |
986 | prot_id = ICE_PROT_SCTP_IL; |
987 | break; |
988 | case ICE_FLOW_FIELD_IDX_GTPC_TEID: |
989 | case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID: |
990 | case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID: |
991 | case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID: |
992 | case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID: |
993 | case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI: |
994 | /* GTP is accessed through UDP OF protocol */ |
995 | prot_id = ICE_PROT_UDP_OF; |
996 | break; |
997 | case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID: |
998 | prot_id = ICE_PROT_PPPOE; |
999 | break; |
1000 | case ICE_FLOW_FIELD_IDX_PFCP_SEID: |
1001 | prot_id = ICE_PROT_UDP_IL_OR_S; |
1002 | break; |
1003 | case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID: |
1004 | prot_id = ICE_PROT_L2TPV3; |
1005 | break; |
1006 | case ICE_FLOW_FIELD_IDX_ESP_SPI: |
1007 | prot_id = ICE_PROT_ESP_F; |
1008 | break; |
1009 | case ICE_FLOW_FIELD_IDX_AH_SPI: |
1010 | prot_id = ICE_PROT_ESP_2; |
1011 | break; |
1012 | case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI: |
1013 | prot_id = ICE_PROT_UDP_IL_OR_S; |
1014 | break; |
1015 | case ICE_FLOW_FIELD_IDX_ARP_SIP: |
1016 | case ICE_FLOW_FIELD_IDX_ARP_DIP: |
1017 | case ICE_FLOW_FIELD_IDX_ARP_SHA: |
1018 | case ICE_FLOW_FIELD_IDX_ARP_DHA: |
1019 | case ICE_FLOW_FIELD_IDX_ARP_OP: |
1020 | prot_id = ICE_PROT_ARP_OF; |
1021 | break; |
1022 | case ICE_FLOW_FIELD_IDX_ICMP_TYPE: |
1023 | case ICE_FLOW_FIELD_IDX_ICMP_CODE: |
1024 | /* ICMP type and code share the same extraction seq. entry */ |
1025 | prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? |
1026 | ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; |
1027 | sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? |
1028 | ICE_FLOW_FIELD_IDX_ICMP_CODE : |
1029 | ICE_FLOW_FIELD_IDX_ICMP_TYPE; |
1030 | break; |
1031 | case ICE_FLOW_FIELD_IDX_GRE_KEYID: |
1032 | prot_id = ICE_PROT_GRE_OF; |
1033 | break; |
1034 | default: |
1035 | return -EOPNOTSUPP; |
1036 | } |
1037 | |
1038 | /* Each extraction sequence entry is a word in size, and extracts a |
1039 | * word-aligned offset from a protocol header. |
1040 | */ |
1041 | ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; |
1042 | |
1043 | flds[fld].xtrct.prot_id = prot_id; |
1044 | flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * |
1045 | ICE_FLOW_FV_EXTRACT_SZ; |
1046 | flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); |
1047 | flds[fld].xtrct.idx = params->es_cnt; |
1048 | flds[fld].xtrct.mask = ice_flds_info[fld].mask; |
1049 | |
1050 | /* Adjust the next field-entry index after accommodating the number of |
1051 | * entries this field consumes |
1052 | */ |
1053 | cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size, |
1054 | ese_bits); |
1055 | |
1056 | /* Fill in the extraction sequence entries needed for this field */ |
1057 | off = flds[fld].xtrct.off; |
1058 | mask = flds[fld].xtrct.mask; |
1059 | for (i = 0; i < cnt; i++) { |
1060 | /* Only consume an extraction sequence entry if there is no |
1061 | * sibling field associated with this field or the sibling entry |
1062 | * already extracts the word shared with this field. |
1063 | */ |
1064 | if (sib == ICE_FLOW_FIELD_IDX_MAX || |
1065 | flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || |
1066 | flds[sib].xtrct.off != off) { |
1067 | u8 idx; |
1068 | |
1069 | /* Make sure the number of extraction sequence required |
1070 | * does not exceed the block's capability |
1071 | */ |
1072 | if (params->es_cnt >= fv_words) |
1073 | return -ENOSPC; |
1074 | |
1075 | /* some blocks require a reversed field vector layout */ |
1076 | if (hw->blk[params->blk].es.reverse) |
1077 | idx = fv_words - params->es_cnt - 1; |
1078 | else |
1079 | idx = params->es_cnt; |
1080 | |
1081 | params->es[idx].prot_id = prot_id; |
1082 | params->es[idx].off = off; |
1083 | params->mask[idx] = mask | sib_mask; |
1084 | params->es_cnt++; |
1085 | } |
1086 | |
1087 | off += ICE_FLOW_FV_EXTRACT_SZ; |
1088 | } |
1089 | |
1090 | return 0; |
1091 | } |
1092 | |
1093 | /** |
1094 | * ice_flow_xtract_raws - Create extract sequence entries for raw bytes |
1095 | * @hw: pointer to the HW struct |
1096 | * @params: information about the flow to be processed |
1097 | * @seg: index of packet segment whose raw fields are to be extracted |
1098 | */ |
1099 | static int |
1100 | ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, |
1101 | u8 seg) |
1102 | { |
1103 | u16 fv_words; |
1104 | u16 hdrs_sz; |
1105 | u8 i; |
1106 | |
1107 | if (!params->prof->segs[seg].raws_cnt) |
1108 | return 0; |
1109 | |
1110 | if (params->prof->segs[seg].raws_cnt > |
1111 | ARRAY_SIZE(params->prof->segs[seg].raws)) |
1112 | return -ENOSPC; |
1113 | |
1114 | /* Offsets within the segment headers are not supported */ |
1115 | hdrs_sz = ice_flow_calc_seg_sz(params, seg); |
1116 | if (!hdrs_sz) |
1117 | return -EINVAL; |
1118 | |
1119 | fv_words = hw->blk[params->blk].es.fvw; |
1120 | |
1121 | for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) { |
1122 | struct ice_flow_seg_fld_raw *raw; |
1123 | u16 off, cnt, j; |
1124 | |
1125 | raw = ¶ms->prof->segs[seg].raws[i]; |
1126 | |
1127 | /* Storing extraction information */ |
1128 | raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S; |
1129 | raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) * |
1130 | ICE_FLOW_FV_EXTRACT_SZ; |
1131 | raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) * |
1132 | BITS_PER_BYTE; |
1133 | raw->info.xtrct.idx = params->es_cnt; |
1134 | |
1135 | /* Determine the number of field vector entries this raw field |
1136 | * consumes. |
1137 | */ |
1138 | cnt = DIV_ROUND_UP(raw->info.xtrct.disp + |
1139 | (raw->info.src.last * BITS_PER_BYTE), |
1140 | (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE)); |
1141 | off = raw->info.xtrct.off; |
1142 | for (j = 0; j < cnt; j++) { |
1143 | u16 idx; |
1144 | |
1145 | /* Make sure the number of extraction sequence required |
1146 | * does not exceed the block's capability |
1147 | */ |
1148 | if (params->es_cnt >= hw->blk[params->blk].es.count || |
1149 | params->es_cnt >= ICE_MAX_FV_WORDS) |
1150 | return -ENOSPC; |
1151 | |
1152 | /* some blocks require a reversed field vector layout */ |
1153 | if (hw->blk[params->blk].es.reverse) |
1154 | idx = fv_words - params->es_cnt - 1; |
1155 | else |
1156 | idx = params->es_cnt; |
1157 | |
1158 | params->es[idx].prot_id = raw->info.xtrct.prot_id; |
1159 | params->es[idx].off = off; |
1160 | params->es_cnt++; |
1161 | off += ICE_FLOW_FV_EXTRACT_SZ; |
1162 | } |
1163 | } |
1164 | |
1165 | return 0; |
1166 | } |
1167 | |
1168 | /** |
1169 | * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments |
1170 | * @hw: pointer to the HW struct |
1171 | * @params: information about the flow to be processed |
1172 | * |
1173 | * This function iterates through all matched fields in the given segments, and |
1174 | * creates an extraction sequence for the fields. |
1175 | */ |
1176 | static int |
1177 | ice_flow_create_xtrct_seq(struct ice_hw *hw, |
1178 | struct ice_flow_prof_params *params) |
1179 | { |
1180 | struct ice_flow_prof *prof = params->prof; |
1181 | int status = 0; |
1182 | u8 i; |
1183 | |
1184 | for (i = 0; i < prof->segs_cnt; i++) { |
1185 | u64 match = params->prof->segs[i].match; |
1186 | enum ice_flow_field j; |
1187 | |
1188 | for_each_set_bit(j, (unsigned long *)&match, |
1189 | ICE_FLOW_FIELD_IDX_MAX) { |
1190 | status = ice_flow_xtract_fld(hw, params, seg: i, fld: j, match); |
1191 | if (status) |
1192 | return status; |
1193 | clear_bit(nr: j, addr: (unsigned long *)&match); |
1194 | } |
1195 | |
1196 | /* Process raw matching bytes */ |
1197 | status = ice_flow_xtract_raws(hw, params, seg: i); |
1198 | if (status) |
1199 | return status; |
1200 | } |
1201 | |
1202 | return status; |
1203 | } |
1204 | |
1205 | /** |
1206 | * ice_flow_proc_segs - process all packet segments associated with a profile |
1207 | * @hw: pointer to the HW struct |
1208 | * @params: information about the flow to be processed |
1209 | */ |
1210 | static int |
1211 | ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) |
1212 | { |
1213 | int status; |
1214 | |
1215 | status = ice_flow_proc_seg_hdrs(params); |
1216 | if (status) |
1217 | return status; |
1218 | |
1219 | status = ice_flow_create_xtrct_seq(hw, params); |
1220 | if (status) |
1221 | return status; |
1222 | |
1223 | switch (params->blk) { |
1224 | case ICE_BLK_FD: |
1225 | case ICE_BLK_RSS: |
1226 | status = 0; |
1227 | break; |
1228 | default: |
1229 | return -EOPNOTSUPP; |
1230 | } |
1231 | |
1232 | return status; |
1233 | } |
1234 | |
1235 | #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 |
1236 | #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 |
1237 | #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 |
1238 | #define ICE_FLOW_FIND_PROF_CHK_SYMM 0x00000008 |
1239 | |
1240 | /** |
1241 | * ice_flow_find_prof_conds - Find a profile matching headers and conditions |
1242 | * @hw: pointer to the HW struct |
1243 | * @blk: classification stage |
1244 | * @dir: flow direction |
1245 | * @segs: array of one or more packet segments that describe the flow |
1246 | * @segs_cnt: number of packet segments provided |
1247 | * @symm: symmetric setting for RSS profiles |
1248 | * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) |
1249 | * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) |
1250 | */ |
1251 | static struct ice_flow_prof * |
1252 | ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, |
1253 | enum ice_flow_dir dir, struct ice_flow_seg_info *segs, |
1254 | u8 segs_cnt, bool symm, u16 vsi_handle, u32 conds) |
1255 | { |
1256 | struct ice_flow_prof *p, *prof = NULL; |
1257 | |
1258 | mutex_lock(&hw->fl_profs_locks[blk]); |
1259 | list_for_each_entry(p, &hw->fl_profs[blk], l_entry) |
1260 | if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && |
1261 | segs_cnt && segs_cnt == p->segs_cnt) { |
1262 | u8 i; |
1263 | |
1264 | /* Check for profile-VSI association if specified */ |
1265 | if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && |
1266 | ice_is_vsi_valid(hw, vsi_handle) && |
1267 | !test_bit(vsi_handle, p->vsis)) |
1268 | continue; |
1269 | |
1270 | /* Check for symmetric settings */ |
1271 | if ((conds & ICE_FLOW_FIND_PROF_CHK_SYMM) && |
1272 | p->symm != symm) |
1273 | continue; |
1274 | |
1275 | /* Protocol headers must be checked. Matched fields are |
1276 | * checked if specified. |
1277 | */ |
1278 | for (i = 0; i < segs_cnt; i++) |
1279 | if (segs[i].hdrs != p->segs[i].hdrs || |
1280 | ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && |
1281 | segs[i].match != p->segs[i].match)) |
1282 | break; |
1283 | |
1284 | /* A match is found if all segments are matched */ |
1285 | if (i == segs_cnt) { |
1286 | prof = p; |
1287 | break; |
1288 | } |
1289 | } |
1290 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1291 | |
1292 | return prof; |
1293 | } |
1294 | |
1295 | /** |
1296 | * ice_flow_find_prof_id - Look up a profile with given profile ID |
1297 | * @hw: pointer to the HW struct |
1298 | * @blk: classification stage |
1299 | * @prof_id: unique ID to identify this flow profile |
1300 | */ |
1301 | static struct ice_flow_prof * |
1302 | ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) |
1303 | { |
1304 | struct ice_flow_prof *p; |
1305 | |
1306 | list_for_each_entry(p, &hw->fl_profs[blk], l_entry) |
1307 | if (p->id == prof_id) |
1308 | return p; |
1309 | |
1310 | return NULL; |
1311 | } |
1312 | |
1313 | /** |
1314 | * ice_flow_rem_entry_sync - Remove a flow entry |
1315 | * @hw: pointer to the HW struct |
1316 | * @blk: classification stage |
1317 | * @entry: flow entry to be removed |
1318 | */ |
1319 | static int |
1320 | ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, |
1321 | struct ice_flow_entry *entry) |
1322 | { |
1323 | if (!entry) |
1324 | return -EINVAL; |
1325 | |
1326 | list_del(entry: &entry->l_entry); |
1327 | |
1328 | devm_kfree(dev: ice_hw_to_dev(hw), p: entry); |
1329 | |
1330 | return 0; |
1331 | } |
1332 | |
1333 | /** |
1334 | * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields |
1335 | * @hw: pointer to the HW struct |
1336 | * @blk: classification stage |
1337 | * @dir: flow direction |
1338 | * @segs: array of one or more packet segments that describe the flow |
1339 | * @segs_cnt: number of packet segments provided |
1340 | * @symm: symmetric setting for RSS profiles |
1341 | * @prof: stores the returned flow profile added |
1342 | * |
1343 | * Assumption: the caller has acquired the lock to the profile list |
1344 | */ |
1345 | static int |
1346 | ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, |
1347 | enum ice_flow_dir dir, |
1348 | struct ice_flow_seg_info *segs, u8 segs_cnt, |
1349 | bool symm, struct ice_flow_prof **prof) |
1350 | { |
1351 | struct ice_flow_prof_params *params; |
1352 | struct ice_prof_id *ids; |
1353 | int status; |
1354 | u64 prof_id; |
1355 | u8 i; |
1356 | |
1357 | if (!prof) |
1358 | return -EINVAL; |
1359 | |
1360 | ids = &hw->blk[blk].prof_id; |
1361 | prof_id = find_first_zero_bit(addr: ids->id, size: ids->count); |
1362 | if (prof_id >= ids->count) |
1363 | return -ENOSPC; |
1364 | |
1365 | params = kzalloc(size: sizeof(*params), GFP_KERNEL); |
1366 | if (!params) |
1367 | return -ENOMEM; |
1368 | |
1369 | params->prof = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*params->prof), |
1370 | GFP_KERNEL); |
1371 | if (!params->prof) { |
1372 | status = -ENOMEM; |
1373 | goto free_params; |
1374 | } |
1375 | |
1376 | /* initialize extraction sequence to all invalid (0xff) */ |
1377 | for (i = 0; i < ICE_MAX_FV_WORDS; i++) { |
1378 | params->es[i].prot_id = ICE_PROT_INVALID; |
1379 | params->es[i].off = ICE_FV_OFFSET_INVAL; |
1380 | } |
1381 | |
1382 | params->blk = blk; |
1383 | params->prof->id = prof_id; |
1384 | params->prof->dir = dir; |
1385 | params->prof->segs_cnt = segs_cnt; |
1386 | params->prof->symm = symm; |
1387 | |
1388 | /* Make a copy of the segments that need to be persistent in the flow |
1389 | * profile instance |
1390 | */ |
1391 | for (i = 0; i < segs_cnt; i++) |
1392 | memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs)); |
1393 | |
1394 | status = ice_flow_proc_segs(hw, params); |
1395 | if (status) { |
1396 | ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n" ); |
1397 | goto out; |
1398 | } |
1399 | |
1400 | /* Add a HW profile for this flow profile */ |
1401 | status = ice_add_prof(hw, blk, id: prof_id, ptypes: (u8 *)params->ptypes, |
1402 | attr: params->attr, attr_cnt: params->attr_cnt, es: params->es, |
1403 | masks: params->mask, symm); |
1404 | if (status) { |
1405 | ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n" ); |
1406 | goto out; |
1407 | } |
1408 | |
1409 | INIT_LIST_HEAD(list: ¶ms->prof->entries); |
1410 | mutex_init(¶ms->prof->entries_lock); |
1411 | set_bit(nr: prof_id, addr: ids->id); |
1412 | *prof = params->prof; |
1413 | |
1414 | out: |
1415 | if (status) |
1416 | devm_kfree(dev: ice_hw_to_dev(hw), p: params->prof); |
1417 | free_params: |
1418 | kfree(objp: params); |
1419 | |
1420 | return status; |
1421 | } |
1422 | |
1423 | /** |
1424 | * ice_flow_rem_prof_sync - remove a flow profile |
1425 | * @hw: pointer to the hardware structure |
1426 | * @blk: classification stage |
1427 | * @prof: pointer to flow profile to remove |
1428 | * |
1429 | * Assumption: the caller has acquired the lock to the profile list |
1430 | */ |
1431 | static int |
1432 | ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, |
1433 | struct ice_flow_prof *prof) |
1434 | { |
1435 | int status; |
1436 | |
1437 | /* Remove all remaining flow entries before removing the flow profile */ |
1438 | if (!list_empty(head: &prof->entries)) { |
1439 | struct ice_flow_entry *e, *t; |
1440 | |
1441 | mutex_lock(&prof->entries_lock); |
1442 | |
1443 | list_for_each_entry_safe(e, t, &prof->entries, l_entry) { |
1444 | status = ice_flow_rem_entry_sync(hw, blk, entry: e); |
1445 | if (status) |
1446 | break; |
1447 | } |
1448 | |
1449 | mutex_unlock(lock: &prof->entries_lock); |
1450 | } |
1451 | |
1452 | /* Remove all hardware profiles associated with this flow profile */ |
1453 | status = ice_rem_prof(hw, blk, id: prof->id); |
1454 | if (!status) { |
1455 | clear_bit(nr: prof->id, addr: hw->blk[blk].prof_id.id); |
1456 | list_del(entry: &prof->l_entry); |
1457 | mutex_destroy(lock: &prof->entries_lock); |
1458 | devm_kfree(dev: ice_hw_to_dev(hw), p: prof); |
1459 | } |
1460 | |
1461 | return status; |
1462 | } |
1463 | |
1464 | /** |
1465 | * ice_flow_assoc_prof - associate a VSI with a flow profile |
1466 | * @hw: pointer to the hardware structure |
1467 | * @blk: classification stage |
1468 | * @prof: pointer to flow profile |
1469 | * @vsi_handle: software VSI handle |
1470 | * |
1471 | * Assumption: the caller has acquired the lock to the profile list |
1472 | * and the software VSI handle has been validated |
1473 | */ |
1474 | static int |
1475 | ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, |
1476 | struct ice_flow_prof *prof, u16 vsi_handle) |
1477 | { |
1478 | int status = 0; |
1479 | |
1480 | if (!test_bit(vsi_handle, prof->vsis)) { |
1481 | status = ice_add_prof_id_flow(hw, blk, |
1482 | vsi: ice_get_hw_vsi_num(hw, |
1483 | vsi_handle), |
1484 | hdl: prof->id); |
1485 | if (!status) |
1486 | set_bit(nr: vsi_handle, addr: prof->vsis); |
1487 | else |
1488 | ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n" , |
1489 | status); |
1490 | } |
1491 | |
1492 | return status; |
1493 | } |
1494 | |
1495 | /** |
1496 | * ice_flow_disassoc_prof - disassociate a VSI from a flow profile |
1497 | * @hw: pointer to the hardware structure |
1498 | * @blk: classification stage |
1499 | * @prof: pointer to flow profile |
1500 | * @vsi_handle: software VSI handle |
1501 | * |
1502 | * Assumption: the caller has acquired the lock to the profile list |
1503 | * and the software VSI handle has been validated |
1504 | */ |
1505 | static int |
1506 | ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, |
1507 | struct ice_flow_prof *prof, u16 vsi_handle) |
1508 | { |
1509 | int status = 0; |
1510 | |
1511 | if (test_bit(vsi_handle, prof->vsis)) { |
1512 | status = ice_rem_prof_id_flow(hw, blk, |
1513 | vsi: ice_get_hw_vsi_num(hw, |
1514 | vsi_handle), |
1515 | hdl: prof->id); |
1516 | if (!status) |
1517 | clear_bit(nr: vsi_handle, addr: prof->vsis); |
1518 | else |
1519 | ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n" , |
1520 | status); |
1521 | } |
1522 | |
1523 | return status; |
1524 | } |
1525 | |
1526 | /** |
1527 | * ice_flow_add_prof - Add a flow profile for packet segments and matched fields |
1528 | * @hw: pointer to the HW struct |
1529 | * @blk: classification stage |
1530 | * @dir: flow direction |
1531 | * @segs: array of one or more packet segments that describe the flow |
1532 | * @segs_cnt: number of packet segments provided |
1533 | * @symm: symmetric setting for RSS profiles |
1534 | * @prof: stores the returned flow profile added |
1535 | */ |
1536 | int |
1537 | ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, |
1538 | struct ice_flow_seg_info *segs, u8 segs_cnt, |
1539 | bool symm, struct ice_flow_prof **prof) |
1540 | { |
1541 | int status; |
1542 | |
1543 | if (segs_cnt > ICE_FLOW_SEG_MAX) |
1544 | return -ENOSPC; |
1545 | |
1546 | if (!segs_cnt) |
1547 | return -EINVAL; |
1548 | |
1549 | if (!segs) |
1550 | return -EINVAL; |
1551 | |
1552 | status = ice_flow_val_hdrs(segs, segs_cnt); |
1553 | if (status) |
1554 | return status; |
1555 | |
1556 | mutex_lock(&hw->fl_profs_locks[blk]); |
1557 | |
1558 | status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt, |
1559 | symm, prof); |
1560 | if (!status) |
1561 | list_add(new: &(*prof)->l_entry, head: &hw->fl_profs[blk]); |
1562 | |
1563 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1564 | |
1565 | return status; |
1566 | } |
1567 | |
1568 | /** |
1569 | * ice_flow_rem_prof - Remove a flow profile and all entries associated with it |
1570 | * @hw: pointer to the HW struct |
1571 | * @blk: the block for which the flow profile is to be removed |
1572 | * @prof_id: unique ID of the flow profile to be removed |
1573 | */ |
1574 | int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) |
1575 | { |
1576 | struct ice_flow_prof *prof; |
1577 | int status; |
1578 | |
1579 | mutex_lock(&hw->fl_profs_locks[blk]); |
1580 | |
1581 | prof = ice_flow_find_prof_id(hw, blk, prof_id); |
1582 | if (!prof) { |
1583 | status = -ENOENT; |
1584 | goto out; |
1585 | } |
1586 | |
1587 | /* prof becomes invalid after the call */ |
1588 | status = ice_flow_rem_prof_sync(hw, blk, prof); |
1589 | |
1590 | out: |
1591 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1592 | |
1593 | return status; |
1594 | } |
1595 | |
1596 | /** |
1597 | * ice_flow_add_entry - Add a flow entry |
1598 | * @hw: pointer to the HW struct |
1599 | * @blk: classification stage |
1600 | * @prof_id: ID of the profile to add a new flow entry to |
1601 | * @entry_id: unique ID to identify this flow entry |
1602 | * @vsi_handle: software VSI handle for the flow entry |
1603 | * @prio: priority of the flow entry |
1604 | * @data: pointer to a data buffer containing flow entry's match values/masks |
1605 | * @entry_h: pointer to buffer that receives the new flow entry's handle |
1606 | */ |
1607 | int |
1608 | ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, |
1609 | u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, |
1610 | void *data, u64 *entry_h) |
1611 | { |
1612 | struct ice_flow_entry *e = NULL; |
1613 | struct ice_flow_prof *prof; |
1614 | int status; |
1615 | |
1616 | /* No flow entry data is expected for RSS */ |
1617 | if (!entry_h || (!data && blk != ICE_BLK_RSS)) |
1618 | return -EINVAL; |
1619 | |
1620 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1621 | return -EINVAL; |
1622 | |
1623 | mutex_lock(&hw->fl_profs_locks[blk]); |
1624 | |
1625 | prof = ice_flow_find_prof_id(hw, blk, prof_id); |
1626 | if (!prof) { |
1627 | status = -ENOENT; |
1628 | } else { |
1629 | /* Allocate memory for the entry being added and associate |
1630 | * the VSI to the found flow profile |
1631 | */ |
1632 | e = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*e), GFP_KERNEL); |
1633 | if (!e) |
1634 | status = -ENOMEM; |
1635 | else |
1636 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
1637 | } |
1638 | |
1639 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1640 | if (status) |
1641 | goto out; |
1642 | |
1643 | e->id = entry_id; |
1644 | e->vsi_handle = vsi_handle; |
1645 | e->prof = prof; |
1646 | e->priority = prio; |
1647 | |
1648 | switch (blk) { |
1649 | case ICE_BLK_FD: |
1650 | case ICE_BLK_RSS: |
1651 | break; |
1652 | default: |
1653 | status = -EOPNOTSUPP; |
1654 | goto out; |
1655 | } |
1656 | |
1657 | mutex_lock(&prof->entries_lock); |
1658 | list_add(new: &e->l_entry, head: &prof->entries); |
1659 | mutex_unlock(lock: &prof->entries_lock); |
1660 | |
1661 | *entry_h = ICE_FLOW_ENTRY_HNDL(e); |
1662 | |
1663 | out: |
1664 | if (status) |
1665 | devm_kfree(dev: ice_hw_to_dev(hw), p: e); |
1666 | |
1667 | return status; |
1668 | } |
1669 | |
1670 | /** |
1671 | * ice_flow_rem_entry - Remove a flow entry |
1672 | * @hw: pointer to the HW struct |
1673 | * @blk: classification stage |
1674 | * @entry_h: handle to the flow entry to be removed |
1675 | */ |
1676 | int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h) |
1677 | { |
1678 | struct ice_flow_entry *entry; |
1679 | struct ice_flow_prof *prof; |
1680 | int status = 0; |
1681 | |
1682 | if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) |
1683 | return -EINVAL; |
1684 | |
1685 | entry = ICE_FLOW_ENTRY_PTR(entry_h); |
1686 | |
1687 | /* Retain the pointer to the flow profile as the entry will be freed */ |
1688 | prof = entry->prof; |
1689 | |
1690 | if (prof) { |
1691 | mutex_lock(&prof->entries_lock); |
1692 | status = ice_flow_rem_entry_sync(hw, blk, entry); |
1693 | mutex_unlock(lock: &prof->entries_lock); |
1694 | } |
1695 | |
1696 | return status; |
1697 | } |
1698 | |
1699 | /** |
1700 | * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer |
1701 | * @seg: packet segment the field being set belongs to |
1702 | * @fld: field to be set |
1703 | * @field_type: type of the field |
1704 | * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from |
1705 | * entry's input buffer |
1706 | * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's |
1707 | * input buffer |
1708 | * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from |
1709 | * entry's input buffer |
1710 | * |
1711 | * This helper function stores information of a field being matched, including |
1712 | * the type of the field and the locations of the value to match, the mask, and |
1713 | * the upper-bound value in the start of the input buffer for a flow entry. |
1714 | * This function should only be used for fixed-size data structures. |
1715 | * |
1716 | * This function also opportunistically determines the protocol headers to be |
1717 | * present based on the fields being set. Some fields cannot be used alone to |
1718 | * determine the protocol headers present. Sometimes, fields for particular |
1719 | * protocol headers are not matched. In those cases, the protocol headers |
1720 | * must be explicitly set. |
1721 | */ |
1722 | static void |
1723 | ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, |
1724 | enum ice_flow_fld_match_type field_type, u16 val_loc, |
1725 | u16 mask_loc, u16 last_loc) |
1726 | { |
1727 | u64 bit = BIT_ULL(fld); |
1728 | |
1729 | seg->match |= bit; |
1730 | if (field_type == ICE_FLOW_FLD_TYPE_RANGE) |
1731 | seg->range |= bit; |
1732 | |
1733 | seg->fields[fld].type = field_type; |
1734 | seg->fields[fld].src.val = val_loc; |
1735 | seg->fields[fld].src.mask = mask_loc; |
1736 | seg->fields[fld].src.last = last_loc; |
1737 | |
1738 | ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); |
1739 | } |
1740 | |
1741 | /** |
1742 | * ice_flow_set_fld - specifies locations of field from entry's input buffer |
1743 | * @seg: packet segment the field being set belongs to |
1744 | * @fld: field to be set |
1745 | * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from |
1746 | * entry's input buffer |
1747 | * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's |
1748 | * input buffer |
1749 | * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from |
1750 | * entry's input buffer |
1751 | * @range: indicate if field being matched is to be in a range |
1752 | * |
1753 | * This function specifies the locations, in the form of byte offsets from the |
1754 | * start of the input buffer for a flow entry, from where the value to match, |
1755 | * the mask value, and upper value can be extracted. These locations are then |
1756 | * stored in the flow profile. When adding a flow entry associated with the |
1757 | * flow profile, these locations will be used to quickly extract the values and |
1758 | * create the content of a match entry. This function should only be used for |
1759 | * fixed-size data structures. |
1760 | */ |
1761 | void |
1762 | ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, |
1763 | u16 val_loc, u16 mask_loc, u16 last_loc, bool range) |
1764 | { |
1765 | enum ice_flow_fld_match_type t = range ? |
1766 | ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; |
1767 | |
1768 | ice_flow_set_fld_ext(seg, fld, field_type: t, val_loc, mask_loc, last_loc); |
1769 | } |
1770 | |
1771 | /** |
1772 | * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf |
1773 | * @seg: packet segment the field being set belongs to |
1774 | * @off: offset of the raw field from the beginning of the segment in bytes |
1775 | * @len: length of the raw pattern to be matched |
1776 | * @val_loc: location of the value to match from entry's input buffer |
1777 | * @mask_loc: location of mask value from entry's input buffer |
1778 | * |
1779 | * This function specifies the offset of the raw field to be match from the |
1780 | * beginning of the specified packet segment, and the locations, in the form of |
1781 | * byte offsets from the start of the input buffer for a flow entry, from where |
1782 | * the value to match and the mask value to be extracted. These locations are |
1783 | * then stored in the flow profile. When adding flow entries to the associated |
1784 | * flow profile, these locations can be used to quickly extract the values to |
1785 | * create the content of a match entry. This function should only be used for |
1786 | * fixed-size data structures. |
1787 | */ |
1788 | void |
1789 | ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, |
1790 | u16 val_loc, u16 mask_loc) |
1791 | { |
1792 | if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { |
1793 | seg->raws[seg->raws_cnt].off = off; |
1794 | seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; |
1795 | seg->raws[seg->raws_cnt].info.src.val = val_loc; |
1796 | seg->raws[seg->raws_cnt].info.src.mask = mask_loc; |
1797 | /* The "last" field is used to store the length of the field */ |
1798 | seg->raws[seg->raws_cnt].info.src.last = len; |
1799 | } |
1800 | |
1801 | /* Overflows of "raws" will be handled as an error condition later in |
1802 | * the flow when this information is processed. |
1803 | */ |
1804 | seg->raws_cnt++; |
1805 | } |
1806 | |
1807 | /** |
1808 | * ice_flow_rem_vsi_prof - remove VSI from flow profile |
1809 | * @hw: pointer to the hardware structure |
1810 | * @vsi_handle: software VSI handle |
1811 | * @prof_id: unique ID to identify this flow profile |
1812 | * |
1813 | * This function removes the flow entries associated to the input |
1814 | * VSI handle and disassociate the VSI from the flow profile. |
1815 | */ |
1816 | int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id) |
1817 | { |
1818 | struct ice_flow_prof *prof; |
1819 | int status = 0; |
1820 | |
1821 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1822 | return -EINVAL; |
1823 | |
1824 | /* find flow profile pointer with input package block and profile ID */ |
1825 | prof = ice_flow_find_prof_id(hw, blk: ICE_BLK_FD, prof_id); |
1826 | if (!prof) { |
1827 | ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n" , |
1828 | prof_id); |
1829 | return -ENOENT; |
1830 | } |
1831 | |
1832 | /* Remove all remaining flow entries before removing the flow profile */ |
1833 | if (!list_empty(head: &prof->entries)) { |
1834 | struct ice_flow_entry *e, *t; |
1835 | |
1836 | mutex_lock(&prof->entries_lock); |
1837 | list_for_each_entry_safe(e, t, &prof->entries, l_entry) { |
1838 | if (e->vsi_handle != vsi_handle) |
1839 | continue; |
1840 | |
1841 | status = ice_flow_rem_entry_sync(hw, blk: ICE_BLK_FD, entry: e); |
1842 | if (status) |
1843 | break; |
1844 | } |
1845 | mutex_unlock(lock: &prof->entries_lock); |
1846 | } |
1847 | if (status) |
1848 | return status; |
1849 | |
1850 | /* disassociate the flow profile from sw VSI handle */ |
1851 | status = ice_flow_disassoc_prof(hw, blk: ICE_BLK_FD, prof, vsi_handle); |
1852 | if (status) |
1853 | ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n" , |
1854 | status); |
1855 | return status; |
1856 | } |
1857 | |
1858 | #define \ |
1859 | (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) |
1860 | |
1861 | #define \ |
1862 | (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) |
1863 | |
1864 | #define \ |
1865 | (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) |
1866 | |
1867 | #define \ |
1868 | (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ |
1869 | ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ |
1870 | ICE_FLOW_RSS_SEG_HDR_L4_MASKS) |
1871 | |
1872 | /** |
1873 | * ice_flow_set_rss_seg_info - setup packet segments for RSS |
1874 | * @segs: pointer to the flow field segment(s) |
1875 | * @seg_cnt: segment count |
1876 | * @cfg: configure parameters |
1877 | * |
1878 | * Helper function to extract fields from hash bitmap and use flow |
1879 | * header value to set flow field segment for further use in flow |
1880 | * profile entry or removal. |
1881 | */ |
1882 | static int |
1883 | (struct ice_flow_seg_info *segs, u8 seg_cnt, |
1884 | const struct ice_rss_hash_cfg *cfg) |
1885 | { |
1886 | struct ice_flow_seg_info *seg; |
1887 | u64 val; |
1888 | u16 i; |
1889 | |
1890 | /* set inner most segment */ |
1891 | seg = &segs[seg_cnt - 1]; |
1892 | |
1893 | for_each_set_bit(i, (const unsigned long *)&cfg->hash_flds, |
1894 | (u16)ICE_FLOW_FIELD_IDX_MAX) |
1895 | ice_flow_set_fld(seg, fld: (enum ice_flow_field)i, |
1896 | ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, |
1897 | ICE_FLOW_FLD_OFF_INVAL, range: false); |
1898 | |
1899 | ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); |
1900 | |
1901 | /* set outer most header */ |
1902 | if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) |
1903 | segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | |
1904 | ICE_FLOW_SEG_HDR_IPV_OTHER; |
1905 | else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) |
1906 | segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | |
1907 | ICE_FLOW_SEG_HDR_IPV_OTHER; |
1908 | |
1909 | if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & |
1910 | ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) |
1911 | return -EINVAL; |
1912 | |
1913 | val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); |
1914 | if (val && !is_power_of_2(n: val)) |
1915 | return -EIO; |
1916 | |
1917 | val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); |
1918 | if (val && !is_power_of_2(n: val)) |
1919 | return -EIO; |
1920 | |
1921 | return 0; |
1922 | } |
1923 | |
1924 | /** |
1925 | * ice_rem_vsi_rss_list - remove VSI from RSS list |
1926 | * @hw: pointer to the hardware structure |
1927 | * @vsi_handle: software VSI handle |
1928 | * |
1929 | * Remove the VSI from all RSS configurations in the list. |
1930 | */ |
1931 | void (struct ice_hw *hw, u16 vsi_handle) |
1932 | { |
1933 | struct ice_rss_cfg *r, *tmp; |
1934 | |
1935 | if (list_empty(head: &hw->rss_list_head)) |
1936 | return; |
1937 | |
1938 | mutex_lock(&hw->rss_locks); |
1939 | list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) |
1940 | if (test_and_clear_bit(nr: vsi_handle, addr: r->vsis)) |
1941 | if (bitmap_empty(src: r->vsis, ICE_MAX_VSI)) { |
1942 | list_del(entry: &r->l_entry); |
1943 | devm_kfree(dev: ice_hw_to_dev(hw), p: r); |
1944 | } |
1945 | mutex_unlock(lock: &hw->rss_locks); |
1946 | } |
1947 | |
1948 | /** |
1949 | * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI |
1950 | * @hw: pointer to the hardware structure |
1951 | * @vsi_handle: software VSI handle |
1952 | * |
1953 | * This function will iterate through all flow profiles and disassociate |
1954 | * the VSI from that profile. If the flow profile has no VSIs it will |
1955 | * be removed. |
1956 | */ |
1957 | int (struct ice_hw *hw, u16 vsi_handle) |
1958 | { |
1959 | const enum ice_block blk = ICE_BLK_RSS; |
1960 | struct ice_flow_prof *p, *t; |
1961 | int status = 0; |
1962 | |
1963 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1964 | return -EINVAL; |
1965 | |
1966 | if (list_empty(head: &hw->fl_profs[blk])) |
1967 | return 0; |
1968 | |
1969 | mutex_lock(&hw->rss_locks); |
1970 | list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry) |
1971 | if (test_bit(vsi_handle, p->vsis)) { |
1972 | status = ice_flow_disassoc_prof(hw, blk, prof: p, vsi_handle); |
1973 | if (status) |
1974 | break; |
1975 | |
1976 | if (bitmap_empty(src: p->vsis, ICE_MAX_VSI)) { |
1977 | status = ice_flow_rem_prof(hw, blk, prof_id: p->id); |
1978 | if (status) |
1979 | break; |
1980 | } |
1981 | } |
1982 | mutex_unlock(lock: &hw->rss_locks); |
1983 | |
1984 | return status; |
1985 | } |
1986 | |
1987 | /** |
1988 | * ice_get_rss_hdr_type - get a RSS profile's header type |
1989 | * @prof: RSS flow profile |
1990 | */ |
1991 | static enum ice_rss_cfg_hdr_type |
1992 | (struct ice_flow_prof *prof) |
1993 | { |
1994 | if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { |
1995 | return ICE_RSS_OUTER_HEADERS; |
1996 | } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { |
1997 | const struct ice_flow_seg_info *s; |
1998 | |
1999 | s = &prof->segs[ICE_RSS_OUTER_HEADERS]; |
2000 | if (s->hdrs == ICE_FLOW_SEG_HDR_NONE) |
2001 | return ICE_RSS_INNER_HEADERS; |
2002 | if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4) |
2003 | return ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; |
2004 | if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6) |
2005 | return ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; |
2006 | } |
2007 | |
2008 | return ICE_RSS_ANY_HEADERS; |
2009 | } |
2010 | |
2011 | static bool |
2012 | (struct ice_rss_cfg *r, struct ice_flow_prof *prof, |
2013 | enum ice_rss_cfg_hdr_type hdr_type) |
2014 | { |
2015 | return (r->hash.hdr_type == hdr_type && |
2016 | r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match && |
2017 | r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs); |
2018 | } |
2019 | |
2020 | /** |
2021 | * ice_rem_rss_list - remove RSS configuration from list |
2022 | * @hw: pointer to the hardware structure |
2023 | * @vsi_handle: software VSI handle |
2024 | * @prof: pointer to flow profile |
2025 | * |
2026 | * Assumption: lock has already been acquired for RSS list |
2027 | */ |
2028 | static void |
2029 | (struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) |
2030 | { |
2031 | enum ice_rss_cfg_hdr_type hdr_type; |
2032 | struct ice_rss_cfg *r, *tmp; |
2033 | |
2034 | /* Search for RSS hash fields associated to the VSI that match the |
2035 | * hash configurations associated to the flow profile. If found |
2036 | * remove from the RSS entry list of the VSI context and delete entry. |
2037 | */ |
2038 | hdr_type = ice_get_rss_hdr_type(prof); |
2039 | list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) |
2040 | if (ice_rss_match_prof(r, prof, hdr_type)) { |
2041 | clear_bit(nr: vsi_handle, addr: r->vsis); |
2042 | if (bitmap_empty(src: r->vsis, ICE_MAX_VSI)) { |
2043 | list_del(entry: &r->l_entry); |
2044 | devm_kfree(dev: ice_hw_to_dev(hw), p: r); |
2045 | } |
2046 | return; |
2047 | } |
2048 | } |
2049 | |
2050 | /** |
2051 | * ice_add_rss_list - add RSS configuration to list |
2052 | * @hw: pointer to the hardware structure |
2053 | * @vsi_handle: software VSI handle |
2054 | * @prof: pointer to flow profile |
2055 | * |
2056 | * Assumption: lock has already been acquired for RSS list |
2057 | */ |
2058 | static int |
2059 | (struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) |
2060 | { |
2061 | enum ice_rss_cfg_hdr_type hdr_type; |
2062 | struct ice_rss_cfg *r, *; |
2063 | |
2064 | hdr_type = ice_get_rss_hdr_type(prof); |
2065 | list_for_each_entry(r, &hw->rss_list_head, l_entry) |
2066 | if (ice_rss_match_prof(r, prof, hdr_type)) { |
2067 | set_bit(nr: vsi_handle, addr: r->vsis); |
2068 | return 0; |
2069 | } |
2070 | |
2071 | rss_cfg = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*rss_cfg), |
2072 | GFP_KERNEL); |
2073 | if (!rss_cfg) |
2074 | return -ENOMEM; |
2075 | |
2076 | rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match; |
2077 | rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; |
2078 | rss_cfg->hash.hdr_type = hdr_type; |
2079 | rss_cfg->hash.symm = prof->symm; |
2080 | set_bit(nr: vsi_handle, addr: rss_cfg->vsis); |
2081 | |
2082 | list_add_tail(new: &rss_cfg->l_entry, head: &hw->rss_list_head); |
2083 | |
2084 | return 0; |
2085 | } |
2086 | |
2087 | /** |
2088 | * ice_rss_config_xor_word - set the HSYMM registers for one input set word |
2089 | * @hw: pointer to the hardware structure |
2090 | * @prof_id: RSS hardware profile id |
2091 | * @src: the FV index used by the protocol's source field |
2092 | * @dst: the FV index used by the protocol's destination field |
2093 | * |
2094 | * Write to the HSYMM register with the index of @src FV the value of the @dst |
2095 | * FV index. This will tell the hardware to XOR HSYMM[src] with INSET[dst] |
2096 | * while calculating the RSS input set. |
2097 | */ |
2098 | static void |
2099 | (struct ice_hw *hw, u8 prof_id, u8 src, u8 dst) |
2100 | { |
2101 | u32 val, reg, bits_shift; |
2102 | u8 reg_idx; |
2103 | |
2104 | reg_idx = src / GLQF_HSYMM_REG_SIZE; |
2105 | bits_shift = ((src % GLQF_HSYMM_REG_SIZE) << 3); |
2106 | val = dst | GLQF_HSYMM_ENABLE_BIT; |
2107 | |
2108 | reg = rd32(hw, GLQF_HSYMM(prof_id, reg_idx)); |
2109 | reg = (reg & ~(0xff << bits_shift)) | (val << bits_shift); |
2110 | wr32(hw, GLQF_HSYMM(prof_id, reg_idx), reg); |
2111 | } |
2112 | |
2113 | /** |
2114 | * ice_rss_config_xor - set the symmetric registers for a profile's protocol |
2115 | * @hw: pointer to the hardware structure |
2116 | * @prof_id: RSS hardware profile id |
2117 | * @src: the FV index used by the protocol's source field |
2118 | * @dst: the FV index used by the protocol's destination field |
2119 | * @len: length of the source/destination fields in words |
2120 | */ |
2121 | static void |
2122 | (struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len) |
2123 | { |
2124 | int fv_last_word = |
2125 | ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1; |
2126 | int i; |
2127 | |
2128 | for (i = 0; i < len; i++) { |
2129 | ice_rss_config_xor_word(hw, prof_id, |
2130 | /* Yes, field vector in GLQF_HSYMM and |
2131 | * GLQF_HINSET is inversed! |
2132 | */ |
2133 | src: fv_last_word - (src + i), |
2134 | dst: fv_last_word - (dst + i)); |
2135 | ice_rss_config_xor_word(hw, prof_id, |
2136 | src: fv_last_word - (dst + i), |
2137 | dst: fv_last_word - (src + i)); |
2138 | } |
2139 | } |
2140 | |
2141 | /** |
2142 | * ice_rss_set_symm - set the symmetric settings for an RSS profile |
2143 | * @hw: pointer to the hardware structure |
2144 | * @prof: pointer to flow profile |
2145 | * |
2146 | * The symmetric hash will result from XORing the protocol's fields with |
2147 | * indexes in GLQF_HSYMM and GLQF_HINSET. This function configures the profile's |
2148 | * GLQF_HSYMM registers. |
2149 | */ |
2150 | static void (struct ice_hw *hw, struct ice_flow_prof *prof) |
2151 | { |
2152 | struct ice_prof_map *map; |
2153 | u8 prof_id, m; |
2154 | |
2155 | mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock); |
2156 | map = ice_search_prof_id(hw, blk: ICE_BLK_RSS, id: prof->id); |
2157 | if (map) |
2158 | prof_id = map->prof_id; |
2159 | mutex_unlock(lock: &hw->blk[ICE_BLK_RSS].es.prof_map_lock); |
2160 | |
2161 | if (!map) |
2162 | return; |
2163 | |
2164 | /* clear to default */ |
2165 | for (m = 0; m < GLQF_HSYMM_REG_PER_PROF; m++) |
2166 | wr32(hw, GLQF_HSYMM(prof_id, m), 0); |
2167 | |
2168 | if (prof->symm) { |
2169 | struct ice_flow_seg_xtrct *ipv4_src, *ipv4_dst; |
2170 | struct ice_flow_seg_xtrct *ipv6_src, *ipv6_dst; |
2171 | struct ice_flow_seg_xtrct *sctp_src, *sctp_dst; |
2172 | struct ice_flow_seg_xtrct *tcp_src, *tcp_dst; |
2173 | struct ice_flow_seg_xtrct *udp_src, *udp_dst; |
2174 | struct ice_flow_seg_info *seg; |
2175 | |
2176 | seg = &prof->segs[prof->segs_cnt - 1]; |
2177 | |
2178 | ipv4_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct; |
2179 | ipv4_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct; |
2180 | |
2181 | ipv6_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct; |
2182 | ipv6_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct; |
2183 | |
2184 | tcp_src = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct; |
2185 | tcp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct; |
2186 | |
2187 | udp_src = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct; |
2188 | udp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct; |
2189 | |
2190 | sctp_src = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct; |
2191 | sctp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct; |
2192 | |
2193 | /* xor IPv4 */ |
2194 | if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0) |
2195 | ice_rss_config_xor(hw, prof_id, |
2196 | src: ipv4_src->idx, dst: ipv4_dst->idx, len: 2); |
2197 | |
2198 | /* xor IPv6 */ |
2199 | if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0) |
2200 | ice_rss_config_xor(hw, prof_id, |
2201 | src: ipv6_src->idx, dst: ipv6_dst->idx, len: 8); |
2202 | |
2203 | /* xor TCP */ |
2204 | if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0) |
2205 | ice_rss_config_xor(hw, prof_id, |
2206 | src: tcp_src->idx, dst: tcp_dst->idx, len: 1); |
2207 | |
2208 | /* xor UDP */ |
2209 | if (udp_src->prot_id != 0 && udp_dst->prot_id != 0) |
2210 | ice_rss_config_xor(hw, prof_id, |
2211 | src: udp_src->idx, dst: udp_dst->idx, len: 1); |
2212 | |
2213 | /* xor SCTP */ |
2214 | if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0) |
2215 | ice_rss_config_xor(hw, prof_id, |
2216 | src: sctp_src->idx, dst: sctp_dst->idx, len: 1); |
2217 | } |
2218 | } |
2219 | |
2220 | /** |
2221 | * ice_add_rss_cfg_sync - add an RSS configuration |
2222 | * @hw: pointer to the hardware structure |
2223 | * @vsi_handle: software VSI handle |
2224 | * @cfg: configure parameters |
2225 | * |
2226 | * Assumption: lock has already been acquired for RSS list |
2227 | */ |
2228 | static int |
2229 | (struct ice_hw *hw, u16 vsi_handle, |
2230 | const struct ice_rss_hash_cfg *cfg) |
2231 | { |
2232 | const enum ice_block blk = ICE_BLK_RSS; |
2233 | struct ice_flow_prof *prof = NULL; |
2234 | struct ice_flow_seg_info *segs; |
2235 | u8 segs_cnt; |
2236 | int status; |
2237 | |
2238 | segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? |
2239 | ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; |
2240 | |
2241 | segs = kcalloc(n: segs_cnt, size: sizeof(*segs), GFP_KERNEL); |
2242 | if (!segs) |
2243 | return -ENOMEM; |
2244 | |
2245 | /* Construct the packet segment info from the hashed fields */ |
2246 | status = ice_flow_set_rss_seg_info(segs, seg_cnt: segs_cnt, cfg); |
2247 | if (status) |
2248 | goto exit; |
2249 | |
2250 | /* Search for a flow profile that has matching headers, hash fields, |
2251 | * symm and has the input VSI associated to it. If found, no further |
2252 | * operations required and exit. |
2253 | */ |
2254 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2255 | symm: cfg->symm, vsi_handle, |
2256 | ICE_FLOW_FIND_PROF_CHK_FLDS | |
2257 | ICE_FLOW_FIND_PROF_CHK_SYMM | |
2258 | ICE_FLOW_FIND_PROF_CHK_VSI); |
2259 | if (prof) |
2260 | goto exit; |
2261 | |
2262 | /* Check if a flow profile exists with the same protocol headers and |
2263 | * associated with the input VSI. If so disassociate the VSI from |
2264 | * this profile. The VSI will be added to a new profile created with |
2265 | * the protocol header and new hash field configuration. |
2266 | */ |
2267 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2268 | symm: cfg->symm, vsi_handle, |
2269 | ICE_FLOW_FIND_PROF_CHK_VSI); |
2270 | if (prof) { |
2271 | status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); |
2272 | if (!status) |
2273 | ice_rem_rss_list(hw, vsi_handle, prof); |
2274 | else |
2275 | goto exit; |
2276 | |
2277 | /* Remove profile if it has no VSIs associated */ |
2278 | if (bitmap_empty(src: prof->vsis, ICE_MAX_VSI)) { |
2279 | status = ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2280 | if (status) |
2281 | goto exit; |
2282 | } |
2283 | } |
2284 | |
2285 | /* Search for a profile that has the same match fields and symmetric |
2286 | * setting. If this exists then associate the VSI to this profile. |
2287 | */ |
2288 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2289 | symm: cfg->symm, vsi_handle, |
2290 | ICE_FLOW_FIND_PROF_CHK_SYMM | |
2291 | ICE_FLOW_FIND_PROF_CHK_FLDS); |
2292 | if (prof) { |
2293 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
2294 | if (!status) |
2295 | status = ice_add_rss_list(hw, vsi_handle, prof); |
2296 | goto exit; |
2297 | } |
2298 | |
2299 | /* Create a new flow profile with packet segment information. */ |
2300 | status = ice_flow_add_prof(hw, blk, dir: ICE_FLOW_RX, |
2301 | segs, segs_cnt, symm: cfg->symm, prof: &prof); |
2302 | if (status) |
2303 | goto exit; |
2304 | |
2305 | prof->symm = cfg->symm; |
2306 | ice_rss_set_symm(hw, prof); |
2307 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
2308 | /* If association to a new flow profile failed then this profile can |
2309 | * be removed. |
2310 | */ |
2311 | if (status) { |
2312 | ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2313 | goto exit; |
2314 | } |
2315 | |
2316 | status = ice_add_rss_list(hw, vsi_handle, prof); |
2317 | |
2318 | exit: |
2319 | kfree(objp: segs); |
2320 | return status; |
2321 | } |
2322 | |
2323 | /** |
2324 | * ice_add_rss_cfg - add an RSS configuration with specified hashed fields |
2325 | * @hw: pointer to the hardware structure |
2326 | * @vsi: VSI to add the RSS configuration to |
2327 | * @cfg: configure parameters |
2328 | * |
2329 | * This function will generate a flow profile based on fields associated with |
2330 | * the input fields to hash on, the flow type and use the VSI number to add |
2331 | * a flow entry to the profile. |
2332 | */ |
2333 | int |
2334 | (struct ice_hw *hw, struct ice_vsi *vsi, |
2335 | const struct ice_rss_hash_cfg *cfg) |
2336 | { |
2337 | struct ice_rss_hash_cfg local_cfg; |
2338 | u16 vsi_handle; |
2339 | int status; |
2340 | |
2341 | if (!vsi) |
2342 | return -EINVAL; |
2343 | |
2344 | vsi_handle = vsi->idx; |
2345 | if (!ice_is_vsi_valid(hw, vsi_handle) || |
2346 | !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || |
2347 | cfg->hash_flds == ICE_HASH_INVALID) |
2348 | return -EINVAL; |
2349 | |
2350 | mutex_lock(&hw->rss_locks); |
2351 | local_cfg = *cfg; |
2352 | if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { |
2353 | status = ice_add_rss_cfg_sync(hw, vsi_handle, cfg: &local_cfg); |
2354 | } else { |
2355 | local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; |
2356 | status = ice_add_rss_cfg_sync(hw, vsi_handle, cfg: &local_cfg); |
2357 | if (!status) { |
2358 | local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; |
2359 | status = ice_add_rss_cfg_sync(hw, vsi_handle, |
2360 | cfg: &local_cfg); |
2361 | } |
2362 | } |
2363 | mutex_unlock(lock: &hw->rss_locks); |
2364 | |
2365 | return status; |
2366 | } |
2367 | |
2368 | /** |
2369 | * ice_rem_rss_cfg_sync - remove an existing RSS configuration |
2370 | * @hw: pointer to the hardware structure |
2371 | * @vsi_handle: software VSI handle |
2372 | * @cfg: configure parameters |
2373 | * |
2374 | * Assumption: lock has already been acquired for RSS list |
2375 | */ |
2376 | static int |
2377 | (struct ice_hw *hw, u16 vsi_handle, |
2378 | const struct ice_rss_hash_cfg *cfg) |
2379 | { |
2380 | const enum ice_block blk = ICE_BLK_RSS; |
2381 | struct ice_flow_seg_info *segs; |
2382 | struct ice_flow_prof *prof; |
2383 | u8 segs_cnt; |
2384 | int status; |
2385 | |
2386 | segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? |
2387 | ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX; |
2388 | segs = kcalloc(n: segs_cnt, size: sizeof(*segs), GFP_KERNEL); |
2389 | if (!segs) |
2390 | return -ENOMEM; |
2391 | |
2392 | /* Construct the packet segment info from the hashed fields */ |
2393 | status = ice_flow_set_rss_seg_info(segs, seg_cnt: segs_cnt, cfg); |
2394 | if (status) |
2395 | goto out; |
2396 | |
2397 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2398 | symm: cfg->symm, vsi_handle, |
2399 | ICE_FLOW_FIND_PROF_CHK_FLDS); |
2400 | if (!prof) { |
2401 | status = -ENOENT; |
2402 | goto out; |
2403 | } |
2404 | |
2405 | status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); |
2406 | if (status) |
2407 | goto out; |
2408 | |
2409 | /* Remove RSS configuration from VSI context before deleting |
2410 | * the flow profile. |
2411 | */ |
2412 | ice_rem_rss_list(hw, vsi_handle, prof); |
2413 | |
2414 | if (bitmap_empty(src: prof->vsis, ICE_MAX_VSI)) |
2415 | status = ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2416 | |
2417 | out: |
2418 | kfree(objp: segs); |
2419 | return status; |
2420 | } |
2421 | |
2422 | /** |
2423 | * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields |
2424 | * @hw: pointer to the hardware structure |
2425 | * @vsi_handle: software VSI handle |
2426 | * @cfg: configure parameters |
2427 | * |
2428 | * This function will lookup the flow profile based on the input |
2429 | * hash field bitmap, iterate through the profile entry list of |
2430 | * that profile and find entry associated with input VSI to be |
2431 | * removed. Calls are made to underlying flow apis which will in |
2432 | * turn build or update buffers for RSS XLT1 section. |
2433 | */ |
2434 | int |
2435 | (struct ice_hw *hw, u16 vsi_handle, |
2436 | const struct ice_rss_hash_cfg *cfg) |
2437 | { |
2438 | struct ice_rss_hash_cfg local_cfg; |
2439 | int status; |
2440 | |
2441 | if (!ice_is_vsi_valid(hw, vsi_handle) || |
2442 | !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS || |
2443 | cfg->hash_flds == ICE_HASH_INVALID) |
2444 | return -EINVAL; |
2445 | |
2446 | mutex_lock(&hw->rss_locks); |
2447 | local_cfg = *cfg; |
2448 | if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { |
2449 | status = ice_rem_rss_cfg_sync(hw, vsi_handle, cfg: &local_cfg); |
2450 | } else { |
2451 | local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; |
2452 | status = ice_rem_rss_cfg_sync(hw, vsi_handle, cfg: &local_cfg); |
2453 | if (!status) { |
2454 | local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; |
2455 | status = ice_rem_rss_cfg_sync(hw, vsi_handle, |
2456 | cfg: &local_cfg); |
2457 | } |
2458 | } |
2459 | mutex_unlock(lock: &hw->rss_locks); |
2460 | |
2461 | return status; |
2462 | } |
2463 | |
2464 | /* Mapping of AVF hash bit fields to an L3-L4 hash combination. |
2465 | * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, |
2466 | * convert its values to their appropriate flow L3, L4 values. |
2467 | */ |
2468 | #define \ |
2469 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ |
2470 | BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) |
2471 | #define \ |
2472 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ |
2473 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) |
2474 | #define \ |
2475 | (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ |
2476 | BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ |
2477 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) |
2478 | #define \ |
2479 | (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ |
2480 | ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) |
2481 | |
2482 | #define \ |
2483 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ |
2484 | BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) |
2485 | #define \ |
2486 | (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ |
2487 | BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ |
2488 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) |
2489 | #define \ |
2490 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ |
2491 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) |
2492 | #define \ |
2493 | (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ |
2494 | ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) |
2495 | |
2496 | /** |
2497 | * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver |
2498 | * @hw: pointer to the hardware structure |
2499 | * @vsi: VF's VSI |
2500 | * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure |
2501 | * |
2502 | * This function will take the hash bitmap provided by the AVF driver via a |
2503 | * message, convert it to ICE-compatible values, and configure RSS flow |
2504 | * profiles. |
2505 | */ |
2506 | int (struct ice_hw *hw, struct ice_vsi *vsi, u64 avf_hash) |
2507 | { |
2508 | struct ice_rss_hash_cfg hcfg; |
2509 | u16 vsi_handle; |
2510 | int status = 0; |
2511 | u64 hash_flds; |
2512 | |
2513 | if (!vsi) |
2514 | return -EINVAL; |
2515 | |
2516 | vsi_handle = vsi->idx; |
2517 | if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || |
2518 | !ice_is_vsi_valid(hw, vsi_handle)) |
2519 | return -EINVAL; |
2520 | |
2521 | /* Make sure no unsupported bits are specified */ |
2522 | if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | |
2523 | ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) |
2524 | return -EIO; |
2525 | |
2526 | hash_flds = avf_hash; |
2527 | |
2528 | /* Always create an L3 RSS configuration for any L4 RSS configuration */ |
2529 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) |
2530 | hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; |
2531 | |
2532 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) |
2533 | hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; |
2534 | |
2535 | /* Create the corresponding RSS configuration for each valid hash bit */ |
2536 | while (hash_flds) { |
2537 | u64 = ICE_HASH_INVALID; |
2538 | |
2539 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { |
2540 | if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { |
2541 | rss_hash = ICE_FLOW_HASH_IPV4; |
2542 | hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; |
2543 | } else if (hash_flds & |
2544 | ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { |
2545 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2546 | ICE_FLOW_HASH_TCP_PORT; |
2547 | hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; |
2548 | } else if (hash_flds & |
2549 | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { |
2550 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2551 | ICE_FLOW_HASH_UDP_PORT; |
2552 | hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; |
2553 | } else if (hash_flds & |
2554 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { |
2555 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2556 | ICE_FLOW_HASH_SCTP_PORT; |
2557 | hash_flds &= |
2558 | ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); |
2559 | } |
2560 | } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { |
2561 | if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { |
2562 | rss_hash = ICE_FLOW_HASH_IPV6; |
2563 | hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; |
2564 | } else if (hash_flds & |
2565 | ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { |
2566 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2567 | ICE_FLOW_HASH_TCP_PORT; |
2568 | hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; |
2569 | } else if (hash_flds & |
2570 | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { |
2571 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2572 | ICE_FLOW_HASH_UDP_PORT; |
2573 | hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; |
2574 | } else if (hash_flds & |
2575 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { |
2576 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2577 | ICE_FLOW_HASH_SCTP_PORT; |
2578 | hash_flds &= |
2579 | ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); |
2580 | } |
2581 | } |
2582 | |
2583 | if (rss_hash == ICE_HASH_INVALID) |
2584 | return -EIO; |
2585 | |
2586 | hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; |
2587 | hcfg.hash_flds = rss_hash; |
2588 | hcfg.hdr_type = ICE_RSS_ANY_HEADERS; |
2589 | hcfg.symm = false; |
2590 | status = ice_add_rss_cfg(hw, vsi, cfg: &hcfg); |
2591 | if (status) |
2592 | break; |
2593 | } |
2594 | |
2595 | return status; |
2596 | } |
2597 | |
2598 | static bool (u64 hfld) |
2599 | { |
2600 | return !((!!(hfld & ICE_FLOW_HASH_FLD_IPV4_SA) ^ |
2601 | !!(hfld & ICE_FLOW_HASH_FLD_IPV4_DA)) || |
2602 | (!!(hfld & ICE_FLOW_HASH_FLD_IPV6_SA) ^ |
2603 | !!(hfld & ICE_FLOW_HASH_FLD_IPV6_DA)) || |
2604 | (!!(hfld & ICE_FLOW_HASH_FLD_TCP_SRC_PORT) ^ |
2605 | !!(hfld & ICE_FLOW_HASH_FLD_TCP_DST_PORT)) || |
2606 | (!!(hfld & ICE_FLOW_HASH_FLD_UDP_SRC_PORT) ^ |
2607 | !!(hfld & ICE_FLOW_HASH_FLD_UDP_DST_PORT)) || |
2608 | (!!(hfld & ICE_FLOW_HASH_FLD_SCTP_SRC_PORT) ^ |
2609 | !!(hfld & ICE_FLOW_HASH_FLD_SCTP_DST_PORT))); |
2610 | } |
2611 | |
2612 | /** |
2613 | * ice_set_rss_cfg_symm - set symmtery for all VSI's RSS configurations |
2614 | * @hw: pointer to the hardware structure |
2615 | * @vsi: VSI to set/unset Symmetric RSS |
2616 | * @symm: TRUE to set Symmetric RSS hashing |
2617 | */ |
2618 | int (struct ice_hw *hw, struct ice_vsi *vsi, bool symm) |
2619 | { |
2620 | struct ice_rss_hash_cfg local; |
2621 | struct ice_rss_cfg *r, *tmp; |
2622 | u16 vsi_handle = vsi->idx; |
2623 | int status = 0; |
2624 | |
2625 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
2626 | return -EINVAL; |
2627 | |
2628 | mutex_lock(&hw->rss_locks); |
2629 | list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) { |
2630 | if (test_bit(vsi_handle, r->vsis) && r->hash.symm != symm) { |
2631 | local = r->hash; |
2632 | local.symm = symm; |
2633 | if (symm && !rss_cfg_symm_valid(hfld: r->hash.hash_flds)) |
2634 | continue; |
2635 | |
2636 | status = ice_add_rss_cfg_sync(hw, vsi_handle, cfg: &local); |
2637 | if (status) |
2638 | break; |
2639 | } |
2640 | } |
2641 | mutex_unlock(lock: &hw->rss_locks); |
2642 | |
2643 | return status; |
2644 | } |
2645 | |
2646 | /** |
2647 | * ice_replay_rss_cfg - replay RSS configurations associated with VSI |
2648 | * @hw: pointer to the hardware structure |
2649 | * @vsi_handle: software VSI handle |
2650 | */ |
2651 | int (struct ice_hw *hw, u16 vsi_handle) |
2652 | { |
2653 | struct ice_rss_cfg *r; |
2654 | int status = 0; |
2655 | |
2656 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
2657 | return -EINVAL; |
2658 | |
2659 | mutex_lock(&hw->rss_locks); |
2660 | list_for_each_entry(r, &hw->rss_list_head, l_entry) { |
2661 | if (test_bit(vsi_handle, r->vsis)) { |
2662 | status = ice_add_rss_cfg_sync(hw, vsi_handle, cfg: &r->hash); |
2663 | if (status) |
2664 | break; |
2665 | } |
2666 | } |
2667 | mutex_unlock(lock: &hw->rss_locks); |
2668 | |
2669 | return status; |
2670 | } |
2671 | |
2672 | /** |
2673 | * ice_get_rss_cfg - returns hashed fields for the given header types |
2674 | * @hw: pointer to the hardware structure |
2675 | * @vsi_handle: software VSI handle |
2676 | * @hdrs: protocol header type |
2677 | * @symm: whether the RSS is symmetric (bool, output) |
2678 | * |
2679 | * This function will return the match fields of the first instance of flow |
2680 | * profile having the given header types and containing input VSI |
2681 | */ |
2682 | u64 (struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm) |
2683 | { |
2684 | u64 = ICE_HASH_INVALID; |
2685 | struct ice_rss_cfg *r; |
2686 | |
2687 | /* verify if the protocol header is non zero and VSI is valid */ |
2688 | if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) |
2689 | return ICE_HASH_INVALID; |
2690 | |
2691 | mutex_lock(&hw->rss_locks); |
2692 | list_for_each_entry(r, &hw->rss_list_head, l_entry) |
2693 | if (test_bit(vsi_handle, r->vsis) && |
2694 | r->hash.addl_hdrs == hdrs) { |
2695 | rss_hash = r->hash.hash_flds; |
2696 | *symm = r->hash.symm; |
2697 | break; |
2698 | } |
2699 | mutex_unlock(lock: &hw->rss_locks); |
2700 | |
2701 | return rss_hash; |
2702 | } |
2703 | |