net/ice/base: check new FD filter duplication
[dpdk.git] / drivers / net / ice / base / ice_fdir.c
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_ONE;
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                                 if (rule->fltr_id == input->fltr_id &&
697                                     rule->q_index != input->q_index)
698                                         ret = false;
699                                 else
700                                         break;
701                         }
702                 }
703         }
704
705         return ret;
706 }
707
708 /**
709  * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI
710  * @hw: hardware data structure
711  * @vsi_num: vsi_num (HW VSI num)
712  *
713  * Clears FD table entries by issuing admin command (direct, 0x0B06)
714  * Must to pass valid vsi_num as returned by "AddVSI".
715  */
716 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)
717 {
718         struct ice_aqc_clear_fd_table *cmd;
719         struct ice_aq_desc desc;
720
721         cmd = &desc.params.clear_fd_table;
722         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
723         cmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX;
724
725         cmd->vsi_index = CPU_TO_LE16(vsi_num);
726         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
727 }
728
729 /**
730  * ice_clear_pf_fd_table - admin command to clear FD table for PF
731  * @hw: hardware data structure
732  *
733  * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)
734  */
735 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)
736 {
737         struct ice_aqc_clear_fd_table *cmd;
738         struct ice_aq_desc desc;
739
740         cmd = &desc.params.clear_fd_table;
741         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
742         cmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX;
743         /* vsi_index must be 0 to clear FD table for a PF */
744         cmd->vsi_index = CPU_TO_LE16(0);
745
746         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
747 }