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 | |
1239 | /** |
1240 | * ice_flow_find_prof_conds - Find a profile matching headers and conditions |
1241 | * @hw: pointer to the HW struct |
1242 | * @blk: classification stage |
1243 | * @dir: flow direction |
1244 | * @segs: array of one or more packet segments that describe the flow |
1245 | * @segs_cnt: number of packet segments provided |
1246 | * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) |
1247 | * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) |
1248 | */ |
1249 | static struct ice_flow_prof * |
1250 | ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, |
1251 | enum ice_flow_dir dir, struct ice_flow_seg_info *segs, |
1252 | u8 segs_cnt, u16 vsi_handle, u32 conds) |
1253 | { |
1254 | struct ice_flow_prof *p, *prof = NULL; |
1255 | |
1256 | mutex_lock(&hw->fl_profs_locks[blk]); |
1257 | list_for_each_entry(p, &hw->fl_profs[blk], l_entry) |
1258 | if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && |
1259 | segs_cnt && segs_cnt == p->segs_cnt) { |
1260 | u8 i; |
1261 | |
1262 | /* Check for profile-VSI association if specified */ |
1263 | if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && |
1264 | ice_is_vsi_valid(hw, vsi_handle) && |
1265 | !test_bit(vsi_handle, p->vsis)) |
1266 | continue; |
1267 | |
1268 | /* Protocol headers must be checked. Matched fields are |
1269 | * checked if specified. |
1270 | */ |
1271 | for (i = 0; i < segs_cnt; i++) |
1272 | if (segs[i].hdrs != p->segs[i].hdrs || |
1273 | ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && |
1274 | segs[i].match != p->segs[i].match)) |
1275 | break; |
1276 | |
1277 | /* A match is found if all segments are matched */ |
1278 | if (i == segs_cnt) { |
1279 | prof = p; |
1280 | break; |
1281 | } |
1282 | } |
1283 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1284 | |
1285 | return prof; |
1286 | } |
1287 | |
1288 | /** |
1289 | * ice_flow_find_prof_id - Look up a profile with given profile ID |
1290 | * @hw: pointer to the HW struct |
1291 | * @blk: classification stage |
1292 | * @prof_id: unique ID to identify this flow profile |
1293 | */ |
1294 | static struct ice_flow_prof * |
1295 | ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) |
1296 | { |
1297 | struct ice_flow_prof *p; |
1298 | |
1299 | list_for_each_entry(p, &hw->fl_profs[blk], l_entry) |
1300 | if (p->id == prof_id) |
1301 | return p; |
1302 | |
1303 | return NULL; |
1304 | } |
1305 | |
1306 | /** |
1307 | * ice_flow_rem_entry_sync - Remove a flow entry |
1308 | * @hw: pointer to the HW struct |
1309 | * @blk: classification stage |
1310 | * @entry: flow entry to be removed |
1311 | */ |
1312 | static int |
1313 | ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk, |
1314 | struct ice_flow_entry *entry) |
1315 | { |
1316 | if (!entry) |
1317 | return -EINVAL; |
1318 | |
1319 | list_del(entry: &entry->l_entry); |
1320 | |
1321 | devm_kfree(dev: ice_hw_to_dev(hw), p: entry); |
1322 | |
1323 | return 0; |
1324 | } |
1325 | |
1326 | /** |
1327 | * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields |
1328 | * @hw: pointer to the HW struct |
1329 | * @blk: classification stage |
1330 | * @dir: flow direction |
1331 | * @prof_id: unique ID to identify this flow profile |
1332 | * @segs: array of one or more packet segments that describe the flow |
1333 | * @segs_cnt: number of packet segments provided |
1334 | * @prof: stores the returned flow profile added |
1335 | * |
1336 | * Assumption: the caller has acquired the lock to the profile list |
1337 | */ |
1338 | static int |
1339 | ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, |
1340 | enum ice_flow_dir dir, u64 prof_id, |
1341 | struct ice_flow_seg_info *segs, u8 segs_cnt, |
1342 | struct ice_flow_prof **prof) |
1343 | { |
1344 | struct ice_flow_prof_params *params; |
1345 | int status; |
1346 | u8 i; |
1347 | |
1348 | if (!prof) |
1349 | return -EINVAL; |
1350 | |
1351 | params = kzalloc(size: sizeof(*params), GFP_KERNEL); |
1352 | if (!params) |
1353 | return -ENOMEM; |
1354 | |
1355 | params->prof = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*params->prof), |
1356 | GFP_KERNEL); |
1357 | if (!params->prof) { |
1358 | status = -ENOMEM; |
1359 | goto free_params; |
1360 | } |
1361 | |
1362 | /* initialize extraction sequence to all invalid (0xff) */ |
1363 | for (i = 0; i < ICE_MAX_FV_WORDS; i++) { |
1364 | params->es[i].prot_id = ICE_PROT_INVALID; |
1365 | params->es[i].off = ICE_FV_OFFSET_INVAL; |
1366 | } |
1367 | |
1368 | params->blk = blk; |
1369 | params->prof->id = prof_id; |
1370 | params->prof->dir = dir; |
1371 | params->prof->segs_cnt = segs_cnt; |
1372 | |
1373 | /* Make a copy of the segments that need to be persistent in the flow |
1374 | * profile instance |
1375 | */ |
1376 | for (i = 0; i < segs_cnt; i++) |
1377 | memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs)); |
1378 | |
1379 | status = ice_flow_proc_segs(hw, params); |
1380 | if (status) { |
1381 | ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n" ); |
1382 | goto out; |
1383 | } |
1384 | |
1385 | /* Add a HW profile for this flow profile */ |
1386 | status = ice_add_prof(hw, blk, id: prof_id, ptypes: (u8 *)params->ptypes, |
1387 | attr: params->attr, attr_cnt: params->attr_cnt, es: params->es, |
1388 | masks: params->mask); |
1389 | if (status) { |
1390 | ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n" ); |
1391 | goto out; |
1392 | } |
1393 | |
1394 | INIT_LIST_HEAD(list: ¶ms->prof->entries); |
1395 | mutex_init(¶ms->prof->entries_lock); |
1396 | *prof = params->prof; |
1397 | |
1398 | out: |
1399 | if (status) |
1400 | devm_kfree(dev: ice_hw_to_dev(hw), p: params->prof); |
1401 | free_params: |
1402 | kfree(objp: params); |
1403 | |
1404 | return status; |
1405 | } |
1406 | |
1407 | /** |
1408 | * ice_flow_rem_prof_sync - remove a flow profile |
1409 | * @hw: pointer to the hardware structure |
1410 | * @blk: classification stage |
1411 | * @prof: pointer to flow profile to remove |
1412 | * |
1413 | * Assumption: the caller has acquired the lock to the profile list |
1414 | */ |
1415 | static int |
1416 | ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, |
1417 | struct ice_flow_prof *prof) |
1418 | { |
1419 | int status; |
1420 | |
1421 | /* Remove all remaining flow entries before removing the flow profile */ |
1422 | if (!list_empty(head: &prof->entries)) { |
1423 | struct ice_flow_entry *e, *t; |
1424 | |
1425 | mutex_lock(&prof->entries_lock); |
1426 | |
1427 | list_for_each_entry_safe(e, t, &prof->entries, l_entry) { |
1428 | status = ice_flow_rem_entry_sync(hw, blk, entry: e); |
1429 | if (status) |
1430 | break; |
1431 | } |
1432 | |
1433 | mutex_unlock(lock: &prof->entries_lock); |
1434 | } |
1435 | |
1436 | /* Remove all hardware profiles associated with this flow profile */ |
1437 | status = ice_rem_prof(hw, blk, id: prof->id); |
1438 | if (!status) { |
1439 | list_del(entry: &prof->l_entry); |
1440 | mutex_destroy(lock: &prof->entries_lock); |
1441 | devm_kfree(dev: ice_hw_to_dev(hw), p: prof); |
1442 | } |
1443 | |
1444 | return status; |
1445 | } |
1446 | |
1447 | /** |
1448 | * ice_flow_assoc_prof - associate a VSI with a flow profile |
1449 | * @hw: pointer to the hardware structure |
1450 | * @blk: classification stage |
1451 | * @prof: pointer to flow profile |
1452 | * @vsi_handle: software VSI handle |
1453 | * |
1454 | * Assumption: the caller has acquired the lock to the profile list |
1455 | * and the software VSI handle has been validated |
1456 | */ |
1457 | static int |
1458 | ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, |
1459 | struct ice_flow_prof *prof, u16 vsi_handle) |
1460 | { |
1461 | int status = 0; |
1462 | |
1463 | if (!test_bit(vsi_handle, prof->vsis)) { |
1464 | status = ice_add_prof_id_flow(hw, blk, |
1465 | vsi: ice_get_hw_vsi_num(hw, |
1466 | vsi_handle), |
1467 | hdl: prof->id); |
1468 | if (!status) |
1469 | set_bit(nr: vsi_handle, addr: prof->vsis); |
1470 | else |
1471 | ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n" , |
1472 | status); |
1473 | } |
1474 | |
1475 | return status; |
1476 | } |
1477 | |
1478 | /** |
1479 | * ice_flow_disassoc_prof - disassociate a VSI from a flow profile |
1480 | * @hw: pointer to the hardware structure |
1481 | * @blk: classification stage |
1482 | * @prof: pointer to flow profile |
1483 | * @vsi_handle: software VSI handle |
1484 | * |
1485 | * Assumption: the caller has acquired the lock to the profile list |
1486 | * and the software VSI handle has been validated |
1487 | */ |
1488 | static int |
1489 | ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, |
1490 | struct ice_flow_prof *prof, u16 vsi_handle) |
1491 | { |
1492 | int status = 0; |
1493 | |
1494 | if (test_bit(vsi_handle, prof->vsis)) { |
1495 | status = ice_rem_prof_id_flow(hw, blk, |
1496 | vsi: ice_get_hw_vsi_num(hw, |
1497 | vsi_handle), |
1498 | hdl: prof->id); |
1499 | if (!status) |
1500 | clear_bit(nr: vsi_handle, addr: prof->vsis); |
1501 | else |
1502 | ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n" , |
1503 | status); |
1504 | } |
1505 | |
1506 | return status; |
1507 | } |
1508 | |
1509 | /** |
1510 | * ice_flow_add_prof - Add a flow profile for packet segments and matched fields |
1511 | * @hw: pointer to the HW struct |
1512 | * @blk: classification stage |
1513 | * @dir: flow direction |
1514 | * @prof_id: unique ID to identify this flow profile |
1515 | * @segs: array of one or more packet segments that describe the flow |
1516 | * @segs_cnt: number of packet segments provided |
1517 | * @prof: stores the returned flow profile added |
1518 | */ |
1519 | int |
1520 | ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, |
1521 | u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, |
1522 | struct ice_flow_prof **prof) |
1523 | { |
1524 | int status; |
1525 | |
1526 | if (segs_cnt > ICE_FLOW_SEG_MAX) |
1527 | return -ENOSPC; |
1528 | |
1529 | if (!segs_cnt) |
1530 | return -EINVAL; |
1531 | |
1532 | if (!segs) |
1533 | return -EINVAL; |
1534 | |
1535 | status = ice_flow_val_hdrs(segs, segs_cnt); |
1536 | if (status) |
1537 | return status; |
1538 | |
1539 | mutex_lock(&hw->fl_profs_locks[blk]); |
1540 | |
1541 | status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, |
1542 | prof); |
1543 | if (!status) |
1544 | list_add(new: &(*prof)->l_entry, head: &hw->fl_profs[blk]); |
1545 | |
1546 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1547 | |
1548 | return status; |
1549 | } |
1550 | |
1551 | /** |
1552 | * ice_flow_rem_prof - Remove a flow profile and all entries associated with it |
1553 | * @hw: pointer to the HW struct |
1554 | * @blk: the block for which the flow profile is to be removed |
1555 | * @prof_id: unique ID of the flow profile to be removed |
1556 | */ |
1557 | int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) |
1558 | { |
1559 | struct ice_flow_prof *prof; |
1560 | int status; |
1561 | |
1562 | mutex_lock(&hw->fl_profs_locks[blk]); |
1563 | |
1564 | prof = ice_flow_find_prof_id(hw, blk, prof_id); |
1565 | if (!prof) { |
1566 | status = -ENOENT; |
1567 | goto out; |
1568 | } |
1569 | |
1570 | /* prof becomes invalid after the call */ |
1571 | status = ice_flow_rem_prof_sync(hw, blk, prof); |
1572 | |
1573 | out: |
1574 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1575 | |
1576 | return status; |
1577 | } |
1578 | |
1579 | /** |
1580 | * ice_flow_add_entry - Add a flow entry |
1581 | * @hw: pointer to the HW struct |
1582 | * @blk: classification stage |
1583 | * @prof_id: ID of the profile to add a new flow entry to |
1584 | * @entry_id: unique ID to identify this flow entry |
1585 | * @vsi_handle: software VSI handle for the flow entry |
1586 | * @prio: priority of the flow entry |
1587 | * @data: pointer to a data buffer containing flow entry's match values/masks |
1588 | * @entry_h: pointer to buffer that receives the new flow entry's handle |
1589 | */ |
1590 | int |
1591 | ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, |
1592 | u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio, |
1593 | void *data, u64 *entry_h) |
1594 | { |
1595 | struct ice_flow_entry *e = NULL; |
1596 | struct ice_flow_prof *prof; |
1597 | int status; |
1598 | |
1599 | /* No flow entry data is expected for RSS */ |
1600 | if (!entry_h || (!data && blk != ICE_BLK_RSS)) |
1601 | return -EINVAL; |
1602 | |
1603 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1604 | return -EINVAL; |
1605 | |
1606 | mutex_lock(&hw->fl_profs_locks[blk]); |
1607 | |
1608 | prof = ice_flow_find_prof_id(hw, blk, prof_id); |
1609 | if (!prof) { |
1610 | status = -ENOENT; |
1611 | } else { |
1612 | /* Allocate memory for the entry being added and associate |
1613 | * the VSI to the found flow profile |
1614 | */ |
1615 | e = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*e), GFP_KERNEL); |
1616 | if (!e) |
1617 | status = -ENOMEM; |
1618 | else |
1619 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
1620 | } |
1621 | |
1622 | mutex_unlock(lock: &hw->fl_profs_locks[blk]); |
1623 | if (status) |
1624 | goto out; |
1625 | |
1626 | e->id = entry_id; |
1627 | e->vsi_handle = vsi_handle; |
1628 | e->prof = prof; |
1629 | e->priority = prio; |
1630 | |
1631 | switch (blk) { |
1632 | case ICE_BLK_FD: |
1633 | case ICE_BLK_RSS: |
1634 | break; |
1635 | default: |
1636 | status = -EOPNOTSUPP; |
1637 | goto out; |
1638 | } |
1639 | |
1640 | mutex_lock(&prof->entries_lock); |
1641 | list_add(new: &e->l_entry, head: &prof->entries); |
1642 | mutex_unlock(lock: &prof->entries_lock); |
1643 | |
1644 | *entry_h = ICE_FLOW_ENTRY_HNDL(e); |
1645 | |
1646 | out: |
1647 | if (status) |
1648 | devm_kfree(dev: ice_hw_to_dev(hw), p: e); |
1649 | |
1650 | return status; |
1651 | } |
1652 | |
1653 | /** |
1654 | * ice_flow_rem_entry - Remove a flow entry |
1655 | * @hw: pointer to the HW struct |
1656 | * @blk: classification stage |
1657 | * @entry_h: handle to the flow entry to be removed |
1658 | */ |
1659 | int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h) |
1660 | { |
1661 | struct ice_flow_entry *entry; |
1662 | struct ice_flow_prof *prof; |
1663 | int status = 0; |
1664 | |
1665 | if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL) |
1666 | return -EINVAL; |
1667 | |
1668 | entry = ICE_FLOW_ENTRY_PTR(entry_h); |
1669 | |
1670 | /* Retain the pointer to the flow profile as the entry will be freed */ |
1671 | prof = entry->prof; |
1672 | |
1673 | if (prof) { |
1674 | mutex_lock(&prof->entries_lock); |
1675 | status = ice_flow_rem_entry_sync(hw, blk, entry); |
1676 | mutex_unlock(lock: &prof->entries_lock); |
1677 | } |
1678 | |
1679 | return status; |
1680 | } |
1681 | |
1682 | /** |
1683 | * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer |
1684 | * @seg: packet segment the field being set belongs to |
1685 | * @fld: field to be set |
1686 | * @field_type: type of the field |
1687 | * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from |
1688 | * entry's input buffer |
1689 | * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's |
1690 | * input buffer |
1691 | * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from |
1692 | * entry's input buffer |
1693 | * |
1694 | * This helper function stores information of a field being matched, including |
1695 | * the type of the field and the locations of the value to match, the mask, and |
1696 | * the upper-bound value in the start of the input buffer for a flow entry. |
1697 | * This function should only be used for fixed-size data structures. |
1698 | * |
1699 | * This function also opportunistically determines the protocol headers to be |
1700 | * present based on the fields being set. Some fields cannot be used alone to |
1701 | * determine the protocol headers present. Sometimes, fields for particular |
1702 | * protocol headers are not matched. In those cases, the protocol headers |
1703 | * must be explicitly set. |
1704 | */ |
1705 | static void |
1706 | ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, |
1707 | enum ice_flow_fld_match_type field_type, u16 val_loc, |
1708 | u16 mask_loc, u16 last_loc) |
1709 | { |
1710 | u64 bit = BIT_ULL(fld); |
1711 | |
1712 | seg->match |= bit; |
1713 | if (field_type == ICE_FLOW_FLD_TYPE_RANGE) |
1714 | seg->range |= bit; |
1715 | |
1716 | seg->fields[fld].type = field_type; |
1717 | seg->fields[fld].src.val = val_loc; |
1718 | seg->fields[fld].src.mask = mask_loc; |
1719 | seg->fields[fld].src.last = last_loc; |
1720 | |
1721 | ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); |
1722 | } |
1723 | |
1724 | /** |
1725 | * ice_flow_set_fld - specifies locations of field from entry's input buffer |
1726 | * @seg: packet segment the field being set belongs to |
1727 | * @fld: field to be set |
1728 | * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from |
1729 | * entry's input buffer |
1730 | * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's |
1731 | * input buffer |
1732 | * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from |
1733 | * entry's input buffer |
1734 | * @range: indicate if field being matched is to be in a range |
1735 | * |
1736 | * This function specifies the locations, in the form of byte offsets from the |
1737 | * start of the input buffer for a flow entry, from where the value to match, |
1738 | * the mask value, and upper value can be extracted. These locations are then |
1739 | * stored in the flow profile. When adding a flow entry associated with the |
1740 | * flow profile, these locations will be used to quickly extract the values and |
1741 | * create the content of a match entry. This function should only be used for |
1742 | * fixed-size data structures. |
1743 | */ |
1744 | void |
1745 | ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, |
1746 | u16 val_loc, u16 mask_loc, u16 last_loc, bool range) |
1747 | { |
1748 | enum ice_flow_fld_match_type t = range ? |
1749 | ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; |
1750 | |
1751 | ice_flow_set_fld_ext(seg, fld, field_type: t, val_loc, mask_loc, last_loc); |
1752 | } |
1753 | |
1754 | /** |
1755 | * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf |
1756 | * @seg: packet segment the field being set belongs to |
1757 | * @off: offset of the raw field from the beginning of the segment in bytes |
1758 | * @len: length of the raw pattern to be matched |
1759 | * @val_loc: location of the value to match from entry's input buffer |
1760 | * @mask_loc: location of mask value from entry's input buffer |
1761 | * |
1762 | * This function specifies the offset of the raw field to be match from the |
1763 | * beginning of the specified packet segment, and the locations, in the form of |
1764 | * byte offsets from the start of the input buffer for a flow entry, from where |
1765 | * the value to match and the mask value to be extracted. These locations are |
1766 | * then stored in the flow profile. When adding flow entries to the associated |
1767 | * flow profile, these locations can be used to quickly extract the values to |
1768 | * create the content of a match entry. This function should only be used for |
1769 | * fixed-size data structures. |
1770 | */ |
1771 | void |
1772 | ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, |
1773 | u16 val_loc, u16 mask_loc) |
1774 | { |
1775 | if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) { |
1776 | seg->raws[seg->raws_cnt].off = off; |
1777 | seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE; |
1778 | seg->raws[seg->raws_cnt].info.src.val = val_loc; |
1779 | seg->raws[seg->raws_cnt].info.src.mask = mask_loc; |
1780 | /* The "last" field is used to store the length of the field */ |
1781 | seg->raws[seg->raws_cnt].info.src.last = len; |
1782 | } |
1783 | |
1784 | /* Overflows of "raws" will be handled as an error condition later in |
1785 | * the flow when this information is processed. |
1786 | */ |
1787 | seg->raws_cnt++; |
1788 | } |
1789 | |
1790 | /** |
1791 | * ice_flow_rem_vsi_prof - remove VSI from flow profile |
1792 | * @hw: pointer to the hardware structure |
1793 | * @vsi_handle: software VSI handle |
1794 | * @prof_id: unique ID to identify this flow profile |
1795 | * |
1796 | * This function removes the flow entries associated to the input |
1797 | * VSI handle and disassociate the VSI from the flow profile. |
1798 | */ |
1799 | int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id) |
1800 | { |
1801 | struct ice_flow_prof *prof; |
1802 | int status = 0; |
1803 | |
1804 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1805 | return -EINVAL; |
1806 | |
1807 | /* find flow profile pointer with input package block and profile ID */ |
1808 | prof = ice_flow_find_prof_id(hw, blk: ICE_BLK_FD, prof_id); |
1809 | if (!prof) { |
1810 | ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n" , |
1811 | prof_id); |
1812 | return -ENOENT; |
1813 | } |
1814 | |
1815 | /* Remove all remaining flow entries before removing the flow profile */ |
1816 | if (!list_empty(head: &prof->entries)) { |
1817 | struct ice_flow_entry *e, *t; |
1818 | |
1819 | mutex_lock(&prof->entries_lock); |
1820 | list_for_each_entry_safe(e, t, &prof->entries, l_entry) { |
1821 | if (e->vsi_handle != vsi_handle) |
1822 | continue; |
1823 | |
1824 | status = ice_flow_rem_entry_sync(hw, blk: ICE_BLK_FD, entry: e); |
1825 | if (status) |
1826 | break; |
1827 | } |
1828 | mutex_unlock(lock: &prof->entries_lock); |
1829 | } |
1830 | if (status) |
1831 | return status; |
1832 | |
1833 | /* disassociate the flow profile from sw VSI handle */ |
1834 | status = ice_flow_disassoc_prof(hw, blk: ICE_BLK_FD, prof, vsi_handle); |
1835 | if (status) |
1836 | ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n" , |
1837 | status); |
1838 | return status; |
1839 | } |
1840 | |
1841 | #define \ |
1842 | (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) |
1843 | |
1844 | #define \ |
1845 | (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) |
1846 | |
1847 | #define \ |
1848 | (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) |
1849 | |
1850 | #define \ |
1851 | (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ |
1852 | ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ |
1853 | ICE_FLOW_RSS_SEG_HDR_L4_MASKS) |
1854 | |
1855 | /** |
1856 | * ice_flow_set_rss_seg_info - setup packet segments for RSS |
1857 | * @segs: pointer to the flow field segment(s) |
1858 | * @hash_fields: fields to be hashed on for the segment(s) |
1859 | * @flow_hdr: protocol header fields within a packet segment |
1860 | * |
1861 | * Helper function to extract fields from hash bitmap and use flow |
1862 | * header value to set flow field segment for further use in flow |
1863 | * profile entry or removal. |
1864 | */ |
1865 | static int |
1866 | (struct ice_flow_seg_info *segs, u64 hash_fields, |
1867 | u32 flow_hdr) |
1868 | { |
1869 | u64 val; |
1870 | u8 i; |
1871 | |
1872 | for_each_set_bit(i, (unsigned long *)&hash_fields, |
1873 | ICE_FLOW_FIELD_IDX_MAX) |
1874 | ice_flow_set_fld(seg: segs, fld: (enum ice_flow_field)i, |
1875 | ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, |
1876 | ICE_FLOW_FLD_OFF_INVAL, range: false); |
1877 | |
1878 | ICE_FLOW_SET_HDRS(segs, flow_hdr); |
1879 | |
1880 | if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & |
1881 | ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER) |
1882 | return -EINVAL; |
1883 | |
1884 | val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); |
1885 | if (val && !is_power_of_2(n: val)) |
1886 | return -EIO; |
1887 | |
1888 | val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); |
1889 | if (val && !is_power_of_2(n: val)) |
1890 | return -EIO; |
1891 | |
1892 | return 0; |
1893 | } |
1894 | |
1895 | /** |
1896 | * ice_rem_vsi_rss_list - remove VSI from RSS list |
1897 | * @hw: pointer to the hardware structure |
1898 | * @vsi_handle: software VSI handle |
1899 | * |
1900 | * Remove the VSI from all RSS configurations in the list. |
1901 | */ |
1902 | void (struct ice_hw *hw, u16 vsi_handle) |
1903 | { |
1904 | struct ice_rss_cfg *r, *tmp; |
1905 | |
1906 | if (list_empty(head: &hw->rss_list_head)) |
1907 | return; |
1908 | |
1909 | mutex_lock(&hw->rss_locks); |
1910 | list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) |
1911 | if (test_and_clear_bit(nr: vsi_handle, addr: r->vsis)) |
1912 | if (bitmap_empty(src: r->vsis, ICE_MAX_VSI)) { |
1913 | list_del(entry: &r->l_entry); |
1914 | devm_kfree(dev: ice_hw_to_dev(hw), p: r); |
1915 | } |
1916 | mutex_unlock(lock: &hw->rss_locks); |
1917 | } |
1918 | |
1919 | /** |
1920 | * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI |
1921 | * @hw: pointer to the hardware structure |
1922 | * @vsi_handle: software VSI handle |
1923 | * |
1924 | * This function will iterate through all flow profiles and disassociate |
1925 | * the VSI from that profile. If the flow profile has no VSIs it will |
1926 | * be removed. |
1927 | */ |
1928 | int (struct ice_hw *hw, u16 vsi_handle) |
1929 | { |
1930 | const enum ice_block blk = ICE_BLK_RSS; |
1931 | struct ice_flow_prof *p, *t; |
1932 | int status = 0; |
1933 | |
1934 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
1935 | return -EINVAL; |
1936 | |
1937 | if (list_empty(head: &hw->fl_profs[blk])) |
1938 | return 0; |
1939 | |
1940 | mutex_lock(&hw->rss_locks); |
1941 | list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry) |
1942 | if (test_bit(vsi_handle, p->vsis)) { |
1943 | status = ice_flow_disassoc_prof(hw, blk, prof: p, vsi_handle); |
1944 | if (status) |
1945 | break; |
1946 | |
1947 | if (bitmap_empty(src: p->vsis, ICE_MAX_VSI)) { |
1948 | status = ice_flow_rem_prof(hw, blk, prof_id: p->id); |
1949 | if (status) |
1950 | break; |
1951 | } |
1952 | } |
1953 | mutex_unlock(lock: &hw->rss_locks); |
1954 | |
1955 | return status; |
1956 | } |
1957 | |
1958 | /** |
1959 | * ice_rem_rss_list - remove RSS configuration from list |
1960 | * @hw: pointer to the hardware structure |
1961 | * @vsi_handle: software VSI handle |
1962 | * @prof: pointer to flow profile |
1963 | * |
1964 | * Assumption: lock has already been acquired for RSS list |
1965 | */ |
1966 | static void |
1967 | (struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) |
1968 | { |
1969 | struct ice_rss_cfg *r, *tmp; |
1970 | |
1971 | /* Search for RSS hash fields associated to the VSI that match the |
1972 | * hash configurations associated to the flow profile. If found |
1973 | * remove from the RSS entry list of the VSI context and delete entry. |
1974 | */ |
1975 | list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) |
1976 | if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && |
1977 | r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { |
1978 | clear_bit(nr: vsi_handle, addr: r->vsis); |
1979 | if (bitmap_empty(src: r->vsis, ICE_MAX_VSI)) { |
1980 | list_del(entry: &r->l_entry); |
1981 | devm_kfree(dev: ice_hw_to_dev(hw), p: r); |
1982 | } |
1983 | return; |
1984 | } |
1985 | } |
1986 | |
1987 | /** |
1988 | * ice_add_rss_list - add RSS configuration to list |
1989 | * @hw: pointer to the hardware structure |
1990 | * @vsi_handle: software VSI handle |
1991 | * @prof: pointer to flow profile |
1992 | * |
1993 | * Assumption: lock has already been acquired for RSS list |
1994 | */ |
1995 | static int |
1996 | (struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) |
1997 | { |
1998 | struct ice_rss_cfg *r, *; |
1999 | |
2000 | list_for_each_entry(r, &hw->rss_list_head, l_entry) |
2001 | if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && |
2002 | r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { |
2003 | set_bit(nr: vsi_handle, addr: r->vsis); |
2004 | return 0; |
2005 | } |
2006 | |
2007 | rss_cfg = devm_kzalloc(dev: ice_hw_to_dev(hw), size: sizeof(*rss_cfg), |
2008 | GFP_KERNEL); |
2009 | if (!rss_cfg) |
2010 | return -ENOMEM; |
2011 | |
2012 | rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; |
2013 | rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; |
2014 | set_bit(nr: vsi_handle, addr: rss_cfg->vsis); |
2015 | |
2016 | list_add_tail(new: &rss_cfg->l_entry, head: &hw->rss_list_head); |
2017 | |
2018 | return 0; |
2019 | } |
2020 | |
2021 | #define ICE_FLOW_PROF_HASH_S 0 |
2022 | #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) |
2023 | #define ICE_FLOW_PROF_HDR_S 32 |
2024 | #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) |
2025 | #define ICE_FLOW_PROF_ENCAP_S 63 |
2026 | #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) |
2027 | |
2028 | #define 1 |
2029 | #define 2 |
2030 | |
2031 | /* Flow profile ID format: |
2032 | * [0:31] - Packet match fields |
2033 | * [32:62] - Protocol header |
2034 | * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled |
2035 | */ |
2036 | #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ |
2037 | ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ |
2038 | (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ |
2039 | ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))) |
2040 | |
2041 | /** |
2042 | * ice_add_rss_cfg_sync - add an RSS configuration |
2043 | * @hw: pointer to the hardware structure |
2044 | * @vsi_handle: software VSI handle |
2045 | * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure |
2046 | * @addl_hdrs: protocol header fields |
2047 | * @segs_cnt: packet segment count |
2048 | * |
2049 | * Assumption: lock has already been acquired for RSS list |
2050 | */ |
2051 | static int |
2052 | (struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, |
2053 | u32 addl_hdrs, u8 segs_cnt) |
2054 | { |
2055 | const enum ice_block blk = ICE_BLK_RSS; |
2056 | struct ice_flow_prof *prof = NULL; |
2057 | struct ice_flow_seg_info *segs; |
2058 | int status; |
2059 | |
2060 | if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX) |
2061 | return -EINVAL; |
2062 | |
2063 | segs = kcalloc(n: segs_cnt, size: sizeof(*segs), GFP_KERNEL); |
2064 | if (!segs) |
2065 | return -ENOMEM; |
2066 | |
2067 | /* Construct the packet segment info from the hashed fields */ |
2068 | status = ice_flow_set_rss_seg_info(segs: &segs[segs_cnt - 1], hash_fields: hashed_flds, |
2069 | flow_hdr: addl_hdrs); |
2070 | if (status) |
2071 | goto exit; |
2072 | |
2073 | /* Search for a flow profile that has matching headers, hash fields |
2074 | * and has the input VSI associated to it. If found, no further |
2075 | * operations required and exit. |
2076 | */ |
2077 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2078 | vsi_handle, |
2079 | ICE_FLOW_FIND_PROF_CHK_FLDS | |
2080 | ICE_FLOW_FIND_PROF_CHK_VSI); |
2081 | if (prof) |
2082 | goto exit; |
2083 | |
2084 | /* Check if a flow profile exists with the same protocol headers and |
2085 | * associated with the input VSI. If so disassociate the VSI from |
2086 | * this profile. The VSI will be added to a new profile created with |
2087 | * the protocol header and new hash field configuration. |
2088 | */ |
2089 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2090 | vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); |
2091 | if (prof) { |
2092 | status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); |
2093 | if (!status) |
2094 | ice_rem_rss_list(hw, vsi_handle, prof); |
2095 | else |
2096 | goto exit; |
2097 | |
2098 | /* Remove profile if it has no VSIs associated */ |
2099 | if (bitmap_empty(src: prof->vsis, ICE_MAX_VSI)) { |
2100 | status = ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2101 | if (status) |
2102 | goto exit; |
2103 | } |
2104 | } |
2105 | |
2106 | /* Search for a profile that has same match fields only. If this |
2107 | * exists then associate the VSI to this profile. |
2108 | */ |
2109 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2110 | vsi_handle, |
2111 | ICE_FLOW_FIND_PROF_CHK_FLDS); |
2112 | if (prof) { |
2113 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
2114 | if (!status) |
2115 | status = ice_add_rss_list(hw, vsi_handle, prof); |
2116 | goto exit; |
2117 | } |
2118 | |
2119 | /* Create a new flow profile with generated profile and packet |
2120 | * segment information. |
2121 | */ |
2122 | status = ice_flow_add_prof(hw, blk, dir: ICE_FLOW_RX, |
2123 | ICE_FLOW_GEN_PROFID(hashed_flds, |
2124 | segs[segs_cnt - 1].hdrs, |
2125 | segs_cnt), |
2126 | segs, segs_cnt, prof: &prof); |
2127 | if (status) |
2128 | goto exit; |
2129 | |
2130 | status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); |
2131 | /* If association to a new flow profile failed then this profile can |
2132 | * be removed. |
2133 | */ |
2134 | if (status) { |
2135 | ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2136 | goto exit; |
2137 | } |
2138 | |
2139 | status = ice_add_rss_list(hw, vsi_handle, prof); |
2140 | |
2141 | exit: |
2142 | kfree(objp: segs); |
2143 | return status; |
2144 | } |
2145 | |
2146 | /** |
2147 | * ice_add_rss_cfg - add an RSS configuration with specified hashed fields |
2148 | * @hw: pointer to the hardware structure |
2149 | * @vsi_handle: software VSI handle |
2150 | * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure |
2151 | * @addl_hdrs: protocol header fields |
2152 | * |
2153 | * This function will generate a flow profile based on fields associated with |
2154 | * the input fields to hash on, the flow type and use the VSI number to add |
2155 | * a flow entry to the profile. |
2156 | */ |
2157 | int |
2158 | (struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, |
2159 | u32 addl_hdrs) |
2160 | { |
2161 | int status; |
2162 | |
2163 | if (hashed_flds == ICE_HASH_INVALID || |
2164 | !ice_is_vsi_valid(hw, vsi_handle)) |
2165 | return -EINVAL; |
2166 | |
2167 | mutex_lock(&hw->rss_locks); |
2168 | status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, |
2169 | ICE_RSS_OUTER_HEADERS); |
2170 | if (!status) |
2171 | status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, |
2172 | addl_hdrs, ICE_RSS_INNER_HEADERS); |
2173 | mutex_unlock(lock: &hw->rss_locks); |
2174 | |
2175 | return status; |
2176 | } |
2177 | |
2178 | /** |
2179 | * ice_rem_rss_cfg_sync - remove an existing RSS configuration |
2180 | * @hw: pointer to the hardware structure |
2181 | * @vsi_handle: software VSI handle |
2182 | * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove |
2183 | * @addl_hdrs: Protocol header fields within a packet segment |
2184 | * @segs_cnt: packet segment count |
2185 | * |
2186 | * Assumption: lock has already been acquired for RSS list |
2187 | */ |
2188 | static int |
2189 | (struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, |
2190 | u32 addl_hdrs, u8 segs_cnt) |
2191 | { |
2192 | const enum ice_block blk = ICE_BLK_RSS; |
2193 | struct ice_flow_seg_info *segs; |
2194 | struct ice_flow_prof *prof; |
2195 | int status; |
2196 | |
2197 | segs = kcalloc(n: segs_cnt, size: sizeof(*segs), GFP_KERNEL); |
2198 | if (!segs) |
2199 | return -ENOMEM; |
2200 | |
2201 | /* Construct the packet segment info from the hashed fields */ |
2202 | status = ice_flow_set_rss_seg_info(segs: &segs[segs_cnt - 1], hash_fields: hashed_flds, |
2203 | flow_hdr: addl_hdrs); |
2204 | if (status) |
2205 | goto out; |
2206 | |
2207 | prof = ice_flow_find_prof_conds(hw, blk, dir: ICE_FLOW_RX, segs, segs_cnt, |
2208 | vsi_handle, |
2209 | ICE_FLOW_FIND_PROF_CHK_FLDS); |
2210 | if (!prof) { |
2211 | status = -ENOENT; |
2212 | goto out; |
2213 | } |
2214 | |
2215 | status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); |
2216 | if (status) |
2217 | goto out; |
2218 | |
2219 | /* Remove RSS configuration from VSI context before deleting |
2220 | * the flow profile. |
2221 | */ |
2222 | ice_rem_rss_list(hw, vsi_handle, prof); |
2223 | |
2224 | if (bitmap_empty(src: prof->vsis, ICE_MAX_VSI)) |
2225 | status = ice_flow_rem_prof(hw, blk, prof_id: prof->id); |
2226 | |
2227 | out: |
2228 | kfree(objp: segs); |
2229 | return status; |
2230 | } |
2231 | |
2232 | /** |
2233 | * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields |
2234 | * @hw: pointer to the hardware structure |
2235 | * @vsi_handle: software VSI handle |
2236 | * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove |
2237 | * @addl_hdrs: Protocol header fields within a packet segment |
2238 | * |
2239 | * This function will lookup the flow profile based on the input |
2240 | * hash field bitmap, iterate through the profile entry list of |
2241 | * that profile and find entry associated with input VSI to be |
2242 | * removed. Calls are made to underlying flow s which will APIs |
2243 | * turn build or update buffers for RSS XLT1 section. |
2244 | */ |
2245 | int __maybe_unused |
2246 | (struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, |
2247 | u32 addl_hdrs) |
2248 | { |
2249 | int status; |
2250 | |
2251 | if (hashed_flds == ICE_HASH_INVALID || |
2252 | !ice_is_vsi_valid(hw, vsi_handle)) |
2253 | return -EINVAL; |
2254 | |
2255 | mutex_lock(&hw->rss_locks); |
2256 | status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs, |
2257 | ICE_RSS_OUTER_HEADERS); |
2258 | if (!status) |
2259 | status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, |
2260 | addl_hdrs, ICE_RSS_INNER_HEADERS); |
2261 | mutex_unlock(lock: &hw->rss_locks); |
2262 | |
2263 | return status; |
2264 | } |
2265 | |
2266 | /* Mapping of AVF hash bit fields to an L3-L4 hash combination. |
2267 | * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, |
2268 | * convert its values to their appropriate flow L3, L4 values. |
2269 | */ |
2270 | #define \ |
2271 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ |
2272 | BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) |
2273 | #define \ |
2274 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ |
2275 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) |
2276 | #define \ |
2277 | (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ |
2278 | BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ |
2279 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) |
2280 | #define \ |
2281 | (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ |
2282 | ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) |
2283 | |
2284 | #define \ |
2285 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ |
2286 | BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) |
2287 | #define \ |
2288 | (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ |
2289 | BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ |
2290 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) |
2291 | #define \ |
2292 | (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ |
2293 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) |
2294 | #define \ |
2295 | (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ |
2296 | ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) |
2297 | |
2298 | /** |
2299 | * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver |
2300 | * @hw: pointer to the hardware structure |
2301 | * @vsi_handle: software VSI handle |
2302 | * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure |
2303 | * |
2304 | * This function will take the hash bitmap provided by the AVF driver via a |
2305 | * message, convert it to ICE-compatible values, and configure RSS flow |
2306 | * profiles. |
2307 | */ |
2308 | int (struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) |
2309 | { |
2310 | int status = 0; |
2311 | u64 hash_flds; |
2312 | |
2313 | if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || |
2314 | !ice_is_vsi_valid(hw, vsi_handle)) |
2315 | return -EINVAL; |
2316 | |
2317 | /* Make sure no unsupported bits are specified */ |
2318 | if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | |
2319 | ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) |
2320 | return -EIO; |
2321 | |
2322 | hash_flds = avf_hash; |
2323 | |
2324 | /* Always create an L3 RSS configuration for any L4 RSS configuration */ |
2325 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) |
2326 | hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; |
2327 | |
2328 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) |
2329 | hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; |
2330 | |
2331 | /* Create the corresponding RSS configuration for each valid hash bit */ |
2332 | while (hash_flds) { |
2333 | u64 = ICE_HASH_INVALID; |
2334 | |
2335 | if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { |
2336 | if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { |
2337 | rss_hash = ICE_FLOW_HASH_IPV4; |
2338 | hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; |
2339 | } else if (hash_flds & |
2340 | ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { |
2341 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2342 | ICE_FLOW_HASH_TCP_PORT; |
2343 | hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; |
2344 | } else if (hash_flds & |
2345 | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { |
2346 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2347 | ICE_FLOW_HASH_UDP_PORT; |
2348 | hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; |
2349 | } else if (hash_flds & |
2350 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { |
2351 | rss_hash = ICE_FLOW_HASH_IPV4 | |
2352 | ICE_FLOW_HASH_SCTP_PORT; |
2353 | hash_flds &= |
2354 | ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); |
2355 | } |
2356 | } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { |
2357 | if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { |
2358 | rss_hash = ICE_FLOW_HASH_IPV6; |
2359 | hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; |
2360 | } else if (hash_flds & |
2361 | ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { |
2362 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2363 | ICE_FLOW_HASH_TCP_PORT; |
2364 | hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; |
2365 | } else if (hash_flds & |
2366 | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { |
2367 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2368 | ICE_FLOW_HASH_UDP_PORT; |
2369 | hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; |
2370 | } else if (hash_flds & |
2371 | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { |
2372 | rss_hash = ICE_FLOW_HASH_IPV6 | |
2373 | ICE_FLOW_HASH_SCTP_PORT; |
2374 | hash_flds &= |
2375 | ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); |
2376 | } |
2377 | } |
2378 | |
2379 | if (rss_hash == ICE_HASH_INVALID) |
2380 | return -EIO; |
2381 | |
2382 | status = ice_add_rss_cfg(hw, vsi_handle, hashed_flds: rss_hash, |
2383 | addl_hdrs: ICE_FLOW_SEG_HDR_NONE); |
2384 | if (status) |
2385 | break; |
2386 | } |
2387 | |
2388 | return status; |
2389 | } |
2390 | |
2391 | /** |
2392 | * ice_replay_rss_cfg - replay RSS configurations associated with VSI |
2393 | * @hw: pointer to the hardware structure |
2394 | * @vsi_handle: software VSI handle |
2395 | */ |
2396 | int (struct ice_hw *hw, u16 vsi_handle) |
2397 | { |
2398 | struct ice_rss_cfg *r; |
2399 | int status = 0; |
2400 | |
2401 | if (!ice_is_vsi_valid(hw, vsi_handle)) |
2402 | return -EINVAL; |
2403 | |
2404 | mutex_lock(&hw->rss_locks); |
2405 | list_for_each_entry(r, &hw->rss_list_head, l_entry) { |
2406 | if (test_bit(vsi_handle, r->vsis)) { |
2407 | status = ice_add_rss_cfg_sync(hw, vsi_handle, |
2408 | hashed_flds: r->hashed_flds, |
2409 | addl_hdrs: r->packet_hdr, |
2410 | ICE_RSS_OUTER_HEADERS); |
2411 | if (status) |
2412 | break; |
2413 | status = ice_add_rss_cfg_sync(hw, vsi_handle, |
2414 | hashed_flds: r->hashed_flds, |
2415 | addl_hdrs: r->packet_hdr, |
2416 | ICE_RSS_INNER_HEADERS); |
2417 | if (status) |
2418 | break; |
2419 | } |
2420 | } |
2421 | mutex_unlock(lock: &hw->rss_locks); |
2422 | |
2423 | return status; |
2424 | } |
2425 | |
2426 | /** |
2427 | * ice_get_rss_cfg - returns hashed fields for the given header types |
2428 | * @hw: pointer to the hardware structure |
2429 | * @vsi_handle: software VSI handle |
2430 | * @hdrs: protocol header type |
2431 | * |
2432 | * This function will return the match fields of the first instance of flow |
2433 | * profile having the given header types and containing input VSI |
2434 | */ |
2435 | u64 (struct ice_hw *hw, u16 vsi_handle, u32 hdrs) |
2436 | { |
2437 | u64 = ICE_HASH_INVALID; |
2438 | struct ice_rss_cfg *r; |
2439 | |
2440 | /* verify if the protocol header is non zero and VSI is valid */ |
2441 | if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) |
2442 | return ICE_HASH_INVALID; |
2443 | |
2444 | mutex_lock(&hw->rss_locks); |
2445 | list_for_each_entry(r, &hw->rss_list_head, l_entry) |
2446 | if (test_bit(vsi_handle, r->vsis) && |
2447 | r->packet_hdr == hdrs) { |
2448 | rss_hash = r->hashed_flds; |
2449 | break; |
2450 | } |
2451 | mutex_unlock(lock: &hw->rss_locks); |
2452 | |
2453 | return rss_hash; |
2454 | } |
2455 | |