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