1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2019
5 #include "ice_common.h"
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
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,
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,
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,
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,
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,
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,
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,
91 /* Flow Director dummy packet table */
92 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
94 ICE_FLTR_PTYPE_NONF_IPV4_TCP,
95 sizeof(ice_fdir_tcpv4_pkt),
99 ICE_FLTR_PTYPE_NONF_IPV4_UDP,
100 sizeof(ice_fdir_udpv4_pkt),
104 ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
105 sizeof(ice_fdir_sctpv4_pkt),
109 ICE_FLTR_PTYPE_NONF_IPV4_OTHER,
110 sizeof(ice_fdir_ipv4_pkt),
114 ICE_FLTR_PTYPE_NONF_IPV6_TCP,
115 sizeof(ice_fdir_tcpv6_pkt),
119 ICE_FLTR_PTYPE_NONF_IPV6_UDP,
120 sizeof(ice_fdir_udpv6_pkt),
124 ICE_FLTR_PTYPE_NONF_IPV6_SCTP,
125 sizeof(ice_fdir_sctpv6_pkt),
129 ICE_FLTR_PTYPE_NONF_IPV6_OTHER,
130 sizeof(ice_fdir_ipv6_pkt),
135 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
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),
167 * ice_set_dflt_val_fd_desc
168 * @fd_fltr_ctx: pointer to fd filter descriptor
171 ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
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;
195 * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
196 * @hw: pointer to the hardware structure
198 * @fdesc: filter descriptor
199 * @add: if add is true, this is an add operation, false implies delete
202 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
203 struct ice_fltr_desc *fdesc, bool add)
205 struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
207 /* set default context info */
208 ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
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;
216 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
217 fdir_fltr_ctx.qindex = input->q_index;
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);
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
241 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,
242 struct ice_fltr_desc *fdir_desc)
244 u64 ctx_buf[2] = { 0 };
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]);
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
257 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
259 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
260 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
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
268 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
270 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
271 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
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
281 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
283 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
284 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
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
295 ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
297 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
298 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
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
309 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
311 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
312 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
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
323 ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
325 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
326 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
331 * ice_get_fdir_cnt_all - get the number of Flow Director filters
332 * @hw: hardware data structure
334 * Returns the number of filters available on device
336 int ice_get_fdir_cnt_all(struct ice_hw *hw)
338 return hw->func_caps.fd_fltr_guar +
339 hw->func_caps.fd_fltr_best_effort;
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
348 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
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);
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
363 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
365 ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
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
374 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
376 ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
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
386 ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag)
388 enum ice_fltr_ptype flow;
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;
396 case ICE_IP_PROTO_UDP:
397 flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
399 case ICE_IP_PROTO_SCTP:
400 flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
402 case ICE_IP_PROTO_IP:
403 flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
406 return ICE_ERR_PARAM;
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;
413 case ICE_IP_PROTO_UDP:
414 flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
416 case ICE_IP_PROTO_SCTP:
417 flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
419 case ICE_IP_PROTO_IP:
420 flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
423 return ICE_ERR_PARAM;
426 flow = input->flow_type;
429 for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
430 if (ice_fdir_pkt[idx].flow == flow)
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);
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);
448 pkt[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
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);
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);
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);
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);
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);
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);
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);
514 return ICE_ERR_PARAM;
517 if (input->flex_fltr)
518 ice_pkt_insert_u16(pkt, input->flex_offset, input->flex_word);
524 * ice_fdir_has_frag - does flow type have 2 ptypes
527 * returns true is there is a fragment packet for this ptype
529 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
531 if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
538 * ice_fdir_find_by_idx - find filter with idx
539 * @hw: pointer to hardware structure
540 * @fltr_idx: index to find.
542 * Returns pointer to filter if found or null
544 struct ice_fdir_fltr *
545 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
547 struct ice_fdir_fltr *rule = NULL;
549 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
551 /* rule ID found in the list */
552 if (fltr_idx == rule->fltr_id)
554 if (fltr_idx < rule->fltr_id)
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
565 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
567 struct ice_fdir_fltr *rule, *parent = NULL;
569 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
571 /* rule ID found or pass its spot in the list */
572 if (rule->fltr_id >= fltr->fltr_id)
578 LIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node);
580 LIST_ADD(&fltr->fltr_node, &hw->fdir_list_head);
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
590 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
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);
599 hw->fdir_fltr_cnt[flow] += incr;
603 * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
607 * Returns 0 on equal, returns non-0 if different
609 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
611 return memcmp(a, b, 4 * sizeof(__be32));
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
620 * Returns true if the filters match
623 ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b, bool v6)
625 enum ice_fltr_ptype flow_type = a->flow_type;
627 /* The calling function already checks that the two filters have the
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)
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)
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,
656 !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
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)
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
674 * Returns true if the filter is found in the list
676 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
678 enum ice_fltr_ptype flow_type;
679 struct ice_fdir_fltr *rule;
684 LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
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);
694 ret = ice_fdir_comp_rules(rule, input, true);
696 if (rule->fltr_id == input->fltr_id &&
697 rule->q_index != input->q_index)
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)
713 * Clears FD table entries by issuing admin command (direct, 0x0B06)
714 * Must to pass valid vsi_num as returned by "AddVSI".
716 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)
718 struct ice_aqc_clear_fd_table *cmd;
719 struct ice_aq_desc desc;
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;
725 cmd->vsi_index = CPU_TO_LE16(vsi_num);
726 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
730 * ice_clear_pf_fd_table - admin command to clear FD table for PF
731 * @hw: hardware data structure
733 * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)
735 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)
737 struct ice_aqc_clear_fd_table *cmd;
738 struct ice_aq_desc desc;
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);
746 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);