xref: /dpdk/drivers/net/ice/base/ice_fdir.c (revision d6cefc11)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2019
3  */
4 
5 #include "ice_common.h"
6 #include "ice_fdir.h"
7 
8 /* These are dummy packet headers used to program flow director filters. */
9 static const u8 ice_fdir_tcpv4_pkt[] = {
10 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
12 	0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
13 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
16 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00
17 };
18 
19 static const u8 ice_fdir_udpv4_pkt[] = {
20 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
22 	0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
23 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 	0x00, 0x00,
26 };
27 
28 static const u8 ice_fdir_sctpv4_pkt[] = {
29 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
31 	0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84,
32 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 };
36 
37 static const u8 ice_fdir_ipv4_pkt[] = {
38 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
40 	0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10,
41 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 	0x00, 0x00
43 };
44 
45 static const u8 ice_fdir_tcpv6_pkt[] = {
46 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
48 	0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
49 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 	0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,
55 	0x00, 0x00,
56 };
57 
58 static const u8 ice_fdir_udpv6_pkt[] = {
59 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
61 	0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00,
62 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 	0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
67 };
68 
69 static const u8 ice_fdir_sctpv6_pkt[] = {
70 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
72 	0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x00,
73 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 	0x00, 0x00,
79 };
80 
81 static const u8 ice_fdir_ipv6_pkt[] = {
82 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
84 	0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00,
85 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 };
90 
91 /* Flow Director dummy packet table */
92 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
93 	{
94 		ICE_FLTR_PTYPE_NONF_IPV4_TCP,
95 		sizeof(ice_fdir_tcpv4_pkt),
96 		ice_fdir_tcpv4_pkt,
97 	},
98 	{
99 		ICE_FLTR_PTYPE_NONF_IPV4_UDP,
100 		sizeof(ice_fdir_udpv4_pkt),
101 		ice_fdir_udpv4_pkt,
102 	},
103 	{
104 		ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
105 		sizeof(ice_fdir_sctpv4_pkt),
106 		ice_fdir_sctpv4_pkt,
107 	},
108 	{
109 		ICE_FLTR_PTYPE_NONF_IPV4_OTHER,
110 		sizeof(ice_fdir_ipv4_pkt),
111 		ice_fdir_ipv4_pkt,
112 	},
113 	{
114 		ICE_FLTR_PTYPE_NONF_IPV6_TCP,
115 		sizeof(ice_fdir_tcpv6_pkt),
116 		ice_fdir_tcpv6_pkt,
117 	},
118 	{
119 		ICE_FLTR_PTYPE_NONF_IPV6_UDP,
120 		sizeof(ice_fdir_udpv6_pkt),
121 		ice_fdir_udpv6_pkt,
122 	},
123 	{
124 		ICE_FLTR_PTYPE_NONF_IPV6_SCTP,
125 		sizeof(ice_fdir_sctpv6_pkt),
126 		ice_fdir_sctpv6_pkt,
127 	},
128 	{
129 		ICE_FLTR_PTYPE_NONF_IPV6_OTHER,
130 		sizeof(ice_fdir_ipv6_pkt),
131 		ice_fdir_ipv6_pkt,
132 	},
133 };
134 
135 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
136 
137 /* Flow Direcotr (FD) filter program descriptor Context */
138 static const struct ice_ctx_ele ice_fd_fltr_desc_ctx_info[] = {
139 					   /* Field		Width	LSB */
140 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, qindex,		11,	0),
141 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_q,		1,	11),
142 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_report,	2,	12),
143 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_space,		2,	14),
144 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_index,		13,	16),
145 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_ena,		2,	29),
146 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, evict_ena,		1,	31),
147 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq,		3,	32),
148 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq_prio,		3,	35),
149 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dpu_recipe,		2,	38),
150 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, drop,		1,	40),
151 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_prio,		3,	41),
152 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_mdid,		4,	44),
153 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_val,		16,	48),
154 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, dtype,		4,	64),
155 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, pcmd,		1,	68),
156 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof_prio,	3,	69),
157 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof,		6,	72),
158 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_vsi,		10,	78),
159 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, swap,		1,	88),
160 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_prio,		3,	89),
161 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_mdid,		4,	92),
162 	ICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid,		32,	96),
163 	{ 0 }
164 };
165 
166 /**
167  * ice_set_dflt_val_fd_desc
168  * @fd_fltr_ctx: pointer to fd filter descriptor
169  */
170 void
171 ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
172 {
173 	fd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
174 	fd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
175 	fd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST;
176 	fd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
177 	fd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE;
178 	fd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX;
179 	fd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1;
180 	fd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT;
181 	fd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO;
182 	fd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE;
183 	fd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0;
184 	fd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0;
185 	fd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG;
186 	fd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO;
187 	fd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO;
188 	fd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET;
189 	fd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ZERO;
190 	fd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD;
191 	fd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO;
192 }
193 
194 /**
195  * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
196  * @hw: pointer to the hardware structure
197  * @input: filter
198  * @fdesc: filter descriptor
199  * @add: if add is true, this is an add operation, false implies delete
200  */
201 void
202 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
203 		       struct ice_fltr_desc *fdesc, bool add)
204 {
205 	struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
206 
207 	/* set default context info */
208 	ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
209 
210 	/* change sideband filtering values */
211 	fdir_fltr_ctx.fdid = input->fltr_id;
212 	if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {
213 		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;
214 		fdir_fltr_ctx.qindex = 0;
215 	} else {
216 		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
217 		fdir_fltr_ctx.qindex = input->q_index;
218 	}
219 	fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
220 	fdir_fltr_ctx.cnt_index = input->cnt_index;
221 	fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
222 	fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
223 	fdir_fltr_ctx.toq_prio = 3;
224 	fdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD :
225 		ICE_FXD_FLTR_QW1_PCMD_REMOVE;
226 	fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
227 	fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
228 	fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;
229 	fdir_fltr_ctx.fdid_prio = 3;
230 	fdir_fltr_ctx.desc_prof = 1;
231 	fdir_fltr_ctx.desc_prof_prio = 3;
232 	ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
233 }
234 
235 /**
236  * ice_set_fd_desc_val
237  * @fd_fltr_ctx: pointer to fd filter descriptor context
238  * @fdir_desc: populated with fd filter descriptor values
239  */
240 void
241 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,
242 		    struct ice_fltr_desc *fdir_desc)
243 {
244 	u64 ctx_buf[2] = { 0 };
245 
246 	ice_set_ctx((u8 *)fd_fltr_ctx, (u8 *)ctx_buf,
247 		    ice_fd_fltr_desc_ctx_info);
248 	fdir_desc->qidx_compq_space_stat = CPU_TO_LE64(ctx_buf[0]);
249 	fdir_desc->dtype_cmd_vsi_fdid = CPU_TO_LE64(ctx_buf[1]);
250 }
251 
252 /**
253  * ice_alloc_fd_res_cntr - obtain counter resource for FD type
254  * @hw: pointer to the hardware structure
255  * @cntr_id: returns counter index
256  */
257 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
258 {
259 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
260 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
261 }
262 
263 /**
264  * ice_free_fd_res_cntr - Free counter resource for FD type
265  * @hw: pointer to the hardware structure
266  * @cntr_id: counter index to be freed
267  */
268 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
269 {
270 	return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
271 				 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
272 }
273 
274 /**
275  * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries
276  * @hw: pointer to the hardware structure
277  * @cntr_id: returns counter index
278  * @num_fltr: number of filter entries to be allocated
279  */
280 enum ice_status
281 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
282 {
283 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
284 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
285 				  cntr_id);
286 }
287 
288 /**
289  * ice_free_fd_guar_item - Free flow director guaranteed entries
290  * @hw: pointer to the hardware structure
291  * @cntr_id: counter index that needs to be freed
292  * @num_fltr: number of filters to be freed
293  */
294 enum ice_status
295 ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
296 {
297 	return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
298 				 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
299 				 cntr_id);
300 }
301 
302 /**
303  * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries
304  * @hw: pointer to the hardware structure
305  * @cntr_id: returns counter index
306  * @num_fltr: number of filter entries to be allocated
307  */
308 enum ice_status
309 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
310 {
311 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
312 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
313 				  cntr_id);
314 }
315 
316 /**
317  * ice_free_fd_shrd_item - Free flow director shared entries
318  * @hw: pointer to the hardware structure
319  * @cntr_id: counter index that needs to be freed
320  * @num_fltr: number of filters to be freed
321  */
322 enum ice_status
323 ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
324 {
325 	return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
326 				 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
327 				 cntr_id);
328 }
329 
330 /**
331  * ice_get_fdir_cnt_all - get the number of Flow Director filters
332  * @hw: hardware data structure
333  *
334  * Returns the number of filters available on device
335  */
336 int ice_get_fdir_cnt_all(struct ice_hw *hw)
337 {
338 	return hw->func_caps.fd_fltr_guar +
339 	       hw->func_caps.fd_fltr_best_effort;
340 }
341 
342 /**
343  * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer.
344  * @pkt: packet buffer
345  * @offset: offset into buffer
346  * @addr: IPv6 address to convert and insert into pkt at offset
347  */
348 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
349 {
350 	int idx;
351 
352 	for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
353 		ice_memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
354 			   sizeof(*addr), ICE_NONDMA_TO_NONDMA);
355 }
356 
357 /**
358  * ice_pkt_insert_u16 - insert a be16 value into a memory buffer.
359  * @pkt: packet buffer
360  * @offset: offset into buffer
361  * @data: 16 bit value to convert and insert into pkt at offset
362  */
363 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
364 {
365 	ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
366 }
367 
368 /**
369  * ice_pkt_insert_u32 - insert a be32 value into a memory buffer.
370  * @pkt: packet buffer
371  * @offset: offset into buffer
372  * @data: 32 bit value to convert and insert into pkt at offset
373  */
374 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
375 {
376 	ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
377 }
378 
379 /**
380  * ice_fdir_get_prgm_pkt - generate a dummy packet
381  * @input: flow director filter data structure
382  * @pkt: pointer to return filter packet
383  * @frag: generate a fragment packet
384  */
385 enum ice_status
386 ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag)
387 {
388 	enum ice_fltr_ptype flow;
389 	u16 idx;
390 
391 	if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
392 		switch (input->ip.v4.proto) {
393 		case ICE_IP_PROTO_TCP:
394 			flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
395 			break;
396 		case ICE_IP_PROTO_UDP:
397 			flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
398 			break;
399 		case ICE_IP_PROTO_SCTP:
400 			flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
401 			break;
402 		case ICE_IP_PROTO_IP:
403 			flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
404 			break;
405 		default:
406 			return ICE_ERR_PARAM;
407 		}
408 	} else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
409 		switch (input->ip.v6.proto) {
410 		case ICE_IP_PROTO_TCP:
411 			flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
412 			break;
413 		case ICE_IP_PROTO_UDP:
414 			flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
415 			break;
416 		case ICE_IP_PROTO_SCTP:
417 			flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
418 			break;
419 		case ICE_IP_PROTO_IP:
420 			flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
421 			break;
422 		default:
423 			return ICE_ERR_PARAM;
424 		}
425 	} else {
426 		flow = input->flow_type;
427 	}
428 
429 	for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
430 		if (ice_fdir_pkt[idx].flow == flow)
431 			break;
432 	if (idx == ICE_FDIR_NUM_PKT)
433 		return ICE_ERR_PARAM;
434 	ice_memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len,
435 		   ICE_NONDMA_TO_NONDMA);
436 
437 	switch (flow) {
438 	case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
439 		ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,
440 				   input->ip.v4.dst_ip);
441 		ice_pkt_insert_u16(pkt, ICE_IPV4_TCP_DST_PORT_OFFSET,
442 				   input->ip.v4.dst_port);
443 		ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,
444 				   input->ip.v4.src_ip);
445 		ice_pkt_insert_u16(pkt, ICE_IPV4_TCP_SRC_PORT_OFFSET,
446 				   input->ip.v4.src_port);
447 		if (frag)
448 			pkt[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
449 		break;
450 	case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
451 		ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,
452 				   input->ip.v4.dst_ip);
453 		ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
454 				   input->ip.v4.dst_port);
455 		ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,
456 				   input->ip.v4.src_ip);
457 		ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_SRC_PORT_OFFSET,
458 				   input->ip.v4.src_port);
459 		break;
460 	case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
461 		ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,
462 				   input->ip.v4.dst_ip);
463 		ice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_DST_PORT_OFFSET,
464 				   input->ip.v4.dst_port);
465 		ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,
466 				   input->ip.v4.src_ip);
467 		ice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
468 				   input->ip.v4.src_port);
469 		break;
470 	case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
471 		ice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,
472 				   input->ip.v4.dst_ip);
473 		ice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,
474 				   input->ip.v4.src_ip);
475 		ice_pkt_insert_u16(pkt, ICE_IPV4_PROTO_OFFSET, 0);
476 		break;
477 	case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
478 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,
479 					 input->ip.v6.dst_ip);
480 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,
481 					 input->ip.v6.src_ip);
482 		ice_pkt_insert_u16(pkt, ICE_IPV6_TCP_DST_PORT_OFFSET,
483 				   input->ip.v6.dst_port);
484 		ice_pkt_insert_u16(pkt, ICE_IPV6_TCP_SRC_PORT_OFFSET,
485 				   input->ip.v6.src_port);
486 		break;
487 	case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
488 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,
489 					 input->ip.v6.dst_ip);
490 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,
491 					 input->ip.v6.src_ip);
492 		ice_pkt_insert_u16(pkt, ICE_IPV6_UDP_DST_PORT_OFFSET,
493 				   input->ip.v6.dst_port);
494 		ice_pkt_insert_u16(pkt, ICE_IPV6_UDP_SRC_PORT_OFFSET,
495 				   input->ip.v6.src_port);
496 		break;
497 	case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
498 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,
499 					 input->ip.v6.dst_ip);
500 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,
501 					 input->ip.v6.src_ip);
502 		ice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_DST_PORT_OFFSET,
503 				   input->ip.v6.dst_port);
504 		ice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
505 				   input->ip.v6.src_port);
506 		break;
507 	case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
508 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,
509 					 input->ip.v6.dst_ip);
510 		ice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,
511 					 input->ip.v6.src_ip);
512 		break;
513 	default:
514 		return ICE_ERR_PARAM;
515 	}
516 
517 	if (input->flex_fltr)
518 		ice_pkt_insert_u16(pkt, input->flex_offset, input->flex_word);
519 
520 	return ICE_SUCCESS;
521 }
522 
523 /**
524  * ice_fdir_has_frag - does flow type have 2 ptypes
525  * @flow: flow ptype
526  *
527  * returns true is there is a fragment packet for this ptype
528  */
529 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
530 {
531 	if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
532 		return true;
533 	else
534 		return false;
535 }
536 
537 /**
538  * ice_fdir_find_by_idx - find filter with idx
539  * @hw: pointer to hardware structure
540  * @fltr_idx: index to find.
541  *
542  * Returns pointer to filter if found or null
543  */
544 struct ice_fdir_fltr *
545 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
546 {
547 	struct ice_fdir_fltr *rule = NULL;
548 
549 	LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
550 			    fltr_node) {
551 		/* rule ID found in the list */
552 		if (fltr_idx == rule->fltr_id)
553 			return rule;
554 		if (fltr_idx < rule->fltr_id)
555 			break;
556 	}
557 	return NULL;
558 }
559 
560 /**
561  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
562  * @hw: hardware structure
563  * @fltr: filter node to add to structure
564  */
565 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
566 {
567 	struct ice_fdir_fltr *rule, *parent = NULL;
568 
569 	LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
570 			    fltr_node) {
571 		/* rule ID found or pass its spot in the list */
572 		if (rule->fltr_id >= fltr->fltr_id)
573 			break;
574 		parent = rule;
575 	}
576 
577 	if (parent)
578 		LIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node);
579 	else
580 		LIST_ADD(&fltr->fltr_node, &hw->fdir_list_head);
581 }
582 
583 /**
584  * ice_fdir_update_cntrs - increment / decrement filter counter
585  * @hw: pointer to hardware structure
586  * @flow: filter flow type
587  * @add: true implies filters added
588  */
589 void
590 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
591 {
592 	int incr;
593 
594 	incr = (add) ? 1 : -1;
595 	hw->fdir_active_fltr += incr;
596 	if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
597 		ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
598 	else
599 		hw->fdir_fltr_cnt[flow] += incr;
600 }
601 
602 /**
603  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
604  * @a: IP v6 address
605  * @b: IP v6 address
606  *
607  * Returns 0 on equal, returns non-0 if different
608  */
609 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
610 {
611 	return memcmp(a, b, 4 * sizeof(__be32));
612 }
613 
614 /**
615  * ice_fdir_comp_ipv6_rules - compare 2 filters
616  * @a: a Flow Director filter data structure
617  * @b: a Flow Director filter data structure
618  * @v6: bool true if v6 filter
619  *
620  * Returns true if the filters match
621  */
622 static bool
623 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
624 {
625 	enum ice_fltr_ptype flow_type = a->flow_type;
626 
627 	/* The calling function already checks that the two filters have the
628 	 * same flow_type.
629 	 */
630 	if (!v6) {
631 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
632 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
633 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
634 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
635 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
636 			    a->ip.v4.dst_port == b->ip.v4.dst_port &&
637 			    a->ip.v4.src_port == b->ip.v4.src_port)
638 				return true;
639 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
640 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
641 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
642 			    a->ip.v4.l4_header == b->ip.v4.l4_header &&
643 			    a->ip.v4.proto == b->ip.v4.proto &&
644 			    a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
645 			    a->ip.v4.tos == b->ip.v4.tos)
646 				return true;
647 		}
648 	} else {
649 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
650 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
651 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
652 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
653 			    a->ip.v6.src_port == b->ip.v6.src_port &&
654 			    !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
655 					       b->ip.v6.dst_ip) &&
656 			    !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
657 					       b->ip.v6.src_ip))
658 				return true;
659 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
660 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
661 			    a->ip.v6.src_port == b->ip.v6.src_port)
662 				return true;
663 		}
664 	}
665 
666 	return false;
667 }
668 
669 /**
670  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
671  * @hw: hardware data structure
672  * @input: Flow Director filter data structure
673  *
674  * Returns true if the filter is found in the list
675  */
676 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
677 {
678 	enum ice_fltr_ptype flow_type;
679 	struct ice_fdir_fltr *rule;
680 	bool ret = false;
681 
682 	rule = NULL;
683 
684 	LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
685 			    fltr_node) {
686 		if (rule->flow_type == input->flow_type) {
687 			flow_type = input->flow_type;
688 			if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
689 			    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
690 			    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
691 			    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
692 				ret = ice_fdir_comp_rules(rule, input, false);
693 			else
694 				ret = ice_fdir_comp_rules(rule, input, true);
695 			if (ret)
696 				break;
697 		}
698 	}
699 
700 	return ret;
701 }
702 
703 /**
704  * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI
705  * @hw: hardware data structure
706  * @vsi_num: vsi_num (HW VSI num)
707  *
708  * Clears FD table entries by issuing admin command (direct, 0x0B06)
709  * Must to pass valid vsi_num as returned by "AddVSI".
710  */
711 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)
712 {
713 	struct ice_aqc_clear_fd_table *cmd;
714 	struct ice_aq_desc desc;
715 
716 	cmd = &desc.params.clear_fd_table;
717 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
718 	cmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX;
719 
720 	cmd->vsi_index = CPU_TO_LE16(vsi_num);
721 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
722 }
723 
724 /**
725  * ice_clear_pf_fd_table - admin command to clear FD table for PF
726  * @hw: hardware data structure
727  *
728  * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)
729  */
730 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)
731 {
732 	struct ice_aqc_clear_fd_table *cmd;
733 	struct ice_aq_desc desc;
734 
735 	cmd = &desc.params.clear_fd_table;
736 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
737 	cmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX;
738 	/* vsi_index must be 0 to clear FD table for a PF */
739 	cmd->vsi_index = CPU_TO_LE16(0);
740 
741 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
742 }
743