Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2016 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <errno.h>
8 : : #include <stdint.h>
9 : : #include <stddef.h>
10 : : #include <string.h>
11 : : #include <unistd.h>
12 : : #include <stdarg.h>
13 : : #include <inttypes.h>
14 : : #include <rte_byteorder.h>
15 : : #include <rte_common.h>
16 : : #include <rte_cycles.h>
17 : :
18 : : #include <rte_interrupts.h>
19 : : #include <rte_log.h>
20 : : #include <rte_debug.h>
21 : : #include <rte_pci.h>
22 : : #include <rte_branch_prediction.h>
23 : : #include <rte_memory.h>
24 : : #include <rte_eal.h>
25 : : #include <rte_alarm.h>
26 : : #include <rte_ether.h>
27 : : #include <rte_tailq.h>
28 : : #include <ethdev_driver.h>
29 : : #include <rte_malloc.h>
30 : : #include <rte_random.h>
31 : : #include <dev_driver.h>
32 : : #include <rte_hash_crc.h>
33 : : #include <rte_flow.h>
34 : : #include <rte_hexdump.h>
35 : : #include <rte_flow_driver.h>
36 : :
37 : : #include "ixgbe_logs.h"
38 : : #include "base/ixgbe_api.h"
39 : : #include "base/ixgbe_vf.h"
40 : : #include "base/ixgbe_common.h"
41 : : #include "base/ixgbe_osdep.h"
42 : : #include "ixgbe_ethdev.h"
43 : : #include "ixgbe_bypass.h"
44 : : #include "ixgbe_rxtx.h"
45 : : #include "base/ixgbe_type.h"
46 : : #include "base/ixgbe_phy.h"
47 : : #include "rte_pmd_ixgbe.h"
48 : :
49 : : #include "../common/flow_check.h"
50 : :
51 : :
52 : : #define IXGBE_MIN_N_TUPLE_PRIO 1
53 : : #define IXGBE_MAX_N_TUPLE_PRIO 7
54 : : #define IXGBE_MAX_FLX_SOURCE_OFF 62
55 : :
56 : : struct ixgbe_filter_ele_base {
57 : : TAILQ_ENTRY(ixgbe_filter_ele_base) entries;
58 : : };
59 : :
60 : : /* ntuple filter list structure */
61 : : struct ixgbe_ntuple_filter_ele {
62 : : struct ixgbe_filter_ele_base base;
63 : : struct rte_eth_ntuple_filter filter_info;
64 : : };
65 : : /* ethertype filter list structure */
66 : : struct ixgbe_ethertype_filter_ele {
67 : : struct ixgbe_filter_ele_base base;
68 : : struct rte_eth_ethertype_filter filter_info;
69 : : };
70 : : /* syn filter list structure */
71 : : struct ixgbe_eth_syn_filter_ele {
72 : : struct ixgbe_filter_ele_base base;
73 : : struct rte_eth_syn_filter filter_info;
74 : : };
75 : : /* fdir filter list structure */
76 : : struct ixgbe_fdir_rule_ele {
77 : : struct ixgbe_filter_ele_base base;
78 : : struct ixgbe_fdir_rule filter_info;
79 : : };
80 : : /* l2_tunnel filter list structure */
81 : : struct ixgbe_eth_l2_tunnel_conf_ele {
82 : : struct ixgbe_filter_ele_base base;
83 : : struct ixgbe_l2_tunnel_conf filter_info;
84 : : };
85 : : /* rss filter list structure */
86 : : struct ixgbe_rss_conf_ele {
87 : : struct ixgbe_filter_ele_base base;
88 : : struct ixgbe_rte_flow_rss_conf filter_info;
89 : : };
90 : : /* ixgbe_flow memory list structure */
91 : : struct ixgbe_flow_mem {
92 : : struct ixgbe_filter_ele_base base;
93 : : struct rte_flow *flow;
94 : : };
95 : :
96 : : /**
97 : : * Endless loop will never happen with below assumption
98 : : * 1. there is at least one no-void item(END)
99 : : * 2. cur is before END.
100 : : */
101 : : static inline
102 : : const struct rte_flow_item *next_no_void_pattern(
103 : : const struct rte_flow_item pattern[],
104 : : const struct rte_flow_item *cur)
105 : : {
106 : : const struct rte_flow_item *next =
107 : 0 : cur ? cur + 1 : &pattern[0];
108 : : while (1) {
109 [ # # # # : 0 : if (next->type != RTE_FLOW_ITEM_TYPE_VOID)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
110 : : return next;
111 : 0 : next++;
112 : : }
113 : : }
114 : :
115 : : /*
116 : : * All ixgbe engines mostly check the same stuff, so use a common check.
117 : : */
118 : : static int
119 : 0 : ixgbe_flow_actions_check(const struct ci_flow_actions *actions,
120 : : const struct ci_flow_actions_check_param *param,
121 : : struct rte_flow_error *error)
122 : : {
123 : : const struct rte_flow_action *action;
124 : 0 : struct rte_eth_dev_data *dev_data = param->driver_ctx;
125 : 0 : struct ixgbe_adapter *ad = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev_data->dev_private);
126 : : size_t idx;
127 : :
128 [ # # ]: 0 : for (idx = 0; idx < actions->count; idx++) {
129 : 0 : action = actions->actions[idx];
130 : :
131 [ # # # ]: 0 : switch (action->type) {
132 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
133 : : {
134 : 0 : const struct rte_flow_action_queue *queue = action->conf;
135 [ # # ]: 0 : if (queue->index >= dev_data->nb_rx_queues) {
136 : 0 : return rte_flow_error_set(error, EINVAL,
137 : : RTE_FLOW_ERROR_TYPE_ACTION,
138 : : action,
139 : : "queue index out of range");
140 : : }
141 : : break;
142 : : }
143 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
144 : : {
145 : 0 : const struct rte_flow_action_vf *vf = action->conf;
146 [ # # ]: 0 : if (vf->id >= ad->max_vfs) {
147 : 0 : return rte_flow_error_set(error, EINVAL,
148 : : RTE_FLOW_ERROR_TYPE_ACTION,
149 : : action,
150 : : "VF id out of range");
151 : : }
152 : : break;
153 : : }
154 : : default:
155 : : /* no specific validation */
156 : : break;
157 : : }
158 : : }
159 : : return 0;
160 : : }
161 : :
162 : : /**
163 : : * Please be aware there's an assumption for all the parsers.
164 : : * rte_flow_item is using big endian, rte_flow_attr and
165 : : * rte_flow_action are using CPU order.
166 : : * Because the pattern is used to describe the packets,
167 : : * normally the packets should use network order.
168 : : */
169 : :
170 : : /**
171 : : * Parse the rule to see if it is a n-tuple rule.
172 : : * And get the n-tuple filter info BTW.
173 : : * pattern:
174 : : * The first not void item can be ETH or IPV4.
175 : : * The second not void item must be IPV4 if the first one is ETH.
176 : : * The third not void item must be UDP or TCP.
177 : : * The next not void item must be END.
178 : : * action:
179 : : * The first not void action should be QUEUE.
180 : : * The next not void action should be END.
181 : : * pattern example:
182 : : * ITEM Spec Mask
183 : : * ETH NULL NULL
184 : : * IPV4 src_addr 192.168.1.20 0xFFFFFFFF
185 : : * dst_addr 192.167.3.50 0xFFFFFFFF
186 : : * next_proto_id 17 0xFF
187 : : * UDP/TCP/ src_port 80 0xFFFF
188 : : * SCTP dst_port 80 0xFFFF
189 : : * END
190 : : * other members in mask and spec should set to 0x00.
191 : : * item->last should be NULL.
192 : : *
193 : : * Special case for flow action type RTE_FLOW_ACTION_TYPE_SECURITY.
194 : : *
195 : : */
196 : : static int
197 : 0 : cons_parse_ntuple_filter(const struct rte_flow_attr *attr,
198 : : const struct rte_flow_item pattern[],
199 : : const struct rte_flow_action_queue *q_act,
200 : : struct rte_eth_ntuple_filter *filter,
201 : : struct rte_flow_error *error)
202 : : {
203 : : const struct rte_flow_item *item;
204 : : const struct rte_flow_item_ipv4 *ipv4_spec;
205 : : const struct rte_flow_item_ipv4 *ipv4_mask;
206 : : const struct rte_flow_item_tcp *tcp_spec;
207 : : const struct rte_flow_item_tcp *tcp_mask;
208 : : const struct rte_flow_item_udp *udp_spec;
209 : : const struct rte_flow_item_udp *udp_mask;
210 : : const struct rte_flow_item_sctp *sctp_spec;
211 : : const struct rte_flow_item_sctp *sctp_mask;
212 : : const struct rte_flow_item_eth *eth_spec;
213 : : const struct rte_flow_item_eth *eth_mask;
214 : : const struct rte_flow_item_vlan *vlan_spec;
215 : : const struct rte_flow_item_vlan *vlan_mask;
216 : : struct rte_flow_item_eth eth_null;
217 : : struct rte_flow_item_vlan vlan_null;
218 : :
219 : : /* Priority must be 16-bit */
220 [ # # ]: 0 : if (attr->priority > UINT16_MAX) {
221 : 0 : return rte_flow_error_set(error, EINVAL,
222 : : RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
223 : : "Priority must be 16-bit");
224 : : }
225 : :
226 : : memset(ð_null, 0, sizeof(struct rte_flow_item_eth));
227 : : memset(&vlan_null, 0, sizeof(struct rte_flow_item_vlan));
228 : :
229 : : /* the first not void item can be MAC or IPv4 */
230 : : item = next_no_void_pattern(pattern, NULL);
231 : :
232 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
233 : : item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
234 : 0 : rte_flow_error_set(error, EINVAL,
235 : : RTE_FLOW_ERROR_TYPE_ITEM,
236 : : item, "Not supported by ntuple filter");
237 : 0 : return -rte_errno;
238 : : }
239 : : /* Skip Ethernet */
240 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
241 : 0 : eth_spec = item->spec;
242 : 0 : eth_mask = item->mask;
243 : : /*Not supported last point for range*/
244 [ # # ]: 0 : if (item->last) {
245 : 0 : rte_flow_error_set(error,
246 : : EINVAL,
247 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
248 : : item, "Not supported last point for range");
249 : 0 : return -rte_errno;
250 : :
251 : : }
252 : : /* if the first item is MAC, the content should be NULL */
253 [ # # # # : 0 : if ((item->spec != NULL && memcmp(eth_spec, ð_null, sizeof(eth_null)) != 0) ||
# # ]
254 [ # # ]: 0 : (item->mask != NULL && memcmp(eth_mask, ð_null, sizeof(eth_null)) != 0)) {
255 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
256 : : "Not supported by ntuple filter");
257 : 0 : return -rte_errno;
258 : : }
259 : : /* check if the next not void item is IPv4 or Vlan */
260 : : item = next_no_void_pattern(pattern, item);
261 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
262 : : item->type != RTE_FLOW_ITEM_TYPE_VLAN) {
263 : 0 : rte_flow_error_set(error,
264 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
265 : : item, "Not supported by ntuple filter");
266 : 0 : return -rte_errno;
267 : : }
268 : : }
269 : :
270 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
271 : 0 : vlan_spec = item->spec;
272 : 0 : vlan_mask = item->mask;
273 : : /*Not supported last point for range*/
274 [ # # ]: 0 : if (item->last) {
275 : 0 : rte_flow_error_set(error,
276 : : EINVAL,
277 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
278 : : item, "Not supported last point for range");
279 : 0 : return -rte_errno;
280 : : }
281 : : /* the content should be NULL */
282 [ # # # # : 0 : if ((item->spec != NULL && memcmp(vlan_spec, &vlan_null, sizeof(vlan_null)) != 0) ||
# # ]
283 [ # # ]: 0 : (item->mask != NULL && memcmp(vlan_mask, &vlan_null, sizeof(vlan_null)) != 0)) {
284 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item,
285 : : "Not supported by ntuple filter");
286 : 0 : return -rte_errno;
287 : : }
288 : : /* check if the next not void item is IPv4 */
289 : : item = next_no_void_pattern(pattern, item);
290 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
291 : 0 : rte_flow_error_set(error,
292 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
293 : : item, "Not supported by ntuple filter");
294 : 0 : return -rte_errno;
295 : : }
296 : : }
297 : :
298 [ # # ]: 0 : if (item->mask) {
299 : : /* get the IPv4 info */
300 [ # # ]: 0 : if (!item->spec || !item->mask) {
301 : 0 : rte_flow_error_set(error, EINVAL,
302 : : RTE_FLOW_ERROR_TYPE_ITEM,
303 : : item, "Invalid ntuple mask");
304 : 0 : return -rte_errno;
305 : : }
306 : : /*Not supported last point for range*/
307 [ # # ]: 0 : if (item->last) {
308 : 0 : rte_flow_error_set(error, EINVAL,
309 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
310 : : item, "Not supported last point for range");
311 : 0 : return -rte_errno;
312 : : }
313 : :
314 : : ipv4_mask = item->mask;
315 : : /**
316 : : * Only support src & dst addresses, protocol,
317 : : * others should be masked.
318 : : */
319 [ # # ]: 0 : if (ipv4_mask->hdr.version_ihl ||
320 : 0 : ipv4_mask->hdr.type_of_service ||
321 [ # # ]: 0 : ipv4_mask->hdr.total_length ||
322 [ # # ]: 0 : ipv4_mask->hdr.packet_id ||
323 [ # # ]: 0 : ipv4_mask->hdr.fragment_offset ||
324 [ # # ]: 0 : ipv4_mask->hdr.time_to_live ||
325 [ # # ]: 0 : ipv4_mask->hdr.hdr_checksum) {
326 : 0 : rte_flow_error_set(error,
327 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
328 : : item, "Not supported by ntuple filter");
329 : 0 : return -rte_errno;
330 : : }
331 [ # # ]: 0 : if ((ipv4_mask->hdr.src_addr != 0 &&
332 : 0 : ipv4_mask->hdr.src_addr != UINT32_MAX) ||
333 [ # # ]: 0 : (ipv4_mask->hdr.dst_addr != 0 &&
334 : 0 : ipv4_mask->hdr.dst_addr != UINT32_MAX) ||
335 [ # # ]: 0 : (ipv4_mask->hdr.next_proto_id != UINT8_MAX &&
336 : : ipv4_mask->hdr.next_proto_id != 0)) {
337 : 0 : rte_flow_error_set(error,
338 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
339 : : item, "Not supported by ntuple filter");
340 : 0 : return -rte_errno;
341 : : }
342 : :
343 : 0 : filter->dst_ip_mask = ipv4_mask->hdr.dst_addr;
344 : 0 : filter->src_ip_mask = ipv4_mask->hdr.src_addr;
345 : 0 : filter->proto_mask = ipv4_mask->hdr.next_proto_id;
346 : :
347 : : ipv4_spec = item->spec;
348 : 0 : filter->dst_ip = ipv4_spec->hdr.dst_addr;
349 : 0 : filter->src_ip = ipv4_spec->hdr.src_addr;
350 : 0 : filter->proto = ipv4_spec->hdr.next_proto_id;
351 : : }
352 : :
353 : : /* check if the next not void item is TCP or UDP */
354 : : item = next_no_void_pattern(pattern, item);
355 : 0 : if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
356 : : item->type != RTE_FLOW_ITEM_TYPE_UDP &&
357 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_SCTP &&
358 : : item->type != RTE_FLOW_ITEM_TYPE_END) {
359 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
360 : 0 : rte_flow_error_set(error, EINVAL,
361 : : RTE_FLOW_ERROR_TYPE_ITEM,
362 : : item, "Not supported by ntuple filter");
363 : 0 : return -rte_errno;
364 : : }
365 : :
366 [ # # ]: 0 : if ((item->type != RTE_FLOW_ITEM_TYPE_END) &&
367 [ # # # # ]: 0 : (!item->spec && !item->mask)) {
368 : 0 : goto action;
369 : : }
370 : :
371 : : /* get the TCP/UDP/SCTP info */
372 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END &&
373 [ # # # # ]: 0 : (!item->spec || !item->mask)) {
374 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
375 : 0 : rte_flow_error_set(error, EINVAL,
376 : : RTE_FLOW_ERROR_TYPE_ITEM,
377 : : item, "Invalid ntuple mask");
378 : 0 : return -rte_errno;
379 : : }
380 : :
381 : : /*Not supported last point for range*/
382 [ # # ]: 0 : if (item->last) {
383 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
384 : 0 : rte_flow_error_set(error, EINVAL,
385 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
386 : : item, "Not supported last point for range");
387 : 0 : return -rte_errno;
388 : :
389 : : }
390 : :
391 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_TCP) {
392 : 0 : tcp_mask = item->mask;
393 : :
394 : : /**
395 : : * Only support src & dst ports, tcp flags,
396 : : * others should be masked.
397 : : */
398 [ # # ]: 0 : if (tcp_mask->hdr.sent_seq ||
399 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
400 [ # # ]: 0 : tcp_mask->hdr.data_off ||
401 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
402 [ # # ]: 0 : tcp_mask->hdr.cksum ||
403 [ # # ]: 0 : tcp_mask->hdr.tcp_urp) {
404 : : memset(filter, 0,
405 : : sizeof(struct rte_eth_ntuple_filter));
406 : 0 : rte_flow_error_set(error, EINVAL,
407 : : RTE_FLOW_ERROR_TYPE_ITEM,
408 : : item, "Not supported by ntuple filter");
409 : 0 : return -rte_errno;
410 : : }
411 [ # # ]: 0 : if ((tcp_mask->hdr.src_port != 0 &&
412 : 0 : tcp_mask->hdr.src_port != UINT16_MAX) ||
413 [ # # ]: 0 : (tcp_mask->hdr.dst_port != 0 &&
414 : : tcp_mask->hdr.dst_port != UINT16_MAX)) {
415 : 0 : rte_flow_error_set(error,
416 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
417 : : item, "Not supported by ntuple filter");
418 : 0 : return -rte_errno;
419 : : }
420 : :
421 : 0 : filter->dst_port_mask = tcp_mask->hdr.dst_port;
422 : 0 : filter->src_port_mask = tcp_mask->hdr.src_port;
423 [ # # ]: 0 : if (tcp_mask->hdr.tcp_flags == 0xFF) {
424 : 0 : filter->flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
425 [ # # ]: 0 : } else if (!tcp_mask->hdr.tcp_flags) {
426 : 0 : filter->flags &= ~RTE_NTUPLE_FLAGS_TCP_FLAG;
427 : : } else {
428 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
429 : 0 : rte_flow_error_set(error, EINVAL,
430 : : RTE_FLOW_ERROR_TYPE_ITEM,
431 : : item, "Not supported by ntuple filter");
432 : 0 : return -rte_errno;
433 : : }
434 : :
435 : 0 : tcp_spec = item->spec;
436 : 0 : filter->dst_port = tcp_spec->hdr.dst_port;
437 : 0 : filter->src_port = tcp_spec->hdr.src_port;
438 : 0 : filter->tcp_flags = tcp_spec->hdr.tcp_flags;
439 [ # # ]: 0 : } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) {
440 : 0 : udp_mask = item->mask;
441 : :
442 : : /**
443 : : * Only support src & dst ports,
444 : : * others should be masked.
445 : : */
446 [ # # ]: 0 : if (udp_mask->hdr.dgram_len ||
447 [ # # ]: 0 : udp_mask->hdr.dgram_cksum) {
448 : : memset(filter, 0,
449 : : sizeof(struct rte_eth_ntuple_filter));
450 : 0 : rte_flow_error_set(error, EINVAL,
451 : : RTE_FLOW_ERROR_TYPE_ITEM,
452 : : item, "Not supported by ntuple filter");
453 : 0 : return -rte_errno;
454 : : }
455 [ # # ]: 0 : if ((udp_mask->hdr.src_port != 0 &&
456 : 0 : udp_mask->hdr.src_port != UINT16_MAX) ||
457 [ # # ]: 0 : (udp_mask->hdr.dst_port != 0 &&
458 : : udp_mask->hdr.dst_port != UINT16_MAX)) {
459 : 0 : rte_flow_error_set(error,
460 : : EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
461 : : item, "Not supported by ntuple filter");
462 : 0 : return -rte_errno;
463 : : }
464 : :
465 : 0 : filter->dst_port_mask = udp_mask->hdr.dst_port;
466 : 0 : filter->src_port_mask = udp_mask->hdr.src_port;
467 : :
468 : 0 : udp_spec = item->spec;
469 : 0 : filter->dst_port = udp_spec->hdr.dst_port;
470 : 0 : filter->src_port = udp_spec->hdr.src_port;
471 [ # # ]: 0 : } else if (item->type == RTE_FLOW_ITEM_TYPE_SCTP) {
472 : 0 : sctp_mask = item->mask;
473 : :
474 : : /**
475 : : * Only support src & dst ports,
476 : : * others should be masked.
477 : : */
478 [ # # ]: 0 : if (sctp_mask->hdr.tag ||
479 [ # # ]: 0 : sctp_mask->hdr.cksum) {
480 : : memset(filter, 0,
481 : : sizeof(struct rte_eth_ntuple_filter));
482 : 0 : rte_flow_error_set(error, EINVAL,
483 : : RTE_FLOW_ERROR_TYPE_ITEM,
484 : : item, "Not supported by ntuple filter");
485 : 0 : return -rte_errno;
486 : : }
487 : :
488 : 0 : filter->dst_port_mask = sctp_mask->hdr.dst_port;
489 : 0 : filter->src_port_mask = sctp_mask->hdr.src_port;
490 : :
491 : 0 : sctp_spec = item->spec;
492 : 0 : filter->dst_port = sctp_spec->hdr.dst_port;
493 : 0 : filter->src_port = sctp_spec->hdr.src_port;
494 : : } else {
495 : 0 : goto action;
496 : : }
497 : :
498 : : /* check if the next not void item is END */
499 : : item = next_no_void_pattern(pattern, item);
500 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
501 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
502 : 0 : rte_flow_error_set(error, EINVAL,
503 : : RTE_FLOW_ERROR_TYPE_ITEM,
504 : : item, "Not supported by ntuple filter");
505 : 0 : return -rte_errno;
506 : : }
507 : :
508 : 0 : action:
509 : :
510 : 0 : filter->queue = q_act->index;
511 : :
512 : 0 : filter->priority = (uint16_t)attr->priority;
513 [ # # ]: 0 : if (attr->priority < IXGBE_MIN_N_TUPLE_PRIO || attr->priority > IXGBE_MAX_N_TUPLE_PRIO)
514 : 0 : filter->priority = 1;
515 : :
516 : : return 0;
517 : : }
518 : :
519 : : static int
520 : 0 : ixgbe_parse_security_filter(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
521 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
522 : : struct rte_flow_error *error)
523 : : {
524 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
525 : : const struct rte_flow_action_security *security;
526 : : struct rte_security_session *session;
527 : : const struct rte_flow_item *item;
528 : : struct ci_flow_actions parsed_actions;
529 : 0 : struct ci_flow_actions_check_param ap_param = {
530 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
531 : : /* only security is allowed here */
532 : : RTE_FLOW_ACTION_TYPE_SECURITY,
533 : : RTE_FLOW_ACTION_TYPE_END
534 : : },
535 : : .max_actions = 1,
536 : : };
537 : : const struct rte_flow_action *action;
538 : : struct ip_spec spec;
539 : : int ret;
540 : :
541 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_82599EB &&
542 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X540 &&
543 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550 &&
544 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_x &&
545 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_a &&
546 : : hw->mac.type != ixgbe_mac_E610)
547 : : return -ENOTSUP;
548 : :
549 : : /* validate attributes */
550 : 0 : ret = ci_flow_check_attr(attr, NULL, error);
551 [ # # ]: 0 : if (ret)
552 : : return ret;
553 : :
554 : : /* parse requested actions */
555 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
556 [ # # ]: 0 : if (ret)
557 : : return ret;
558 : :
559 : 0 : action = parsed_actions.actions[0];
560 : 0 : security = action->conf;
561 : :
562 : : /* get the IP pattern*/
563 : : item = next_no_void_pattern(pattern, NULL);
564 [ # # ]: 0 : while (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
565 : : item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
566 [ # # # # ]: 0 : if (item->last || item->type == RTE_FLOW_ITEM_TYPE_END) {
567 : 0 : rte_flow_error_set(error, EINVAL,
568 : : RTE_FLOW_ERROR_TYPE_ITEM,
569 : : item, "IP pattern missing.");
570 : 0 : return -rte_errno;
571 : : }
572 : : item = next_no_void_pattern(pattern, item);
573 : : }
574 [ # # ]: 0 : if (item->spec == NULL) {
575 : 0 : rte_flow_error_set(error, EINVAL,
576 : : RTE_FLOW_ERROR_TYPE_ITEM_SPEC, item,
577 : : "NULL IP pattern.");
578 : 0 : return -rte_errno;
579 : : }
580 : 0 : spec.is_ipv6 = item->type == RTE_FLOW_ITEM_TYPE_IPV6;
581 [ # # ]: 0 : if (spec.is_ipv6) {
582 : : const struct rte_flow_item_ipv6 *ipv6 = item->spec;
583 : 0 : spec.spec.ipv6 = *ipv6;
584 : : } else {
585 : : const struct rte_flow_item_ipv4 *ipv4 = item->spec;
586 : 0 : spec.spec.ipv4 = *ipv4;
587 : : }
588 : :
589 : : /*
590 : : * we get pointer to security session from security action, which is
591 : : * const. however, we do need to act on the session, so either we do
592 : : * some kind of pointer based lookup to get session pointer internally
593 : : * (which quickly gets unwieldy for lots of flows case), or we simply
594 : : * cast away constness. the latter path was chosen.
595 : : */
596 : 0 : session = RTE_CAST_PTR(struct rte_security_session *, security->security_session);
597 : 0 : ret = ixgbe_crypto_add_ingress_sa_from_flow(session, &spec);
598 [ # # ]: 0 : if (ret) {
599 : 0 : rte_flow_error_set(error, -ret,
600 : : RTE_FLOW_ERROR_TYPE_ACTION, action,
601 : : "Failed to add security session.");
602 : 0 : return -rte_errno;
603 : : }
604 : : return 0;
605 : : }
606 : :
607 : : /* a specific function for ixgbe because the flags is specific */
608 : : static int
609 : 0 : ixgbe_parse_ntuple_filter(struct rte_eth_dev *dev,
610 : : const struct rte_flow_attr *attr,
611 : : const struct rte_flow_item pattern[],
612 : : const struct rte_flow_action actions[],
613 : : struct rte_eth_ntuple_filter *filter,
614 : : struct rte_flow_error *error)
615 : : {
616 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
617 : 0 : struct ci_flow_attr_check_param attr_param = {
618 : : .allow_priority = true,
619 : : };
620 : : struct ci_flow_actions parsed_actions;
621 : 0 : struct ci_flow_actions_check_param ap_param = {
622 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
623 : : /* only queue is allowed here */
624 : : RTE_FLOW_ACTION_TYPE_QUEUE,
625 : : RTE_FLOW_ACTION_TYPE_END
626 : : },
627 : : .driver_ctx = dev->data,
628 : : .check = ixgbe_flow_actions_check,
629 : : .max_actions = 1,
630 : : };
631 : : const struct rte_flow_action *action;
632 : : int ret;
633 : :
634 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_82599EB &&
635 : : hw->mac.type != ixgbe_mac_X540)
636 : : return -ENOTSUP;
637 : :
638 : : /* validate attributes */
639 : 0 : ret = ci_flow_check_attr(attr, &attr_param, error);
640 [ # # ]: 0 : if (ret)
641 : : return ret;
642 : :
643 : : /* parse requested actions */
644 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
645 [ # # ]: 0 : if (ret)
646 : : return ret;
647 : 0 : action = parsed_actions.actions[0];
648 : :
649 : 0 : ret = cons_parse_ntuple_filter(attr, pattern, action->conf, filter, error);
650 [ # # ]: 0 : if (ret)
651 : : return ret;
652 : :
653 : : /* Ixgbe doesn't support tcp flags. */
654 [ # # ]: 0 : if (filter->flags & RTE_NTUPLE_FLAGS_TCP_FLAG) {
655 : : memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
656 : 0 : rte_flow_error_set(error, EINVAL,
657 : : RTE_FLOW_ERROR_TYPE_ITEM,
658 : : NULL, "Not supported by ntuple filter");
659 : 0 : return -rte_errno;
660 : : }
661 : :
662 : : /* fixed value for ixgbe */
663 : 0 : filter->flags = RTE_5TUPLE_FLAGS;
664 : 0 : return 0;
665 : : }
666 : :
667 : : /**
668 : : * Parse the rule to see if it is a ethertype rule.
669 : : * And get the ethertype filter info BTW.
670 : : * pattern:
671 : : * The first not void item can be ETH.
672 : : * The next not void item must be END.
673 : : * action:
674 : : * The first not void action should be QUEUE.
675 : : * The next not void action should be END.
676 : : * pattern example:
677 : : * ITEM Spec Mask
678 : : * ETH type 0x0807 0xFFFF
679 : : * END
680 : : * other members in mask and spec should set to 0x00.
681 : : * item->last should be NULL.
682 : : */
683 : : static int
684 : 0 : cons_parse_ethertype_filter(const struct rte_flow_item *pattern,
685 : : const struct rte_flow_action *action,
686 : : struct rte_eth_ethertype_filter *filter,
687 : : struct rte_flow_error *error)
688 : : {
689 : : const struct rte_flow_item *item;
690 : : const struct rte_flow_item_eth *eth_spec;
691 : : const struct rte_flow_item_eth *eth_mask;
692 : :
693 : : item = next_no_void_pattern(pattern, NULL);
694 : : /* The first non-void item should be MAC. */
695 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
696 : 0 : rte_flow_error_set(error, EINVAL,
697 : : RTE_FLOW_ERROR_TYPE_ITEM,
698 : : item, "Not supported by ethertype filter");
699 : 0 : return -rte_errno;
700 : : }
701 : :
702 : : /*Not supported last point for range*/
703 [ # # ]: 0 : if (item->last) {
704 : 0 : rte_flow_error_set(error, EINVAL,
705 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
706 : : item, "Not supported last point for range");
707 : 0 : return -rte_errno;
708 : : }
709 : :
710 : : /* Get the MAC info. */
711 [ # # # # ]: 0 : if (!item->spec || !item->mask) {
712 : 0 : rte_flow_error_set(error, EINVAL,
713 : : RTE_FLOW_ERROR_TYPE_ITEM,
714 : : item, "Not supported by ethertype filter");
715 : 0 : return -rte_errno;
716 : : }
717 : :
718 : : eth_spec = item->spec;
719 : : eth_mask = item->mask;
720 : :
721 : : /* Mask bits of source MAC address must be full of 0.
722 : : * Mask bits of destination MAC address must be full
723 : : * of 1 or full of 0.
724 : : */
725 [ # # # # ]: 0 : if (!rte_is_zero_ether_addr(ð_mask->hdr.src_addr) ||
726 [ # # ]: 0 : (!rte_is_zero_ether_addr(ð_mask->hdr.dst_addr) &&
727 : : !rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr))) {
728 : 0 : rte_flow_error_set(error, EINVAL,
729 : : RTE_FLOW_ERROR_TYPE_ITEM,
730 : : item, "Invalid ether address mask");
731 : 0 : return -rte_errno;
732 : : }
733 : :
734 [ # # ]: 0 : if ((eth_mask->hdr.ether_type & UINT16_MAX) != UINT16_MAX) {
735 : 0 : rte_flow_error_set(error, EINVAL,
736 : : RTE_FLOW_ERROR_TYPE_ITEM,
737 : : item, "Invalid ethertype mask");
738 : 0 : return -rte_errno;
739 : : }
740 : :
741 : : /* If mask bits of destination MAC address
742 : : * are full of 1, set RTE_ETHTYPE_FLAGS_MAC.
743 : : */
744 [ # # ]: 0 : if (rte_is_broadcast_ether_addr(ð_mask->hdr.dst_addr)) {
745 : 0 : filter->mac_addr = eth_spec->hdr.dst_addr;
746 : 0 : filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
747 : : } else {
748 : 0 : filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
749 : : }
750 [ # # ]: 0 : filter->ether_type = rte_be_to_cpu_16(eth_spec->hdr.ether_type);
751 : :
752 : : /* Check if the next non-void item is END. */
753 : : item = next_no_void_pattern(pattern, item);
754 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
755 : 0 : rte_flow_error_set(error, EINVAL,
756 : : RTE_FLOW_ERROR_TYPE_ITEM,
757 : : item, "Not supported by ethertype filter.");
758 : 0 : return -rte_errno;
759 : : }
760 : :
761 : 0 : filter->queue = ((const struct rte_flow_action_queue *)action->conf)->index;
762 : :
763 : 0 : return 0;
764 : : }
765 : :
766 : : static int
767 : 0 : ixgbe_parse_ethertype_filter(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
768 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
769 : : struct rte_eth_ethertype_filter *filter, struct rte_flow_error *error)
770 : : {
771 : : int ret;
772 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
773 : : struct ci_flow_actions parsed_actions;
774 : 0 : struct ci_flow_actions_check_param ap_param = {
775 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
776 : : /* only queue is allowed here */
777 : : RTE_FLOW_ACTION_TYPE_QUEUE,
778 : : RTE_FLOW_ACTION_TYPE_END
779 : : },
780 : : .max_actions = 1,
781 : : .driver_ctx = dev->data,
782 : : .check = ixgbe_flow_actions_check
783 : : };
784 : : const struct rte_flow_action *action;
785 : :
786 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_82599EB &&
787 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X540 &&
788 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550 &&
789 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_x &&
790 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_a &&
791 : : hw->mac.type != ixgbe_mac_E610)
792 : : return -ENOTSUP;
793 : :
794 : : /* validate attributes */
795 : 0 : ret = ci_flow_check_attr(attr, NULL, error);
796 [ # # ]: 0 : if (ret)
797 : : return ret;
798 : :
799 : : /* parse requested actions */
800 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
801 [ # # ]: 0 : if (ret)
802 : : return ret;
803 : :
804 : 0 : action = parsed_actions.actions[0];
805 : :
806 : 0 : ret = cons_parse_ethertype_filter(pattern, action, filter, error);
807 [ # # ]: 0 : if (ret)
808 : : return ret;
809 : :
810 [ # # ]: 0 : if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
811 : : filter->ether_type == RTE_ETHER_TYPE_IPV6) {
812 : : memset(filter, 0, sizeof(struct rte_eth_ethertype_filter));
813 : 0 : rte_flow_error_set(error, EINVAL,
814 : : RTE_FLOW_ERROR_TYPE_ITEM,
815 : : NULL, "IPv4/IPv6 not supported by ethertype filter");
816 : 0 : return -rte_errno;
817 : : }
818 : :
819 [ # # ]: 0 : if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) {
820 : : memset(filter, 0, sizeof(struct rte_eth_ethertype_filter));
821 : 0 : rte_flow_error_set(error, EINVAL,
822 : : RTE_FLOW_ERROR_TYPE_ITEM,
823 : : NULL, "mac compare is unsupported");
824 : 0 : return -rte_errno;
825 : : }
826 : :
827 : : return 0;
828 : : }
829 : :
830 : : /**
831 : : * Parse the rule to see if it is a TCP SYN rule.
832 : : * And get the TCP SYN filter info BTW.
833 : : * pattern:
834 : : * The first not void item must be ETH.
835 : : * The second not void item must be IPV4 or IPV6.
836 : : * The third not void item must be TCP.
837 : : * The next not void item must be END.
838 : : * action:
839 : : * The first not void action should be QUEUE.
840 : : * The next not void action should be END.
841 : : * pattern example:
842 : : * ITEM Spec Mask
843 : : * ETH NULL NULL
844 : : * IPV4/IPV6 NULL NULL
845 : : * TCP tcp_flags 0x02 0xFF
846 : : * END
847 : : * other members in mask and spec should set to 0x00.
848 : : * item->last should be NULL.
849 : : */
850 : : static int
851 : 0 : cons_parse_syn_filter(const struct rte_flow_attr *attr, const struct rte_flow_item pattern[],
852 : : const struct rte_flow_action_queue *q_act, struct rte_eth_syn_filter *filter,
853 : : struct rte_flow_error *error)
854 : : {
855 : : const struct rte_flow_item *item;
856 : : const struct rte_flow_item_tcp *tcp_spec;
857 : : const struct rte_flow_item_tcp *tcp_mask;
858 : :
859 : :
860 : : /* the first not void item should be MAC or IPv4 or IPv6 or TCP */
861 : : item = next_no_void_pattern(pattern, NULL);
862 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
863 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
864 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
865 : : item->type != RTE_FLOW_ITEM_TYPE_TCP) {
866 : 0 : rte_flow_error_set(error, EINVAL,
867 : : RTE_FLOW_ERROR_TYPE_ITEM,
868 : : item, "Not supported by syn filter");
869 : 0 : return -rte_errno;
870 : : }
871 : : /*Not supported last point for range*/
872 [ # # ]: 0 : if (item->last) {
873 : 0 : rte_flow_error_set(error, EINVAL,
874 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
875 : : item, "Not supported last point for range");
876 : 0 : return -rte_errno;
877 : : }
878 : :
879 : : /* Skip Ethernet */
880 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
881 : : /* if the item is MAC, the content should be NULL */
882 [ # # # # ]: 0 : if (item->spec || item->mask) {
883 : 0 : rte_flow_error_set(error, EINVAL,
884 : : RTE_FLOW_ERROR_TYPE_ITEM,
885 : : item, "Invalid SYN address mask");
886 : 0 : return -rte_errno;
887 : : }
888 : :
889 : : /* check if the next not void item is IPv4 or IPv6 */
890 : : item = next_no_void_pattern(pattern, item);
891 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
892 : : item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
893 : 0 : rte_flow_error_set(error, EINVAL,
894 : : RTE_FLOW_ERROR_TYPE_ITEM,
895 : : item, "Not supported by syn filter");
896 : 0 : return -rte_errno;
897 : : }
898 : : }
899 : :
900 : : /* Skip IP */
901 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
902 : : item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
903 : : /* if the item is IP, the content should be NULL */
904 [ # # # # ]: 0 : if (item->spec || item->mask) {
905 : 0 : rte_flow_error_set(error, EINVAL,
906 : : RTE_FLOW_ERROR_TYPE_ITEM,
907 : : item, "Invalid SYN mask");
908 : 0 : return -rte_errno;
909 : : }
910 : :
911 : : /* check if the next not void item is TCP */
912 : : item = next_no_void_pattern(pattern, item);
913 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_TCP) {
914 : 0 : rte_flow_error_set(error, EINVAL,
915 : : RTE_FLOW_ERROR_TYPE_ITEM,
916 : : item, "Not supported by syn filter");
917 : 0 : return -rte_errno;
918 : : }
919 : : }
920 : :
921 : : /* Get the TCP info. Only support SYN. */
922 [ # # # # ]: 0 : if (!item->spec || !item->mask) {
923 : 0 : rte_flow_error_set(error, EINVAL,
924 : : RTE_FLOW_ERROR_TYPE_ITEM,
925 : : item, "Invalid SYN mask");
926 : 0 : return -rte_errno;
927 : : }
928 : : /*Not supported last point for range*/
929 [ # # ]: 0 : if (item->last) {
930 : 0 : rte_flow_error_set(error, EINVAL,
931 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
932 : : item, "Not supported last point for range");
933 : 0 : return -rte_errno;
934 : : }
935 : :
936 : : tcp_spec = item->spec;
937 : : tcp_mask = item->mask;
938 [ # # ]: 0 : if (!(tcp_spec->hdr.tcp_flags & RTE_TCP_SYN_FLAG) ||
939 [ # # ]: 0 : tcp_mask->hdr.src_port ||
940 [ # # ]: 0 : tcp_mask->hdr.dst_port ||
941 [ # # ]: 0 : tcp_mask->hdr.sent_seq ||
942 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
943 [ # # ]: 0 : tcp_mask->hdr.data_off ||
944 [ # # ]: 0 : tcp_mask->hdr.tcp_flags != RTE_TCP_SYN_FLAG ||
945 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
946 [ # # ]: 0 : tcp_mask->hdr.cksum ||
947 [ # # ]: 0 : tcp_mask->hdr.tcp_urp) {
948 : : memset(filter, 0, sizeof(struct rte_eth_syn_filter));
949 : 0 : rte_flow_error_set(error, EINVAL,
950 : : RTE_FLOW_ERROR_TYPE_ITEM,
951 : : item, "Not supported by syn filter");
952 : 0 : return -rte_errno;
953 : : }
954 : :
955 : : /* check if the next not void item is END */
956 : : item = next_no_void_pattern(pattern, item);
957 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
958 : : memset(filter, 0, sizeof(struct rte_eth_syn_filter));
959 : 0 : rte_flow_error_set(error, EINVAL,
960 : : RTE_FLOW_ERROR_TYPE_ITEM,
961 : : item, "Not supported by syn filter");
962 : 0 : return -rte_errno;
963 : : }
964 : :
965 : 0 : filter->queue = q_act->index;
966 : :
967 : : /* Support 2 priorities, the lowest or highest. */
968 [ # # ]: 0 : if (!attr->priority) {
969 : 0 : filter->hig_pri = 0;
970 [ # # ]: 0 : } else if (attr->priority == (uint32_t)~0U) {
971 : 0 : filter->hig_pri = 1;
972 : : } else {
973 : : memset(filter, 0, sizeof(struct rte_eth_syn_filter));
974 : 0 : rte_flow_error_set(error, EINVAL,
975 : : RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
976 : : attr, "Priority can be 0 or 0xFFFFFFFF");
977 : 0 : return -rte_errno;
978 : : }
979 : :
980 : : return 0;
981 : : }
982 : :
983 : : static int
984 : 0 : ixgbe_parse_syn_filter(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
985 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
986 : : struct rte_eth_syn_filter *filter, struct rte_flow_error *error)
987 : : {
988 : : int ret;
989 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
990 : : struct ci_flow_actions parsed_actions;
991 : 0 : struct ci_flow_actions_check_param ap_param = {
992 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
993 : : /* only queue is allowed here */
994 : : RTE_FLOW_ACTION_TYPE_QUEUE,
995 : : RTE_FLOW_ACTION_TYPE_END
996 : : },
997 : : .driver_ctx = dev->data,
998 : : .check = ixgbe_flow_actions_check,
999 : : .max_actions = 1,
1000 : : };
1001 : 0 : struct ci_flow_attr_check_param attr_param = {
1002 : : .allow_priority = true,
1003 : : };
1004 : : const struct rte_flow_action *action;
1005 : :
1006 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_82599EB &&
1007 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X540 &&
1008 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550 &&
1009 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_x &&
1010 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_a &&
1011 : : hw->mac.type != ixgbe_mac_E610)
1012 : : return -ENOTSUP;
1013 : :
1014 : : /* validate attributes */
1015 : 0 : ret = ci_flow_check_attr(attr, &attr_param, error);
1016 [ # # ]: 0 : if (ret)
1017 : : return ret;
1018 : :
1019 : : /* parse requested actions */
1020 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
1021 [ # # ]: 0 : if (ret)
1022 : : return ret;
1023 : :
1024 : 0 : action = parsed_actions.actions[0];
1025 : :
1026 : 0 : return cons_parse_syn_filter(attr, pattern, action->conf, filter, error);
1027 : : }
1028 : :
1029 : : /**
1030 : : * Parse the rule to see if it is a L2 tunnel rule.
1031 : : * And get the L2 tunnel filter info BTW.
1032 : : * Only support E-tag now.
1033 : : * pattern:
1034 : : * The first not void item can be E_TAG.
1035 : : * The next not void item must be END.
1036 : : * action:
1037 : : * The first not void action should be VF or PF.
1038 : : * The next not void action should be END.
1039 : : * pattern example:
1040 : : * ITEM Spec Mask
1041 : : * E_TAG grp 0x1 0x3
1042 : : e_cid_base 0x309 0xFFF
1043 : : * END
1044 : : * other members in mask and spec should set to 0x00.
1045 : : * item->last should be NULL.
1046 : : */
1047 : : static int
1048 : 0 : cons_parse_l2_tn_filter(struct rte_eth_dev *dev,
1049 : : const struct rte_flow_item pattern[],
1050 : : const struct rte_flow_action *action,
1051 : : struct ixgbe_l2_tunnel_conf *filter,
1052 : : struct rte_flow_error *error)
1053 : : {
1054 : : const struct rte_flow_item *item;
1055 : : const struct rte_flow_item_e_tag *e_tag_spec;
1056 : : const struct rte_flow_item_e_tag *e_tag_mask;
1057 : 0 : struct ixgbe_adapter *ad = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
1058 : :
1059 : : /* The first not void item should be e-tag. */
1060 : : item = next_no_void_pattern(pattern, NULL);
1061 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_E_TAG) {
1062 : : memset(filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
1063 : 0 : rte_flow_error_set(error, EINVAL,
1064 : : RTE_FLOW_ERROR_TYPE_ITEM,
1065 : : item, "Not supported by L2 tunnel filter");
1066 : 0 : return -rte_errno;
1067 : : }
1068 : :
1069 [ # # # # ]: 0 : if (!item->spec || !item->mask) {
1070 : : memset(filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
1071 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1072 : : item, "Not supported by L2 tunnel filter");
1073 : 0 : return -rte_errno;
1074 : : }
1075 : :
1076 : : /*Not supported last point for range*/
1077 [ # # ]: 0 : if (item->last) {
1078 : 0 : rte_flow_error_set(error, EINVAL,
1079 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1080 : : item, "Not supported last point for range");
1081 : 0 : return -rte_errno;
1082 : : }
1083 : :
1084 : : e_tag_spec = item->spec;
1085 : : e_tag_mask = item->mask;
1086 : :
1087 : : /* Only care about GRP and E cid base. */
1088 [ # # ]: 0 : if (e_tag_mask->epcp_edei_in_ecid_b ||
1089 [ # # ]: 0 : e_tag_mask->in_ecid_e ||
1090 : 0 : e_tag_mask->ecid_e ||
1091 [ # # ]: 0 : e_tag_mask->rsvd_grp_ecid_b != rte_cpu_to_be_16(0x3FFF)) {
1092 : : memset(filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
1093 : 0 : rte_flow_error_set(error, EINVAL,
1094 : : RTE_FLOW_ERROR_TYPE_ITEM,
1095 : : item, "Not supported by L2 tunnel filter");
1096 : 0 : return -rte_errno;
1097 : : }
1098 : :
1099 : 0 : filter->l2_tunnel_type = RTE_ETH_L2_TUNNEL_TYPE_E_TAG;
1100 : : /**
1101 : : * grp and e_cid_base are bit fields and only use 14 bits.
1102 : : * e-tag id is taken as little endian by HW.
1103 : : */
1104 [ # # ]: 0 : filter->tunnel_id = rte_be_to_cpu_16(e_tag_spec->rsvd_grp_ecid_b);
1105 : :
1106 : : /* check if the next not void item is END */
1107 : : item = next_no_void_pattern(pattern, item);
1108 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
1109 : : memset(filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
1110 : 0 : rte_flow_error_set(error, EINVAL,
1111 : : RTE_FLOW_ERROR_TYPE_ITEM,
1112 : : item, "Not supported by L2 tunnel filter");
1113 : 0 : return -rte_errno;
1114 : : }
1115 : :
1116 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_VF) {
1117 : 0 : const struct rte_flow_action_vf *act_vf = action->conf;
1118 : 0 : filter->pool = act_vf->id;
1119 : : } else {
1120 : 0 : filter->pool = ad->max_vfs;
1121 : : }
1122 : :
1123 : : return 0;
1124 : : }
1125 : :
1126 : : static int
1127 : 0 : ixgbe_parse_l2_tn_filter(struct rte_eth_dev *dev,
1128 : : const struct rte_flow_attr *attr,
1129 : : const struct rte_flow_item pattern[],
1130 : : const struct rte_flow_action actions[],
1131 : : struct ixgbe_l2_tunnel_conf *l2_tn_filter,
1132 : : struct rte_flow_error *error)
1133 : : {
1134 : 0 : struct rte_eth_dev_data *dev_data = dev->data;
1135 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev_data->dev_private);
1136 : : struct ci_flow_actions parsed_actions;
1137 : 0 : struct ci_flow_actions_check_param ap_param = {
1138 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
1139 : : /* only vf/pf is allowed here */
1140 : : RTE_FLOW_ACTION_TYPE_VF,
1141 : : RTE_FLOW_ACTION_TYPE_PF,
1142 : : RTE_FLOW_ACTION_TYPE_END
1143 : : },
1144 : : .driver_ctx = dev_data,
1145 : : .check = ixgbe_flow_actions_check,
1146 : : .max_actions = 1,
1147 : : };
1148 : : int ret = 0;
1149 : : const struct rte_flow_action *action;
1150 : :
1151 : 0 : if (hw->mac.type != ixgbe_mac_X550 &&
1152 : : hw->mac.type != ixgbe_mac_X550EM_x &&
1153 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_a &&
1154 : : hw->mac.type != ixgbe_mac_E610) {
1155 : 0 : rte_flow_error_set(error, EINVAL,
1156 : : RTE_FLOW_ERROR_TYPE_ITEM,
1157 : : NULL, "Not supported by L2 tunnel filter");
1158 : 0 : return -rte_errno;
1159 : : }
1160 : :
1161 : : /* validate attributes */
1162 : 0 : ret = ci_flow_check_attr(attr, NULL, error);
1163 [ # # ]: 0 : if (ret)
1164 : : return ret;
1165 : :
1166 : : /* parse requested actions */
1167 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
1168 [ # # ]: 0 : if (ret)
1169 : : return ret;
1170 : :
1171 : : /* only one action is supported */
1172 [ # # ]: 0 : if (parsed_actions.count > 1) {
1173 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
1174 : 0 : parsed_actions.actions[1],
1175 : : "Only one action can be specified at a time");
1176 : : }
1177 : 0 : action = parsed_actions.actions[0];
1178 : :
1179 : 0 : ret = cons_parse_l2_tn_filter(dev, pattern, action, l2_tn_filter, error);
1180 : :
1181 : 0 : return ret;
1182 : : }
1183 : :
1184 : : /* search next no void pattern and skip fuzzy */
1185 : : static inline
1186 : : const struct rte_flow_item *next_no_fuzzy_pattern(
1187 : : const struct rte_flow_item pattern[],
1188 : : const struct rte_flow_item *cur)
1189 : : {
1190 : : const struct rte_flow_item *next =
1191 : : next_no_void_pattern(pattern, cur);
1192 : : while (1) {
1193 [ # # # # : 0 : if (next->type != RTE_FLOW_ITEM_TYPE_FUZZY)
# # # # #
# # # # #
# # # # ]
1194 : : return next;
1195 : : next = next_no_void_pattern(pattern, next);
1196 : : }
1197 : : }
1198 : :
1199 : 0 : static inline uint8_t signature_match(const struct rte_flow_item pattern[])
1200 : : {
1201 : : const struct rte_flow_item_fuzzy *spec, *last, *mask;
1202 : : const struct rte_flow_item *item;
1203 : : uint32_t sh, lh, mh;
1204 : : int i = 0;
1205 : :
1206 : : while (1) {
1207 : 0 : item = pattern + i;
1208 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_END)
1209 : : break;
1210 : :
1211 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_FUZZY) {
1212 : 0 : spec = item->spec;
1213 : 0 : last = item->last;
1214 : 0 : mask = item->mask;
1215 : :
1216 [ # # ]: 0 : if (!spec || !mask)
1217 : : return 0;
1218 : :
1219 : 0 : sh = spec->thresh;
1220 : :
1221 [ # # ]: 0 : if (!last)
1222 : : lh = sh;
1223 : : else
1224 : 0 : lh = last->thresh;
1225 : :
1226 : 0 : mh = mask->thresh;
1227 : 0 : sh = sh & mh;
1228 : 0 : lh = lh & mh;
1229 : :
1230 [ # # ]: 0 : if (!sh || sh > lh)
1231 : : return 0;
1232 : :
1233 : 0 : return 1;
1234 : : }
1235 : :
1236 : 0 : i++;
1237 : : }
1238 : :
1239 : : return 0;
1240 : : }
1241 : :
1242 : : /**
1243 : : * Parse the rule to see if it is a IP or MAC VLAN flow director rule.
1244 : : * And get the flow director filter info BTW.
1245 : : * UDP/TCP/SCTP PATTERN:
1246 : : * The first not void item can be ETH or IPV4 or IPV6
1247 : : * The second not void item must be IPV4 or IPV6 if the first one is ETH.
1248 : : * The next not void item could be UDP or TCP or SCTP (optional)
1249 : : * The next not void item could be RAW (for flexbyte, optional)
1250 : : * The next not void item must be END.
1251 : : * A Fuzzy Match pattern can appear at any place before END.
1252 : : * Fuzzy Match is optional for IPV4 but is required for IPV6
1253 : : * MAC VLAN PATTERN:
1254 : : * The first not void item must be ETH.
1255 : : * The second not void item must be MAC VLAN.
1256 : : * The next not void item must be END.
1257 : : * ACTION:
1258 : : * The first not void action should be QUEUE or DROP.
1259 : : * The second not void optional action should be MARK,
1260 : : * mark_id is a uint32_t number.
1261 : : * The next not void action should be END.
1262 : : * UDP/TCP/SCTP pattern example:
1263 : : * ITEM Spec Mask
1264 : : * ETH NULL NULL
1265 : : * IPV4 src_addr 192.168.1.20 0xFFFFFFFF
1266 : : * dst_addr 192.167.3.50 0xFFFFFFFF
1267 : : * UDP/TCP/SCTP src_port 80 0xFFFF
1268 : : * dst_port 80 0xFFFF
1269 : : * FLEX relative 0 0x1
1270 : : * search 0 0x1
1271 : : * reserved 0 0
1272 : : * offset 12 0xFFFFFFFF
1273 : : * limit 0 0xFFFF
1274 : : * length 2 0xFFFF
1275 : : * pattern[0] 0x86 0xFF
1276 : : * pattern[1] 0xDD 0xFF
1277 : : * END
1278 : : * MAC VLAN pattern example:
1279 : : * ITEM Spec Mask
1280 : : * ETH dst_addr
1281 : : {0xAC, 0x7B, 0xA1, {0xFF, 0xFF, 0xFF,
1282 : : 0x2C, 0x6D, 0x36} 0xFF, 0xFF, 0xFF}
1283 : : * MAC VLAN tci 0x2016 0xEFFF
1284 : : * END
1285 : : * Other members in mask and spec should set to 0x00.
1286 : : * Item->last should be NULL.
1287 : : */
1288 : : static int
1289 : 0 : ixgbe_parse_fdir_filter_normal(struct rte_eth_dev *dev,
1290 : : const struct rte_flow_item pattern[],
1291 : : const struct ci_flow_actions *parsed_actions,
1292 : : struct ixgbe_fdir_rule *rule,
1293 : : struct rte_flow_error *error)
1294 : : {
1295 : : const struct rte_flow_item *item;
1296 : : const struct rte_flow_item_eth *eth_spec;
1297 : : const struct rte_flow_item_eth *eth_mask;
1298 : : const struct rte_flow_item_ipv4 *ipv4_spec;
1299 : : const struct rte_flow_item_ipv4 *ipv4_mask;
1300 : : const struct rte_flow_item_ipv6 *ipv6_spec;
1301 : : const struct rte_flow_item_ipv6 *ipv6_mask;
1302 : : const struct rte_flow_item_tcp *tcp_spec;
1303 : : const struct rte_flow_item_tcp *tcp_mask;
1304 : : const struct rte_flow_item_udp *udp_spec;
1305 : : const struct rte_flow_item_udp *udp_mask;
1306 : : const struct rte_flow_item_sctp *sctp_spec;
1307 : : const struct rte_flow_item_sctp *sctp_mask;
1308 : : const struct rte_flow_item_vlan *vlan_spec;
1309 : : const struct rte_flow_item_vlan *vlan_mask;
1310 : : const struct rte_flow_item_raw *raw_mask;
1311 : : const struct rte_flow_item_raw *raw_spec;
1312 : : const struct rte_flow_action *fwd_action, *aux_action;
1313 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1314 : : uint8_t j;
1315 : :
1316 : 0 : fwd_action = parsed_actions->actions[0];
1317 : : /* can be NULL */
1318 [ # # ]: 0 : aux_action = parsed_actions->actions[1];
1319 : :
1320 : : /**
1321 : : * Some fields may not be provided. Set spec to 0 and mask to default
1322 : : * value. So, we need not do anything for the not provided fields later.
1323 : : */
1324 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1325 : 0 : memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask));
1326 : 0 : rule->mask.vlan_tci_mask = 0;
1327 : 0 : rule->mask.flex_bytes_mask = 0;
1328 : 0 : rule->mask.l4_proto_match = 0;
1329 : 0 : rule->mask.dst_port_mask = 0;
1330 : 0 : rule->mask.src_port_mask = 0;
1331 : :
1332 : : /* check if this is a signature match */
1333 [ # # ]: 0 : if (signature_match(pattern))
1334 : 0 : rule->mode = RTE_FDIR_MODE_SIGNATURE;
1335 : : else
1336 : 0 : rule->mode = RTE_FDIR_MODE_PERFECT;
1337 : :
1338 : : /* set up action */
1339 [ # # ]: 0 : if (fwd_action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1340 : 0 : const struct rte_flow_action_queue *q_act = fwd_action->conf;
1341 : 0 : rule->queue = q_act->index;
1342 : : } else {
1343 : : /* signature mode does not support drop action. */
1344 [ # # ]: 0 : if (rule->mode == RTE_FDIR_MODE_SIGNATURE) {
1345 : 0 : rte_flow_error_set(error, EINVAL,
1346 : : RTE_FLOW_ERROR_TYPE_ACTION, fwd_action,
1347 : : "Signature mode does not support drop action.");
1348 : 0 : return -rte_errno;
1349 : : }
1350 : 0 : rule->fdirflags = IXGBE_FDIRCMD_DROP;
1351 : : }
1352 : :
1353 : : /* set up mark action */
1354 [ # # # # ]: 0 : if (aux_action != NULL && aux_action->type == RTE_FLOW_ACTION_TYPE_MARK) {
1355 : 0 : const struct rte_flow_action_mark *m_act = aux_action->conf;
1356 : 0 : rule->soft_id = m_act->id;
1357 : : }
1358 : :
1359 : : /**
1360 : : * The first not void item should be
1361 : : * MAC or IPv4 or TCP or UDP or SCTP.
1362 : : */
1363 : : item = next_no_fuzzy_pattern(pattern, NULL);
1364 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
1365 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
1366 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
1367 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_TCP &&
1368 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_UDP &&
1369 : : item->type != RTE_FLOW_ITEM_TYPE_SCTP) {
1370 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1371 : 0 : rte_flow_error_set(error, EINVAL,
1372 : : RTE_FLOW_ERROR_TYPE_ITEM,
1373 : : item, "Not supported by fdir filter");
1374 : 0 : return -rte_errno;
1375 : : }
1376 : :
1377 : : /*Not supported last point for range*/
1378 [ # # ]: 0 : if (item->last) {
1379 : 0 : rte_flow_error_set(error, EINVAL,
1380 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1381 : : item, "Not supported last point for range");
1382 : 0 : return -rte_errno;
1383 : : }
1384 : :
1385 : : /* Get the MAC info. */
1386 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
1387 : : /**
1388 : : * Only support vlan and dst MAC address,
1389 : : * others should be masked.
1390 : : */
1391 [ # # # # ]: 0 : if (item->spec && !item->mask) {
1392 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1393 : 0 : rte_flow_error_set(error, EINVAL,
1394 : : RTE_FLOW_ERROR_TYPE_ITEM,
1395 : : item, "Not supported by fdir filter");
1396 : 0 : return -rte_errno;
1397 : : }
1398 : :
1399 [ # # ]: 0 : if (item->spec) {
1400 : 0 : rule->b_spec = TRUE;
1401 : : eth_spec = item->spec;
1402 : :
1403 : : /* Get the dst MAC. */
1404 [ # # ]: 0 : for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
1405 : 0 : rule->ixgbe_fdir.formatted.inner_mac[j] =
1406 : 0 : eth_spec->hdr.dst_addr.addr_bytes[j];
1407 : : }
1408 : : }
1409 : :
1410 : :
1411 [ # # ]: 0 : if (item->mask) {
1412 : :
1413 : 0 : rule->b_mask = TRUE;
1414 : : eth_mask = item->mask;
1415 : :
1416 : : /* Ether type should be masked. */
1417 [ # # ]: 0 : if (eth_mask->hdr.ether_type ||
1418 [ # # ]: 0 : rule->mode == RTE_FDIR_MODE_SIGNATURE) {
1419 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1420 : 0 : rte_flow_error_set(error, EINVAL,
1421 : : RTE_FLOW_ERROR_TYPE_ITEM,
1422 : : item, "Not supported by fdir filter");
1423 : 0 : return -rte_errno;
1424 : : }
1425 : :
1426 : : /* If ethernet has meaning, it means MAC VLAN mode. */
1427 : 0 : rule->mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN;
1428 : :
1429 : : /**
1430 : : * src MAC address must be masked,
1431 : : * and don't support dst MAC address mask.
1432 : : */
1433 [ # # ]: 0 : for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
1434 [ # # ]: 0 : if (eth_mask->hdr.src_addr.addr_bytes[j] ||
1435 [ # # ]: 0 : eth_mask->hdr.dst_addr.addr_bytes[j] != 0xFF) {
1436 : : memset(rule, 0,
1437 : : sizeof(struct ixgbe_fdir_rule));
1438 : 0 : rte_flow_error_set(error, EINVAL,
1439 : : RTE_FLOW_ERROR_TYPE_ITEM,
1440 : : item, "Not supported by fdir filter");
1441 : 0 : return -rte_errno;
1442 : : }
1443 : : }
1444 : :
1445 : : /* When no VLAN, considered as full mask. */
1446 : 0 : rule->mask.vlan_tci_mask = rte_cpu_to_be_16(0xEFFF);
1447 : : }
1448 : : /*** If both spec and mask are item,
1449 : : * it means don't care about ETH.
1450 : : * Do nothing.
1451 : : */
1452 : :
1453 : : /**
1454 : : * Check if the next not void item is vlan or ipv4.
1455 : : * IPv6 is not supported.
1456 : : */
1457 : : item = next_no_fuzzy_pattern(pattern, item);
1458 [ # # ]: 0 : if (rule->mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
1459 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_VLAN) {
1460 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1461 : 0 : rte_flow_error_set(error, EINVAL,
1462 : : RTE_FLOW_ERROR_TYPE_ITEM,
1463 : : item, "Not supported by fdir filter");
1464 : 0 : return -rte_errno;
1465 : : }
1466 : : } else {
1467 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
1468 : : item->type != RTE_FLOW_ITEM_TYPE_VLAN) {
1469 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1470 : 0 : rte_flow_error_set(error, EINVAL,
1471 : : RTE_FLOW_ERROR_TYPE_ITEM,
1472 : : item, "Not supported by fdir filter");
1473 : 0 : return -rte_errno;
1474 : : }
1475 : : }
1476 : : }
1477 : :
1478 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
1479 [ # # # # ]: 0 : if (!(item->spec && item->mask)) {
1480 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1481 : 0 : rte_flow_error_set(error, EINVAL,
1482 : : RTE_FLOW_ERROR_TYPE_ITEM,
1483 : : item, "Not supported by fdir filter");
1484 : 0 : return -rte_errno;
1485 : : }
1486 : :
1487 : : /*Not supported last point for range*/
1488 [ # # ]: 0 : if (item->last) {
1489 : 0 : rte_flow_error_set(error, EINVAL,
1490 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1491 : : item, "Not supported last point for range");
1492 : 0 : return -rte_errno;
1493 : : }
1494 : :
1495 : : vlan_spec = item->spec;
1496 : : vlan_mask = item->mask;
1497 : :
1498 : 0 : rule->ixgbe_fdir.formatted.vlan_id = vlan_spec->hdr.vlan_tci;
1499 : :
1500 : 0 : rule->mask.vlan_tci_mask = vlan_mask->hdr.vlan_tci;
1501 : 0 : rule->mask.vlan_tci_mask &= rte_cpu_to_be_16(0xEFFF);
1502 : : /* More than one tags are not supported. */
1503 : :
1504 : : /* Next not void item must be END */
1505 : : item = next_no_fuzzy_pattern(pattern, item);
1506 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
1507 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1508 : 0 : rte_flow_error_set(error, EINVAL,
1509 : : RTE_FLOW_ERROR_TYPE_ITEM,
1510 : : item, "Not supported by fdir filter");
1511 : 0 : return -rte_errno;
1512 : : }
1513 : : }
1514 : :
1515 : : /* Get the IPV4 info. */
1516 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_IPV4) {
1517 : : /**
1518 : : * Set the flow type even if there's no content
1519 : : * as we must have a flow type.
1520 : : */
1521 : : rule->ixgbe_fdir.formatted.flow_type =
1522 : : IXGBE_ATR_FLOW_TYPE_IPV4;
1523 : : /*Not supported last point for range*/
1524 [ # # ]: 0 : if (item->last) {
1525 : 0 : rte_flow_error_set(error, EINVAL,
1526 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1527 : : item, "Not supported last point for range");
1528 : 0 : return -rte_errno;
1529 : : }
1530 : : /**
1531 : : * Only care about src & dst addresses,
1532 : : * others should be masked.
1533 : : */
1534 [ # # ]: 0 : if (!item->mask) {
1535 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1536 : 0 : rte_flow_error_set(error, EINVAL,
1537 : : RTE_FLOW_ERROR_TYPE_ITEM,
1538 : : item, "Not supported by fdir filter");
1539 : 0 : return -rte_errno;
1540 : : }
1541 : 0 : rule->b_mask = TRUE;
1542 : : ipv4_mask = item->mask;
1543 [ # # ]: 0 : if (ipv4_mask->hdr.version_ihl ||
1544 : 0 : ipv4_mask->hdr.type_of_service ||
1545 [ # # ]: 0 : ipv4_mask->hdr.total_length ||
1546 [ # # ]: 0 : ipv4_mask->hdr.packet_id ||
1547 [ # # ]: 0 : ipv4_mask->hdr.fragment_offset ||
1548 [ # # ]: 0 : ipv4_mask->hdr.time_to_live ||
1549 : 0 : ipv4_mask->hdr.next_proto_id ||
1550 [ # # ]: 0 : ipv4_mask->hdr.hdr_checksum) {
1551 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1552 : 0 : rte_flow_error_set(error, EINVAL,
1553 : : RTE_FLOW_ERROR_TYPE_ITEM,
1554 : : item, "Not supported by fdir filter");
1555 : 0 : return -rte_errno;
1556 : : }
1557 : 0 : rule->mask.dst_ipv4_mask = ipv4_mask->hdr.dst_addr;
1558 : 0 : rule->mask.src_ipv4_mask = ipv4_mask->hdr.src_addr;
1559 : :
1560 [ # # ]: 0 : if (item->spec) {
1561 : 0 : rule->b_spec = TRUE;
1562 : : ipv4_spec = item->spec;
1563 : 0 : rule->ixgbe_fdir.formatted.dst_ip[0] =
1564 : 0 : ipv4_spec->hdr.dst_addr;
1565 : 0 : rule->ixgbe_fdir.formatted.src_ip[0] =
1566 : 0 : ipv4_spec->hdr.src_addr;
1567 : : }
1568 : :
1569 : : /**
1570 : : * Check if the next not void item is
1571 : : * TCP or UDP or SCTP or END.
1572 : : */
1573 : : item = next_no_fuzzy_pattern(pattern, item);
1574 : 0 : if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
1575 : : item->type != RTE_FLOW_ITEM_TYPE_UDP &&
1576 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_SCTP &&
1577 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_END &&
1578 : : item->type != RTE_FLOW_ITEM_TYPE_RAW) {
1579 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1580 : 0 : rte_flow_error_set(error, EINVAL,
1581 : : RTE_FLOW_ERROR_TYPE_ITEM,
1582 : : item, "Not supported by fdir filter");
1583 : 0 : return -rte_errno;
1584 : : }
1585 : : }
1586 : :
1587 : : /* Get the IPV6 info. */
1588 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
1589 : : /**
1590 : : * Set the flow type even if there's no content
1591 : : * as we must have a flow type.
1592 : : */
1593 : 0 : rule->ixgbe_fdir.formatted.flow_type =
1594 : : IXGBE_ATR_FLOW_TYPE_IPV6;
1595 : :
1596 : : /**
1597 : : * 1. must signature match
1598 : : * 2. not support last
1599 : : * 3. mask must not null
1600 : : */
1601 [ # # ]: 0 : if (rule->mode != RTE_FDIR_MODE_SIGNATURE ||
1602 [ # # ]: 0 : item->last ||
1603 [ # # ]: 0 : !item->mask) {
1604 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1605 : 0 : rte_flow_error_set(error, EINVAL,
1606 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1607 : : item, "Not supported last point for range");
1608 : 0 : return -rte_errno;
1609 : : }
1610 : :
1611 : 0 : rule->b_mask = TRUE;
1612 : : ipv6_mask = item->mask;
1613 [ # # ]: 0 : if (ipv6_mask->hdr.vtc_flow ||
1614 : : ipv6_mask->hdr.payload_len ||
1615 [ # # ]: 0 : ipv6_mask->hdr.proto ||
1616 : : ipv6_mask->hdr.hop_limits) {
1617 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1618 : 0 : rte_flow_error_set(error, EINVAL,
1619 : : RTE_FLOW_ERROR_TYPE_ITEM,
1620 : : item, "Not supported by fdir filter");
1621 : 0 : return -rte_errno;
1622 : : }
1623 : :
1624 : : /* check src addr mask */
1625 [ # # ]: 0 : for (j = 0; j < 16; j++) {
1626 [ # # ]: 0 : if (ipv6_mask->hdr.src_addr.a[j] == 0) {
1627 : 0 : rule->mask.src_ipv6_mask &= ~(1 << j);
1628 [ # # ]: 0 : } else if (ipv6_mask->hdr.src_addr.a[j] != UINT8_MAX) {
1629 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1630 : 0 : rte_flow_error_set(error, EINVAL,
1631 : : RTE_FLOW_ERROR_TYPE_ITEM,
1632 : : item, "Not supported by fdir filter");
1633 : 0 : return -rte_errno;
1634 : : }
1635 : : }
1636 : :
1637 : : /* check dst addr mask */
1638 [ # # ]: 0 : for (j = 0; j < 16; j++) {
1639 [ # # ]: 0 : if (ipv6_mask->hdr.dst_addr.a[j] == 0) {
1640 : 0 : rule->mask.dst_ipv6_mask &= ~(1 << j);
1641 [ # # ]: 0 : } else if (ipv6_mask->hdr.dst_addr.a[j] != UINT8_MAX) {
1642 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1643 : 0 : rte_flow_error_set(error, EINVAL,
1644 : : RTE_FLOW_ERROR_TYPE_ITEM,
1645 : : item, "Not supported by fdir filter");
1646 : 0 : return -rte_errno;
1647 : : }
1648 : : }
1649 : :
1650 [ # # ]: 0 : if (item->spec) {
1651 : 0 : rule->b_spec = TRUE;
1652 : : ipv6_spec = item->spec;
1653 : 0 : memcpy(rule->ixgbe_fdir.formatted.src_ip,
1654 : 0 : &ipv6_spec->hdr.src_addr, 16);
1655 : 0 : memcpy(rule->ixgbe_fdir.formatted.dst_ip,
1656 : 0 : &ipv6_spec->hdr.dst_addr, 16);
1657 : : }
1658 : :
1659 : : /**
1660 : : * Check if the next not void item is
1661 : : * TCP or UDP or SCTP or END.
1662 : : */
1663 : : item = next_no_fuzzy_pattern(pattern, item);
1664 : 0 : if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
1665 : : item->type != RTE_FLOW_ITEM_TYPE_UDP &&
1666 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_SCTP &&
1667 [ # # ]: 0 : item->type != RTE_FLOW_ITEM_TYPE_END &&
1668 : : item->type != RTE_FLOW_ITEM_TYPE_RAW) {
1669 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1670 : 0 : rte_flow_error_set(error, EINVAL,
1671 : : RTE_FLOW_ERROR_TYPE_ITEM,
1672 : : item, "Not supported by fdir filter");
1673 : 0 : return -rte_errno;
1674 : : }
1675 : : }
1676 : :
1677 : : /* Get the TCP info. */
1678 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_TCP) {
1679 : : /**
1680 : : * Set the flow type even if there's no content
1681 : : * as we must have a flow type.
1682 : : */
1683 : 0 : rule->ixgbe_fdir.formatted.flow_type |=
1684 : : IXGBE_ATR_L4TYPE_TCP;
1685 : : /*Not supported last point for range*/
1686 [ # # ]: 0 : if (item->last) {
1687 : 0 : rte_flow_error_set(error, EINVAL,
1688 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1689 : : item, "Not supported last point for range");
1690 : 0 : return -rte_errno;
1691 : : }
1692 : 0 : tcp_mask = item->mask;
1693 [ # # ]: 0 : if (tcp_mask != NULL) {
1694 : : /**
1695 : : * Only care about src & dst ports,
1696 : : * others should be masked.
1697 : : */
1698 : 0 : rule->b_mask = TRUE;
1699 [ # # ]: 0 : if (tcp_mask->hdr.sent_seq ||
1700 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
1701 [ # # ]: 0 : tcp_mask->hdr.data_off ||
1702 [ # # ]: 0 : tcp_mask->hdr.tcp_flags ||
1703 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
1704 [ # # ]: 0 : tcp_mask->hdr.cksum ||
1705 [ # # ]: 0 : tcp_mask->hdr.tcp_urp) {
1706 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1707 : 0 : rte_flow_error_set(error, EINVAL,
1708 : : RTE_FLOW_ERROR_TYPE_ITEM,
1709 : : item, "Not supported by fdir filter");
1710 : 0 : return -rte_errno;
1711 : : }
1712 : 0 : rule->mask.src_port_mask = tcp_mask->hdr.src_port;
1713 : 0 : rule->mask.dst_port_mask = tcp_mask->hdr.dst_port;
1714 : :
1715 [ # # ]: 0 : if (item->spec) {
1716 : 0 : rule->b_spec = TRUE;
1717 : : tcp_spec = item->spec;
1718 : 0 : rule->ixgbe_fdir.formatted.src_port =
1719 : 0 : tcp_spec->hdr.src_port;
1720 : 0 : rule->ixgbe_fdir.formatted.dst_port =
1721 : 0 : tcp_spec->hdr.dst_port;
1722 : : }
1723 [ # # ]: 0 : } else if (item->spec != NULL) {
1724 : : /* No port mask means protocol-only match; spec is invalid. */
1725 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1726 : 0 : rte_flow_error_set(error, EINVAL,
1727 : : RTE_FLOW_ERROR_TYPE_ITEM,
1728 : : item, "Not supported by fdir filter");
1729 : 0 : return -rte_errno;
1730 : : }
1731 : :
1732 : : item = next_no_fuzzy_pattern(pattern, item);
1733 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
1734 : : item->type != RTE_FLOW_ITEM_TYPE_END) {
1735 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1736 : 0 : rte_flow_error_set(error, EINVAL,
1737 : : RTE_FLOW_ERROR_TYPE_ITEM,
1738 : : item, "Not supported by fdir filter");
1739 : 0 : return -rte_errno;
1740 : : }
1741 : :
1742 : : }
1743 : :
1744 : : /* Get the UDP info */
1745 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_UDP) {
1746 : : /**
1747 : : * Set the flow type even if there's no content
1748 : : * as we must have a flow type.
1749 : : */
1750 : 0 : rule->ixgbe_fdir.formatted.flow_type |=
1751 : : IXGBE_ATR_L4TYPE_UDP;
1752 : : /*Not supported last point for range*/
1753 [ # # ]: 0 : if (item->last) {
1754 : 0 : rte_flow_error_set(error, EINVAL,
1755 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1756 : : item, "Not supported last point for range");
1757 : 0 : return -rte_errno;
1758 : : }
1759 : 0 : udp_mask = item->mask;
1760 [ # # ]: 0 : if (udp_mask != NULL) {
1761 : : /**
1762 : : * Only care about src & dst ports,
1763 : : * others should be masked.
1764 : : */
1765 : 0 : rule->b_mask = TRUE;
1766 [ # # ]: 0 : if (udp_mask->hdr.dgram_len ||
1767 [ # # ]: 0 : udp_mask->hdr.dgram_cksum) {
1768 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1769 : 0 : rte_flow_error_set(error, EINVAL,
1770 : : RTE_FLOW_ERROR_TYPE_ITEM,
1771 : : item, "Not supported by fdir filter");
1772 : 0 : return -rte_errno;
1773 : : }
1774 : 0 : rule->mask.src_port_mask = udp_mask->hdr.src_port;
1775 : 0 : rule->mask.dst_port_mask = udp_mask->hdr.dst_port;
1776 : :
1777 [ # # ]: 0 : if (item->spec) {
1778 : 0 : rule->b_spec = TRUE;
1779 : : udp_spec = item->spec;
1780 : 0 : rule->ixgbe_fdir.formatted.src_port =
1781 : 0 : udp_spec->hdr.src_port;
1782 : 0 : rule->ixgbe_fdir.formatted.dst_port =
1783 : 0 : udp_spec->hdr.dst_port;
1784 : : }
1785 [ # # ]: 0 : } else if (item->spec != NULL) {
1786 : : /* No port mask means protocol-only match; spec is invalid. */
1787 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1788 : 0 : rte_flow_error_set(error, EINVAL,
1789 : : RTE_FLOW_ERROR_TYPE_ITEM,
1790 : : item, "Not supported by fdir filter");
1791 : 0 : return -rte_errno;
1792 : : }
1793 : :
1794 : : item = next_no_fuzzy_pattern(pattern, item);
1795 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
1796 : : item->type != RTE_FLOW_ITEM_TYPE_END) {
1797 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1798 : 0 : rte_flow_error_set(error, EINVAL,
1799 : : RTE_FLOW_ERROR_TYPE_ITEM,
1800 : : item, "Not supported by fdir filter");
1801 : 0 : return -rte_errno;
1802 : : }
1803 : :
1804 : : }
1805 : :
1806 : : /* Get the SCTP info */
1807 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_SCTP) {
1808 : : /**
1809 : : * Set the flow type even if there's no content
1810 : : * as we must have a flow type.
1811 : : */
1812 : 0 : rule->ixgbe_fdir.formatted.flow_type |=
1813 : : IXGBE_ATR_L4TYPE_SCTP;
1814 : : /*Not supported last point for range*/
1815 [ # # ]: 0 : if (item->last) {
1816 : 0 : rte_flow_error_set(error, EINVAL,
1817 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1818 : : item, "Not supported last point for range");
1819 : 0 : return -rte_errno;
1820 : : }
1821 : :
1822 : 0 : sctp_mask = item->mask;
1823 [ # # ]: 0 : if (sctp_mask != NULL) {
1824 : : /* only some mac types support sctp port masking */
1825 : 0 : if (hw->mac.type == ixgbe_mac_X550 ||
1826 : : hw->mac.type == ixgbe_mac_X550EM_x ||
1827 [ # # ]: 0 : hw->mac.type == ixgbe_mac_X550EM_a ||
1828 : : hw->mac.type == ixgbe_mac_E610) {
1829 : : /**
1830 : : * Only care about src & dst ports,
1831 : : * others should be masked.
1832 : : */
1833 : 0 : rule->b_mask = TRUE;
1834 [ # # ]: 0 : if (sctp_mask->hdr.tag ||
1835 [ # # ]: 0 : sctp_mask->hdr.cksum) {
1836 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1837 : 0 : rte_flow_error_set(error, EINVAL,
1838 : : RTE_FLOW_ERROR_TYPE_ITEM,
1839 : : item, "Not supported by fdir filter");
1840 : 0 : return -rte_errno;
1841 : : }
1842 : 0 : rule->mask.src_port_mask = sctp_mask->hdr.src_port;
1843 : 0 : rule->mask.dst_port_mask = sctp_mask->hdr.dst_port;
1844 : :
1845 [ # # ]: 0 : if (item->spec) {
1846 : 0 : rule->b_spec = TRUE;
1847 : : sctp_spec = item->spec;
1848 : 0 : rule->ixgbe_fdir.formatted.src_port =
1849 : 0 : sctp_spec->hdr.src_port;
1850 : 0 : rule->ixgbe_fdir.formatted.dst_port =
1851 : 0 : sctp_spec->hdr.dst_port;
1852 : : }
1853 : : /* others even sctp port masking is not supported */
1854 [ # # ]: 0 : } else if (sctp_mask->hdr.src_port ||
1855 [ # # ]: 0 : sctp_mask->hdr.dst_port ||
1856 [ # # ]: 0 : sctp_mask->hdr.tag ||
1857 [ # # ]: 0 : sctp_mask->hdr.cksum) {
1858 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1859 : 0 : rte_flow_error_set(error, EINVAL,
1860 : : RTE_FLOW_ERROR_TYPE_ITEM,
1861 : : item, "Not supported by fdir filter");
1862 : 0 : return -rte_errno;
1863 : : }
1864 [ # # ]: 0 : } else if (item->spec != NULL) {
1865 : : /* No port mask means protocol-only match; spec is invalid. */
1866 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1867 : 0 : rte_flow_error_set(error, EINVAL,
1868 : : RTE_FLOW_ERROR_TYPE_ITEM,
1869 : : item, "Not supported by fdir filter");
1870 : 0 : return -rte_errno;
1871 : : }
1872 : :
1873 : : item = next_no_fuzzy_pattern(pattern, item);
1874 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
1875 : : item->type != RTE_FLOW_ITEM_TYPE_END) {
1876 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1877 : 0 : rte_flow_error_set(error, EINVAL,
1878 : : RTE_FLOW_ERROR_TYPE_ITEM,
1879 : : item, "Not supported by fdir filter");
1880 : 0 : return -rte_errno;
1881 : : }
1882 : : }
1883 : :
1884 : : /* Get the flex byte info */
1885 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_RAW) {
1886 : : /* Not supported last point for range*/
1887 [ # # ]: 0 : if (item->last) {
1888 : 0 : rte_flow_error_set(error, EINVAL,
1889 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1890 : : item, "Not supported last point for range");
1891 : 0 : return -rte_errno;
1892 : : }
1893 : : /* mask should not be null */
1894 [ # # # # ]: 0 : if (!item->mask || !item->spec) {
1895 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1896 : 0 : rte_flow_error_set(error, EINVAL,
1897 : : RTE_FLOW_ERROR_TYPE_ITEM,
1898 : : item, "Not supported by fdir filter");
1899 : 0 : return -rte_errno;
1900 : : }
1901 : :
1902 : : raw_mask = item->mask;
1903 : :
1904 : : /* check mask */
1905 : 0 : if (raw_mask->relative != 0x1 ||
1906 : : raw_mask->search != 0x1 ||
1907 [ # # ]: 0 : raw_mask->reserved != 0x0 ||
1908 : : (uint32_t)raw_mask->offset != 0xffffffff ||
1909 [ # # ]: 0 : raw_mask->limit != 0xffff ||
1910 : : raw_mask->length != 0xffff) {
1911 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1912 : 0 : rte_flow_error_set(error, EINVAL,
1913 : : RTE_FLOW_ERROR_TYPE_ITEM,
1914 : : item, "Not supported by fdir filter");
1915 : 0 : return -rte_errno;
1916 : : }
1917 : :
1918 : : raw_spec = item->spec;
1919 : :
1920 : : /* check spec */
1921 : 0 : if (raw_spec->relative != 0 ||
1922 [ # # ]: 0 : raw_spec->search != 0 ||
1923 : 0 : raw_spec->reserved != 0 ||
1924 [ # # # # ]: 0 : raw_spec->offset > IXGBE_MAX_FLX_SOURCE_OFF ||
1925 : : raw_spec->offset % 2 ||
1926 [ # # ]: 0 : raw_spec->limit != 0 ||
1927 : 0 : raw_spec->length != 2 ||
1928 : : /* pattern can't be 0xffff */
1929 [ # # ]: 0 : (raw_spec->pattern[0] == 0xff &&
1930 [ # # ]: 0 : raw_spec->pattern[1] == 0xff)) {
1931 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1932 : 0 : rte_flow_error_set(error, EINVAL,
1933 : : RTE_FLOW_ERROR_TYPE_ITEM,
1934 : : item, "Not supported by fdir filter");
1935 : 0 : return -rte_errno;
1936 : : }
1937 : :
1938 : : /* check pattern mask */
1939 [ # # ]: 0 : if (raw_mask->pattern[0] != 0xff ||
1940 [ # # ]: 0 : raw_mask->pattern[1] != 0xff) {
1941 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1942 : 0 : rte_flow_error_set(error, EINVAL,
1943 : : RTE_FLOW_ERROR_TYPE_ITEM,
1944 : : item, "Not supported by fdir filter");
1945 : 0 : return -rte_errno;
1946 : : }
1947 : :
1948 : 0 : rule->mask.flex_bytes_mask = 0xffff;
1949 : 0 : rule->ixgbe_fdir.formatted.flex_bytes =
1950 : 0 : (((uint16_t)raw_spec->pattern[1]) << 8) |
1951 : 0 : raw_spec->pattern[0];
1952 : 0 : rule->flex_bytes_offset = raw_spec->offset;
1953 : : }
1954 : :
1955 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
1956 : : /* check if the next not void item is END */
1957 : : item = next_no_fuzzy_pattern(pattern, item);
1958 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
1959 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
1960 : 0 : rte_flow_error_set(error, EINVAL,
1961 : : RTE_FLOW_ERROR_TYPE_ITEM,
1962 : : item, "Not supported by fdir filter");
1963 : 0 : return -rte_errno;
1964 : : }
1965 : : }
1966 : :
1967 : : /* L4 protocol matching is enabled when parser selected an L4 type. */
1968 : 0 : rule->mask.l4_proto_match =
1969 : 0 : (rule->ixgbe_fdir.formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) != 0;
1970 : :
1971 : 0 : return 0;
1972 : : }
1973 : :
1974 : : #define NVGRE_PROTOCOL 0x6558
1975 : :
1976 : : /**
1977 : : * Parse the rule to see if it is a VxLAN or NVGRE flow director rule.
1978 : : * And get the flow director filter info BTW.
1979 : : * VxLAN PATTERN:
1980 : : * The first not void item must be ETH.
1981 : : * The second not void item must be IPV4/ IPV6.
1982 : : * The third not void item must be NVGRE.
1983 : : * The next not void item must be END.
1984 : : * NVGRE PATTERN:
1985 : : * The first not void item must be ETH.
1986 : : * The second not void item must be IPV4/ IPV6.
1987 : : * The third not void item must be NVGRE.
1988 : : * The next not void item must be END.
1989 : : * ACTION:
1990 : : * The first not void action should be QUEUE or DROP.
1991 : : * The second not void optional action should be MARK,
1992 : : * mark_id is a uint32_t number.
1993 : : * The next not void action should be END.
1994 : : * VxLAN pattern example:
1995 : : * ITEM Spec Mask
1996 : : * ETH NULL NULL
1997 : : * IPV4/IPV6 NULL NULL
1998 : : * UDP NULL NULL
1999 : : * VxLAN vni{0x00, 0x32, 0x54} {0xFF, 0xFF, 0xFF}
2000 : : * MAC VLAN tci 0x2016 0xEFFF
2001 : : * END
2002 : : * NEGRV pattern example:
2003 : : * ITEM Spec Mask
2004 : : * ETH NULL NULL
2005 : : * IPV4/IPV6 NULL NULL
2006 : : * NVGRE protocol 0x6558 0xFFFF
2007 : : * tni{0x00, 0x32, 0x54} {0xFF, 0xFF, 0xFF}
2008 : : * MAC VLAN tci 0x2016 0xEFFF
2009 : : * END
2010 : : * other members in mask and spec should set to 0x00.
2011 : : * item->last should be NULL.
2012 : : */
2013 : : static int
2014 : 0 : ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_item pattern[],
2015 : : const struct ci_flow_actions *parsed_actions,
2016 : : struct ixgbe_fdir_rule *rule,
2017 : : struct rte_flow_error *error)
2018 : : {
2019 : : const struct rte_flow_item *item;
2020 : : const struct rte_flow_item_vxlan *vxlan_spec;
2021 : : const struct rte_flow_item_vxlan *vxlan_mask;
2022 : : const struct rte_flow_item_nvgre *nvgre_spec;
2023 : : const struct rte_flow_item_nvgre *nvgre_mask;
2024 : : const struct rte_flow_item_eth *eth_spec;
2025 : : const struct rte_flow_item_eth *eth_mask;
2026 : : const struct rte_flow_item_vlan *vlan_spec;
2027 : : const struct rte_flow_item_vlan *vlan_mask;
2028 : : const struct rte_flow_action *fwd_action, *aux_action;
2029 : : uint32_t j;
2030 : :
2031 : 0 : fwd_action = parsed_actions->actions[0];
2032 : : /* can be NULL */
2033 [ # # ]: 0 : aux_action = parsed_actions->actions[1];
2034 : :
2035 : : /**
2036 : : * Some fields may not be provided. Set spec to 0 and mask to default
2037 : : * value. So, we need not do anything for the not provided fields later.
2038 : : */
2039 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2040 : 0 : memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask));
2041 : 0 : rule->mask.vlan_tci_mask = 0;
2042 : :
2043 : : /* set up queue/drop action */
2044 [ # # ]: 0 : if (fwd_action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
2045 : 0 : const struct rte_flow_action_queue *q_act = fwd_action->conf;
2046 : 0 : rule->queue = q_act->index;
2047 : : } else {
2048 : 0 : rule->fdirflags = IXGBE_FDIRCMD_DROP;
2049 : : }
2050 : :
2051 : : /* set up mark action */
2052 [ # # # # ]: 0 : if (aux_action != NULL && aux_action->type == RTE_FLOW_ACTION_TYPE_MARK) {
2053 : 0 : const struct rte_flow_action_mark *mark = aux_action->conf;
2054 : 0 : rule->soft_id = mark->id;
2055 : : }
2056 : :
2057 : : /**
2058 : : * The first not void item should be
2059 : : * MAC or IPv4 or IPv6 or UDP or VxLAN.
2060 : : */
2061 : : item = next_no_void_pattern(pattern, NULL);
2062 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
2063 : : item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
2064 : : item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
2065 : : item->type != RTE_FLOW_ITEM_TYPE_UDP &&
2066 : : item->type != RTE_FLOW_ITEM_TYPE_VXLAN &&
2067 : : item->type != RTE_FLOW_ITEM_TYPE_NVGRE) {
2068 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2069 : 0 : rte_flow_error_set(error, EINVAL,
2070 : : RTE_FLOW_ERROR_TYPE_ITEM,
2071 : : item, "Not supported by fdir filter");
2072 : 0 : return -rte_errno;
2073 : : }
2074 : :
2075 : 0 : rule->mode = RTE_FDIR_MODE_PERFECT_TUNNEL;
2076 : :
2077 : : /* Skip MAC. */
2078 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
2079 : : /* Only used to describe the protocol stack. */
2080 [ # # # # ]: 0 : if (item->spec || item->mask) {
2081 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2082 : 0 : rte_flow_error_set(error, EINVAL,
2083 : : RTE_FLOW_ERROR_TYPE_ITEM,
2084 : : item, "Not supported by fdir filter");
2085 : 0 : return -rte_errno;
2086 : : }
2087 : : /* Not supported last point for range*/
2088 [ # # ]: 0 : if (item->last) {
2089 : 0 : rte_flow_error_set(error, EINVAL,
2090 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2091 : : item, "Not supported last point for range");
2092 : 0 : return -rte_errno;
2093 : : }
2094 : :
2095 : : /* Check if the next not void item is IPv4 or IPv6. */
2096 : : item = next_no_void_pattern(pattern, item);
2097 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
2098 : : item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
2099 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2100 : 0 : rte_flow_error_set(error, EINVAL,
2101 : : RTE_FLOW_ERROR_TYPE_ITEM,
2102 : : item, "Not supported by fdir filter");
2103 : 0 : return -rte_errno;
2104 : : }
2105 : : }
2106 : :
2107 : : /* Skip IP. */
2108 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_IPV4 ||
2109 : : item->type == RTE_FLOW_ITEM_TYPE_IPV6) {
2110 : : /* Only used to describe the protocol stack. */
2111 [ # # # # ]: 0 : if (item->spec || item->mask) {
2112 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2113 : 0 : rte_flow_error_set(error, EINVAL,
2114 : : RTE_FLOW_ERROR_TYPE_ITEM,
2115 : : item, "Not supported by fdir filter");
2116 : 0 : return -rte_errno;
2117 : : }
2118 : : /*Not supported last point for range*/
2119 [ # # ]: 0 : if (item->last) {
2120 : 0 : rte_flow_error_set(error, EINVAL,
2121 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2122 : : item, "Not supported last point for range");
2123 : 0 : return -rte_errno;
2124 : : }
2125 : :
2126 : : /* Check if the next not void item is UDP or NVGRE. */
2127 : : item = next_no_void_pattern(pattern, item);
2128 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_UDP &&
2129 : : item->type != RTE_FLOW_ITEM_TYPE_NVGRE) {
2130 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2131 : 0 : rte_flow_error_set(error, EINVAL,
2132 : : RTE_FLOW_ERROR_TYPE_ITEM,
2133 : : item, "Not supported by fdir filter");
2134 : 0 : return -rte_errno;
2135 : : }
2136 : : }
2137 : :
2138 : : /* Skip UDP. */
2139 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_UDP) {
2140 : : /* Only used to describe the protocol stack. */
2141 [ # # # # ]: 0 : if (item->spec || item->mask) {
2142 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2143 : 0 : rte_flow_error_set(error, EINVAL,
2144 : : RTE_FLOW_ERROR_TYPE_ITEM,
2145 : : item, "Not supported by fdir filter");
2146 : 0 : return -rte_errno;
2147 : : }
2148 : : /*Not supported last point for range*/
2149 [ # # ]: 0 : if (item->last) {
2150 : 0 : rte_flow_error_set(error, EINVAL,
2151 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2152 : : item, "Not supported last point for range");
2153 : 0 : return -rte_errno;
2154 : : }
2155 : :
2156 : : /* Check if the next not void item is VxLAN. */
2157 : : item = next_no_void_pattern(pattern, item);
2158 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
2159 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2160 : 0 : rte_flow_error_set(error, EINVAL,
2161 : : RTE_FLOW_ERROR_TYPE_ITEM,
2162 : : item, "Not supported by fdir filter");
2163 : 0 : return -rte_errno;
2164 : : }
2165 : : }
2166 : :
2167 : : /* Get the VxLAN info */
2168 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN) {
2169 : 0 : rule->ixgbe_fdir.formatted.tunnel_type =
2170 : : IXGBE_FDIR_VXLAN_TUNNEL_TYPE;
2171 : :
2172 : : /* Only care about VNI, others should be masked. */
2173 [ # # ]: 0 : if (!item->mask) {
2174 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2175 : 0 : rte_flow_error_set(error, EINVAL,
2176 : : RTE_FLOW_ERROR_TYPE_ITEM,
2177 : : item, "Not supported by fdir filter");
2178 : 0 : return -rte_errno;
2179 : : }
2180 : : /*Not supported last point for range*/
2181 [ # # ]: 0 : if (item->last) {
2182 : 0 : rte_flow_error_set(error, EINVAL,
2183 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2184 : : item, "Not supported last point for range");
2185 : 0 : return -rte_errno;
2186 : : }
2187 : 0 : rule->b_mask = TRUE;
2188 : :
2189 : : /* Tunnel type is always meaningful. */
2190 : 0 : rule->mask.tunnel_type_mask = 1;
2191 : :
2192 : : vxlan_mask = item->mask;
2193 [ # # ]: 0 : if (vxlan_mask->hdr.flags) {
2194 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2195 : 0 : rte_flow_error_set(error, EINVAL,
2196 : : RTE_FLOW_ERROR_TYPE_ITEM,
2197 : : item, "Not supported by fdir filter");
2198 : 0 : return -rte_errno;
2199 : : }
2200 : : /* VNI must be totally masked or not. */
2201 [ # # # # ]: 0 : if ((vxlan_mask->hdr.vni[0] || vxlan_mask->hdr.vni[1] ||
2202 [ # # # # ]: 0 : vxlan_mask->hdr.vni[2]) &&
2203 : 0 : ((vxlan_mask->hdr.vni[0] != 0xFF) ||
2204 [ # # ]: 0 : (vxlan_mask->hdr.vni[1] != 0xFF) ||
2205 [ # # ]: 0 : (vxlan_mask->hdr.vni[2] != 0xFF))) {
2206 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2207 : 0 : rte_flow_error_set(error, EINVAL,
2208 : : RTE_FLOW_ERROR_TYPE_ITEM,
2209 : : item, "Not supported by fdir filter");
2210 : 0 : return -rte_errno;
2211 : : }
2212 : :
2213 [ # # ]: 0 : memcpy(&rule->mask.tunnel_id_mask, vxlan_mask->hdr.vni,
2214 : : RTE_DIM(vxlan_mask->hdr.vni));
2215 : :
2216 [ # # ]: 0 : if (item->spec) {
2217 : 0 : rule->b_spec = TRUE;
2218 : : vxlan_spec = item->spec;
2219 : : memcpy(((uint8_t *)
2220 : 0 : &rule->ixgbe_fdir.formatted.tni_vni),
2221 : 0 : vxlan_spec->hdr.vni, RTE_DIM(vxlan_spec->hdr.vni));
2222 : : }
2223 : : }
2224 : :
2225 : : /* Get the NVGRE info */
2226 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_NVGRE) {
2227 : 0 : rule->ixgbe_fdir.formatted.tunnel_type =
2228 : : IXGBE_FDIR_NVGRE_TUNNEL_TYPE;
2229 : :
2230 : : /**
2231 : : * Only care about flags0, flags1, protocol and TNI,
2232 : : * others should be masked.
2233 : : */
2234 [ # # ]: 0 : if (!item->mask) {
2235 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2236 : 0 : rte_flow_error_set(error, EINVAL,
2237 : : RTE_FLOW_ERROR_TYPE_ITEM,
2238 : : item, "Not supported by fdir filter");
2239 : 0 : return -rte_errno;
2240 : : }
2241 : : /*Not supported last point for range*/
2242 [ # # ]: 0 : if (item->last) {
2243 : 0 : rte_flow_error_set(error, EINVAL,
2244 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2245 : : item, "Not supported last point for range");
2246 : 0 : return -rte_errno;
2247 : : }
2248 : 0 : rule->b_mask = TRUE;
2249 : :
2250 : : /* Tunnel type is always meaningful. */
2251 : 0 : rule->mask.tunnel_type_mask = 1;
2252 : :
2253 : : nvgre_mask = item->mask;
2254 [ # # ]: 0 : if (nvgre_mask->flow_id) {
2255 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2256 : 0 : rte_flow_error_set(error, EINVAL,
2257 : : RTE_FLOW_ERROR_TYPE_ITEM,
2258 : : item, "Not supported by fdir filter");
2259 : 0 : return -rte_errno;
2260 : : }
2261 [ # # ]: 0 : if (nvgre_mask->protocol &&
2262 : : nvgre_mask->protocol != 0xFFFF) {
2263 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2264 : 0 : rte_flow_error_set(error, EINVAL,
2265 : : RTE_FLOW_ERROR_TYPE_ITEM,
2266 : : item, "Not supported by fdir filter");
2267 : 0 : return -rte_errno;
2268 : : }
2269 [ # # # # ]: 0 : if (nvgre_mask->c_k_s_rsvd0_ver &&
2270 : : nvgre_mask->c_k_s_rsvd0_ver !=
2271 : : rte_cpu_to_be_16(0xFFFF)) {
2272 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2273 : 0 : rte_flow_error_set(error, EINVAL,
2274 : : RTE_FLOW_ERROR_TYPE_ITEM,
2275 : : item, "Not supported by fdir filter");
2276 : 0 : return -rte_errno;
2277 : : }
2278 : : /* TNI must be totally masked or not. */
2279 [ # # ]: 0 : if (nvgre_mask->tni[0] &&
2280 [ # # ]: 0 : ((nvgre_mask->tni[0] != 0xFF) ||
2281 : 0 : (nvgre_mask->tni[1] != 0xFF) ||
2282 [ # # ]: 0 : (nvgre_mask->tni[2] != 0xFF))) {
2283 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2284 : 0 : rte_flow_error_set(error, EINVAL,
2285 : : RTE_FLOW_ERROR_TYPE_ITEM,
2286 : : item, "Not supported by fdir filter");
2287 : 0 : return -rte_errno;
2288 : : }
2289 : : /* tni is a 24-bits bit field */
2290 [ # # ]: 0 : memcpy(&rule->mask.tunnel_id_mask, nvgre_mask->tni,
2291 : : RTE_DIM(nvgre_mask->tni));
2292 : 0 : rule->mask.tunnel_id_mask <<= 8;
2293 : :
2294 [ # # ]: 0 : if (item->spec) {
2295 : 0 : rule->b_spec = TRUE;
2296 : : nvgre_spec = item->spec;
2297 [ # # ]: 0 : if (nvgre_spec->c_k_s_rsvd0_ver !=
2298 : 0 : rte_cpu_to_be_16(0x2000) &&
2299 [ # # ]: 0 : nvgre_mask->c_k_s_rsvd0_ver) {
2300 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2301 : 0 : rte_flow_error_set(error, EINVAL,
2302 : : RTE_FLOW_ERROR_TYPE_ITEM,
2303 : : item, "Not supported by fdir filter");
2304 : 0 : return -rte_errno;
2305 : : }
2306 [ # # ]: 0 : if (nvgre_mask->protocol &&
2307 [ # # ]: 0 : nvgre_spec->protocol !=
2308 : : rte_cpu_to_be_16(NVGRE_PROTOCOL)) {
2309 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2310 : 0 : rte_flow_error_set(error, EINVAL,
2311 : : RTE_FLOW_ERROR_TYPE_ITEM,
2312 : : item, "Not supported by fdir filter");
2313 : 0 : return -rte_errno;
2314 : : }
2315 : : /* tni is a 24-bits bit field */
2316 : 0 : memcpy(&rule->ixgbe_fdir.formatted.tni_vni,
2317 : 0 : nvgre_spec->tni, RTE_DIM(nvgre_spec->tni));
2318 : : }
2319 : : }
2320 : :
2321 : : /* check if the next not void item is MAC */
2322 : : item = next_no_void_pattern(pattern, item);
2323 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
2324 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2325 : 0 : rte_flow_error_set(error, EINVAL,
2326 : : RTE_FLOW_ERROR_TYPE_ITEM,
2327 : : item, "Not supported by fdir filter");
2328 : 0 : return -rte_errno;
2329 : : }
2330 : :
2331 : : /**
2332 : : * Only support vlan and dst MAC address,
2333 : : * others should be masked.
2334 : : */
2335 : :
2336 [ # # ]: 0 : if (!item->mask) {
2337 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2338 : 0 : rte_flow_error_set(error, EINVAL,
2339 : : RTE_FLOW_ERROR_TYPE_ITEM,
2340 : : item, "Not supported by fdir filter");
2341 : 0 : return -rte_errno;
2342 : : }
2343 : : /*Not supported last point for range*/
2344 [ # # ]: 0 : if (item->last) {
2345 : 0 : rte_flow_error_set(error, EINVAL,
2346 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2347 : : item, "Not supported last point for range");
2348 : 0 : return -rte_errno;
2349 : : }
2350 : 0 : rule->b_mask = TRUE;
2351 : : eth_mask = item->mask;
2352 : :
2353 : : /* Ether type should be masked. */
2354 [ # # ]: 0 : if (eth_mask->hdr.ether_type) {
2355 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2356 : 0 : rte_flow_error_set(error, EINVAL,
2357 : : RTE_FLOW_ERROR_TYPE_ITEM,
2358 : : item, "Not supported by fdir filter");
2359 : 0 : return -rte_errno;
2360 : : }
2361 : :
2362 : : /* src MAC address should be masked. */
2363 [ # # ]: 0 : for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
2364 [ # # ]: 0 : if (eth_mask->hdr.src_addr.addr_bytes[j]) {
2365 : : memset(rule, 0,
2366 : : sizeof(struct ixgbe_fdir_rule));
2367 : 0 : rte_flow_error_set(error, EINVAL,
2368 : : RTE_FLOW_ERROR_TYPE_ITEM,
2369 : : item, "Not supported by fdir filter");
2370 : 0 : return -rte_errno;
2371 : : }
2372 : : }
2373 : 0 : rule->mask.mac_addr_byte_mask = 0;
2374 [ # # ]: 0 : for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
2375 : : /* It's a per byte mask. */
2376 [ # # ]: 0 : if (eth_mask->hdr.dst_addr.addr_bytes[j] == 0xFF) {
2377 : 0 : rule->mask.mac_addr_byte_mask |= 0x1 << j;
2378 [ # # ]: 0 : } else if (eth_mask->hdr.dst_addr.addr_bytes[j]) {
2379 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2380 : 0 : rte_flow_error_set(error, EINVAL,
2381 : : RTE_FLOW_ERROR_TYPE_ITEM,
2382 : : item, "Not supported by fdir filter");
2383 : 0 : return -rte_errno;
2384 : : }
2385 : : }
2386 : :
2387 : : /* When no vlan, considered as full mask. */
2388 : 0 : rule->mask.vlan_tci_mask = rte_cpu_to_be_16(0xEFFF);
2389 : :
2390 [ # # ]: 0 : if (item->spec) {
2391 : 0 : rule->b_spec = TRUE;
2392 : : eth_spec = item->spec;
2393 : :
2394 : : /* Get the dst MAC. */
2395 [ # # ]: 0 : for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
2396 : 0 : rule->ixgbe_fdir.formatted.inner_mac[j] =
2397 : 0 : eth_spec->hdr.dst_addr.addr_bytes[j];
2398 : : }
2399 : : }
2400 : :
2401 : : /**
2402 : : * Check if the next not void item is vlan or ipv4.
2403 : : * IPv6 is not supported.
2404 : : */
2405 : : item = next_no_void_pattern(pattern, item);
2406 [ # # ]: 0 : if ((item->type != RTE_FLOW_ITEM_TYPE_VLAN) &&
2407 : : (item->type != RTE_FLOW_ITEM_TYPE_IPV4)) {
2408 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2409 : 0 : rte_flow_error_set(error, EINVAL,
2410 : : RTE_FLOW_ERROR_TYPE_ITEM,
2411 : : item, "Not supported by fdir filter");
2412 : 0 : return -rte_errno;
2413 : : }
2414 : : /*Not supported last point for range*/
2415 [ # # ]: 0 : if (item->last) {
2416 : 0 : rte_flow_error_set(error, EINVAL,
2417 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2418 : : item, "Not supported last point for range");
2419 : 0 : return -rte_errno;
2420 : : }
2421 : :
2422 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
2423 [ # # # # ]: 0 : if (!(item->spec && item->mask)) {
2424 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2425 : 0 : rte_flow_error_set(error, EINVAL,
2426 : : RTE_FLOW_ERROR_TYPE_ITEM,
2427 : : item, "Not supported by fdir filter");
2428 : 0 : return -rte_errno;
2429 : : }
2430 : :
2431 : : vlan_spec = item->spec;
2432 : : vlan_mask = item->mask;
2433 : :
2434 : 0 : rule->ixgbe_fdir.formatted.vlan_id = vlan_spec->hdr.vlan_tci;
2435 : :
2436 : 0 : rule->mask.vlan_tci_mask = vlan_mask->hdr.vlan_tci;
2437 : 0 : rule->mask.vlan_tci_mask &= rte_cpu_to_be_16(0xEFFF);
2438 : : /* More than one tags are not supported. */
2439 : :
2440 : : /* check if the next not void item is END */
2441 : : item = next_no_void_pattern(pattern, item);
2442 : :
2443 [ # # ]: 0 : if (item->type != RTE_FLOW_ITEM_TYPE_END) {
2444 : : memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
2445 : 0 : rte_flow_error_set(error, EINVAL,
2446 : : RTE_FLOW_ERROR_TYPE_ITEM,
2447 : : item, "Not supported by fdir filter");
2448 : 0 : return -rte_errno;
2449 : : }
2450 : : }
2451 : :
2452 : : /**
2453 : : * If the tags is 0, it means don't care about the VLAN.
2454 : : * Do nothing.
2455 : : */
2456 : :
2457 : : return 0;
2458 : : }
2459 : :
2460 : : /*
2461 : : * Check flow director actions
2462 : : */
2463 : : static int
2464 : 0 : ixgbe_fdir_actions_check(const struct ci_flow_actions *parsed_actions,
2465 : : const struct ci_flow_actions_check_param *param __rte_unused,
2466 : : struct rte_flow_error *error)
2467 : : {
2468 : 0 : const enum rte_flow_action_type fwd_actions[] = {
2469 : : RTE_FLOW_ACTION_TYPE_QUEUE,
2470 : : RTE_FLOW_ACTION_TYPE_DROP,
2471 : : RTE_FLOW_ACTION_TYPE_END
2472 : : };
2473 : : const struct rte_flow_action *action;
2474 : :
2475 : : /* do the generic checks first */
2476 : 0 : int ret = ixgbe_flow_actions_check(parsed_actions, param, error);
2477 [ # # ]: 0 : if (ret)
2478 : : return ret;
2479 : :
2480 : : /* first action must be a forwarding action */
2481 : 0 : action = parsed_actions->actions[0];
2482 [ # # ]: 0 : if (!ci_flow_action_type_in_list(action->type, fwd_actions)) {
2483 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
2484 : : action, "First action must be QUEUE or DROP");
2485 : : }
2486 : :
2487 : : /* second action, if specified, must not be a forwarding action */
2488 : 0 : action = parsed_actions->actions[1];
2489 [ # # # # ]: 0 : if (action != NULL && ci_flow_action_type_in_list(action->type, fwd_actions)) {
2490 : 0 : return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
2491 : : action, "Conflicting actions");
2492 : : }
2493 : : return 0;
2494 : : }
2495 : :
2496 : : static int
2497 : 0 : ixgbe_parse_fdir_filter(struct rte_eth_dev *dev,
2498 : : const struct rte_flow_attr *attr,
2499 : : const struct rte_flow_item pattern[],
2500 : : const struct rte_flow_action actions[],
2501 : : struct ixgbe_fdir_rule *rule,
2502 : : struct rte_flow_error *error)
2503 : : {
2504 : : int ret;
2505 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
2506 : : struct ixgbe_adapter *adapter = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2507 : : struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_PRIVATE_TO_FDIR_CONF(adapter);
2508 : : struct ci_flow_actions parsed_actions;
2509 : 0 : struct ci_flow_actions_check_param ap_param = {
2510 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
2511 : : /* queue/mark/drop allowed here */
2512 : : RTE_FLOW_ACTION_TYPE_QUEUE,
2513 : : RTE_FLOW_ACTION_TYPE_DROP,
2514 : : RTE_FLOW_ACTION_TYPE_MARK,
2515 : : RTE_FLOW_ACTION_TYPE_END
2516 : : },
2517 : : .driver_ctx = dev->data,
2518 : : .check = ixgbe_fdir_actions_check
2519 : : };
2520 : :
2521 [ # # ]: 0 : if (hw->mac.type != ixgbe_mac_82599EB &&
2522 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X540 &&
2523 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550 &&
2524 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_x &&
2525 [ # # ]: 0 : hw->mac.type != ixgbe_mac_X550EM_a &&
2526 : : hw->mac.type != ixgbe_mac_E610)
2527 : : return -ENOTSUP;
2528 : :
2529 : : /* validate attributes */
2530 : 0 : ret = ci_flow_check_attr(attr, NULL, error);
2531 [ # # ]: 0 : if (ret)
2532 : : return ret;
2533 : :
2534 : : /* parse requested actions */
2535 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
2536 [ # # ]: 0 : if (ret)
2537 : : return ret;
2538 : :
2539 : 0 : fdir_conf->drop_queue = IXGBE_FDIR_DROP_QUEUE;
2540 : :
2541 : 0 : ret = ixgbe_parse_fdir_filter_normal(dev, pattern, &parsed_actions, rule, error);
2542 [ # # ]: 0 : if (!ret)
2543 : : return 0;
2544 : :
2545 : 0 : return ixgbe_parse_fdir_filter_tunnel(pattern, &parsed_actions,
2546 : : rule, error);
2547 : : }
2548 : :
2549 : : static int
2550 : 0 : ixgbe_fdir_process_rule(struct ixgbe_adapter *adapter,
2551 : : struct ixgbe_hw_fdir_info *fdir_info,
2552 : : struct ixgbe_fdir_rule *fdir_rule,
2553 : : bool *first_mask,
2554 : : struct rte_flow_error *error)
2555 : : {
2556 : : bool flex_byte_offset_changed;
2557 : : int ret;
2558 : :
2559 : : /* rule must have a spec to be valid */
2560 [ # # ]: 0 : if (!fdir_rule->b_spec)
2561 : 0 : return rte_flow_error_set(error, EINVAL,
2562 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2563 : : NULL, "No filter spec");
2564 : :
2565 : : /* if rule doesn't have a mask, nothing to be done */
2566 [ # # ]: 0 : if (!fdir_rule->b_mask)
2567 : : return 0;
2568 : :
2569 : : /* if we already have a mask, check if it's compatible */
2570 [ # # ]: 0 : if (fdir_info->mask_added) {
2571 : 0 : ret = memcmp(&fdir_info->mask, &fdir_rule->mask,
2572 : : sizeof(struct ixgbe_hw_fdir_mask));
2573 [ # # ]: 0 : if (ret)
2574 : 0 : return rte_flow_error_set(error, EINVAL,
2575 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2576 : : NULL, "Mask mismatch");
2577 : :
2578 [ # # ]: 0 : if (fdir_rule->mask.flex_bytes_mask &&
2579 : 0 : fdir_info->flex_bytes_offset !=
2580 [ # # ]: 0 : fdir_rule->flex_bytes_offset)
2581 : 0 : return rte_flow_error_set(error, EINVAL,
2582 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2583 : : NULL, "Flex bytes offset mismatch");
2584 : :
2585 : : /* success */
2586 : : return 0;
2587 : : }
2588 : :
2589 : : /* we don't have a mask yet, so set it up based on this rule */
2590 : : flex_byte_offset_changed =
2591 : 0 : fdir_info->flex_bytes_offset !=
2592 : 0 : fdir_rule->flex_bytes_offset;
2593 : :
2594 [ # # # # ]: 0 : if (fdir_rule->mask.flex_bytes_mask != 0 && flex_byte_offset_changed) {
2595 : 0 : ret = ixgbe_fdir_set_flexbytes_offset(adapter,
2596 : : fdir_rule->flex_bytes_offset);
2597 [ # # ]: 0 : if (ret)
2598 : 0 : return rte_flow_error_set(error, EINVAL,
2599 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2600 : : NULL,
2601 : : "Failed to set flex bytes offset");
2602 : : }
2603 : :
2604 : 0 : ret = ixgbe_fdir_set_input_mask(adapter, &fdir_rule->mask,
2605 : : fdir_rule->mode);
2606 [ # # ]: 0 : if (ret)
2607 : 0 : return rte_flow_error_set(error, EINVAL,
2608 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2609 : : NULL, "Failed to set fdir mask");
2610 : :
2611 : : /* let the caller know that we've installed a mask */
2612 : 0 : *first_mask = true;
2613 : :
2614 : 0 : return 0;
2615 : : }
2616 : :
2617 : : static int
2618 : 0 : ixgbe_fdir_flow_program(struct rte_eth_dev *dev,
2619 : : struct ixgbe_adapter *adapter,
2620 : : struct ixgbe_fdir_rule *fdir_rule,
2621 : : bool *first_mask,
2622 : : struct rte_flow_error *error)
2623 : : {
2624 : 0 : struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
2625 : 0 : struct rte_eth_fdir_conf local_fdir_conf = *fdir_conf;
2626 : 0 : struct ixgbe_hw_fdir_info *fdir_info =
2627 : : IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
2628 : : int ret;
2629 : :
2630 [ # # ]: 0 : if (fdir_rule->queue >= dev->data->nb_rx_queues) {
2631 : 0 : return rte_flow_error_set(error, EINVAL,
2632 : : RTE_FLOW_ERROR_TYPE_ACTION,
2633 : : NULL, "queue id > max number of queues");
2634 : : }
2635 : :
2636 : 0 : local_fdir_conf.mode = fdir_rule->mode;
2637 : :
2638 : : /* Configure FDIR mode if this is the first filter */
2639 [ # # ]: 0 : if (fdir_conf->mode == RTE_FDIR_MODE_NONE) {
2640 : 0 : ret = ixgbe_fdir_configure(adapter, &local_fdir_conf, &fdir_rule->mask);
2641 [ # # ]: 0 : if (ret) {
2642 : 0 : return rte_flow_error_set(error, EINVAL,
2643 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2644 : : NULL, "Failed to configure fdir mode");
2645 : : }
2646 [ # # ]: 0 : } else if (fdir_conf->mode != fdir_rule->mode) {
2647 : 0 : return rte_flow_error_set(error, EINVAL,
2648 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2649 : : NULL, "Conflict with existing fdir mode");
2650 : : }
2651 : :
2652 : : /* Process and validate rule spec and mask */
2653 : 0 : ret = ixgbe_fdir_process_rule(adapter, fdir_info, fdir_rule,
2654 : : first_mask, error);
2655 [ # # ]: 0 : if (ret)
2656 : : return ret;
2657 : :
2658 : : /* Program the filter */
2659 : 0 : ret = ixgbe_fdir_filter_program(adapter, &local_fdir_conf,
2660 : : fdir_rule, FALSE, FALSE);
2661 [ # # ]: 0 : if (ret)
2662 : 0 : return rte_flow_error_set(error, EINVAL,
2663 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2664 : : NULL, "Failed to add fdir filter");
2665 : :
2666 : : return 0;
2667 : : }
2668 : :
2669 : : /* Flow actions check specific to RSS filter */
2670 : : static int
2671 : 0 : ixgbe_flow_actions_check_rss(const struct ci_flow_actions *parsed_actions,
2672 : : const struct ci_flow_actions_check_param *param,
2673 : : struct rte_flow_error *error)
2674 : : {
2675 : 0 : const struct rte_flow_action *action = parsed_actions->actions[0];
2676 : 0 : const struct rte_flow_action_rss *rss_act = action->conf;
2677 : 0 : struct rte_eth_dev_data *dev_data = param->driver_ctx;
2678 : : const size_t rss_key_len = sizeof(((struct ixgbe_rte_flow_rss_conf *)0)->key);
2679 : : size_t q_idx, q;
2680 : :
2681 : : /* check if queue list is not empty */
2682 [ # # ]: 0 : if (rss_act->queue_num == 0) {
2683 : 0 : return rte_flow_error_set(error, ENOTSUP,
2684 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
2685 : : "RSS queue list is empty");
2686 : : }
2687 : :
2688 : : /* check if each RSS queue is valid */
2689 [ # # ]: 0 : for (q_idx = 0; q_idx < rss_act->queue_num; q_idx++) {
2690 : 0 : q = rss_act->queue[q_idx];
2691 [ # # ]: 0 : if (q >= dev_data->nb_rx_queues) {
2692 : 0 : return rte_flow_error_set(error, ENOTSUP,
2693 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
2694 : : "Invalid RSS queue specified");
2695 : : }
2696 : : }
2697 : :
2698 : : /* only support default hash function */
2699 [ # # ]: 0 : if (rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
2700 : 0 : return rte_flow_error_set(error, ENOTSUP,
2701 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
2702 : : "Non-default RSS hash functions are not supported");
2703 : : }
2704 : : /* levels aren't supported */
2705 [ # # ]: 0 : if (rss_act->level) {
2706 : 0 : return rte_flow_error_set(error, ENOTSUP,
2707 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
2708 : : "A nonzero RSS encapsulation level is not supported");
2709 : : }
2710 : : /* check key length */
2711 [ # # ]: 0 : if (rss_act->key_len != 0 && rss_act->key_len != rss_key_len) {
2712 : 0 : return rte_flow_error_set(error, ENOTSUP,
2713 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
2714 : : "RSS key must be exactly 40 bytes long");
2715 : : }
2716 : : return 0;
2717 : : }
2718 : :
2719 : : static int
2720 : 0 : ixgbe_parse_rss_filter(struct rte_eth_dev *dev,
2721 : : const struct rte_flow_attr *attr,
2722 : : const struct rte_flow_action actions[],
2723 : : struct ixgbe_rte_flow_rss_conf *rss_conf,
2724 : : struct rte_flow_error *error)
2725 : : {
2726 : : struct ci_flow_actions parsed_actions;
2727 : 0 : struct ci_flow_actions_check_param ap_param = {
2728 : 0 : .allowed_types = (const enum rte_flow_action_type[]){
2729 : : /* only rss allowed here */
2730 : : RTE_FLOW_ACTION_TYPE_RSS,
2731 : : RTE_FLOW_ACTION_TYPE_END
2732 : : },
2733 : 0 : .driver_ctx = dev->data,
2734 : : .check = ixgbe_flow_actions_check_rss,
2735 : : .max_actions = 1,
2736 : : };
2737 : : int ret;
2738 : : const struct rte_flow_action *action;
2739 : :
2740 : : /* validate attributes */
2741 : 0 : ret = ci_flow_check_attr(attr, NULL, error);
2742 [ # # ]: 0 : if (ret)
2743 : : return ret;
2744 : :
2745 : : /* parse requested actions */
2746 : 0 : ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
2747 [ # # ]: 0 : if (ret)
2748 : : return ret;
2749 : 0 : action = parsed_actions.actions[0];
2750 : :
2751 [ # # ]: 0 : if (ixgbe_rss_conf_init(rss_conf, action->conf))
2752 : 0 : return rte_flow_error_set(error, EINVAL,
2753 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
2754 : : "RSS context initialization failure");
2755 : :
2756 : : return 0;
2757 : : }
2758 : :
2759 : : /* remove the rss filter */
2760 : : static void
2761 : : ixgbe_clear_rss_filter(struct rte_eth_dev *dev)
2762 : : {
2763 : 0 : struct ixgbe_adapter *adapter =
2764 : 0 : IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2765 : : struct ixgbe_filter_info *filter_info =
2766 : : IXGBE_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private);
2767 : :
2768 [ # # ]: 0 : if (filter_info->rss_info.conf.queue_num)
2769 : 0 : ixgbe_config_rss_filter(adapter, &filter_info->rss_info, FALSE);
2770 : : }
2771 : :
2772 : : void
2773 : 0 : ixgbe_filterlist_init(struct rte_eth_dev *dev)
2774 : : {
2775 : 0 : struct ixgbe_adapter *adapter = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2776 : :
2777 : 0 : TAILQ_INIT(&adapter->flow_list);
2778 : 0 : }
2779 : :
2780 : : void
2781 : 0 : ixgbe_filterlist_flush(struct rte_eth_dev *dev)
2782 : : {
2783 : 0 : struct ixgbe_adapter *adapter = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2784 : : struct ixgbe_filter_ele_base *ele, *tmp;
2785 : :
2786 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(ele, &adapter->flow_list, entries, tmp) {
2787 : : struct ixgbe_flow_mem *ixgbe_flow_mem_ptr =
2788 : : (struct ixgbe_flow_mem *)ele;
2789 : 0 : struct rte_flow *flow = ixgbe_flow_mem_ptr->flow;
2790 : :
2791 [ # # ]: 0 : TAILQ_REMOVE(&adapter->flow_list, ele, entries);
2792 : 0 : rte_free(flow->rule);
2793 : 0 : rte_free(flow);
2794 : 0 : rte_free(ele);
2795 : : }
2796 : 0 : }
2797 : :
2798 : : /**
2799 : : * Create or destroy a flow rule.
2800 : : * Theorically one rule can match more than one filters.
2801 : : * We will let it use the filter which it hitt first.
2802 : : * So, the sequence matters.
2803 : : */
2804 : : static struct rte_flow *
2805 : 0 : ixgbe_flow_create(struct rte_eth_dev *dev,
2806 : : const struct rte_flow_attr *attr,
2807 : : const struct rte_flow_item pattern[],
2808 : : const struct rte_flow_action actions[],
2809 : : struct rte_flow_error *error)
2810 : : {
2811 : : int ret;
2812 : 0 : struct ixgbe_adapter *adapter =
2813 : 0 : IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2814 : : struct rte_eth_ntuple_filter ntuple_filter;
2815 : : struct rte_eth_ethertype_filter ethertype_filter;
2816 : : struct rte_eth_syn_filter syn_filter;
2817 : : struct ixgbe_fdir_rule fdir_rule;
2818 : : struct ixgbe_l2_tunnel_conf l2_tn_filter;
2819 : : struct ixgbe_hw_fdir_info *fdir_info =
2820 : : IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
2821 : : struct ixgbe_rte_flow_rss_conf rss_conf;
2822 : : struct rte_flow *flow = NULL;
2823 : : struct ixgbe_ntuple_filter_ele *ntuple_filter_ptr;
2824 : : struct ixgbe_ethertype_filter_ele *ethertype_filter_ptr;
2825 : : struct ixgbe_eth_syn_filter_ele *syn_filter_ptr;
2826 : : struct ixgbe_eth_l2_tunnel_conf_ele *l2_tn_filter_ptr;
2827 : : struct ixgbe_fdir_rule_ele *fdir_rule_ptr;
2828 : : struct ixgbe_rss_conf_ele *rss_filter_ptr;
2829 : : struct ixgbe_flow_mem *ixgbe_flow_mem_ptr;
2830 : :
2831 : 0 : flow = rte_zmalloc("ixgbe_rte_flow", sizeof(struct rte_flow), 0);
2832 [ # # ]: 0 : if (!flow) {
2833 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2834 : 0 : return (struct rte_flow *)flow;
2835 : : }
2836 : 0 : ixgbe_flow_mem_ptr = rte_zmalloc("ixgbe_flow_mem",
2837 : : sizeof(struct ixgbe_flow_mem), 0);
2838 [ # # ]: 0 : if (!ixgbe_flow_mem_ptr) {
2839 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2840 : 0 : rte_free(flow);
2841 : 0 : return NULL;
2842 : : }
2843 : 0 : ixgbe_flow_mem_ptr->flow = flow;
2844 : 0 : TAILQ_INSERT_TAIL(&adapter->flow_list,
2845 : : &ixgbe_flow_mem_ptr->base, entries);
2846 : :
2847 : : /**
2848 : : * Special case for flow action type RTE_FLOW_ACTION_TYPE_SECURITY
2849 : : */
2850 : 0 : ret = ixgbe_parse_security_filter(dev, attr, pattern, actions, error);
2851 [ # # ]: 0 : if (!ret) {
2852 : 0 : flow->is_security = true;
2853 : 0 : return flow;
2854 : : }
2855 : :
2856 : : memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter));
2857 : 0 : ret = ixgbe_parse_ntuple_filter(dev, attr, pattern,
2858 : : actions, &ntuple_filter, error);
2859 : :
2860 [ # # ]: 0 : if (!ret) {
2861 : 0 : ret = ixgbe_add_del_ntuple_filter(adapter, &ntuple_filter, TRUE);
2862 [ # # ]: 0 : if (!ret) {
2863 : 0 : ntuple_filter_ptr = rte_zmalloc("ixgbe_ntuple_filter",
2864 : : sizeof(struct ixgbe_ntuple_filter_ele), 0);
2865 [ # # ]: 0 : if (!ntuple_filter_ptr) {
2866 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2867 : 0 : goto out;
2868 : : }
2869 : 0 : memcpy(&ntuple_filter_ptr->filter_info,
2870 : : &ntuple_filter,
2871 : : sizeof(struct rte_eth_ntuple_filter));
2872 : 0 : flow->rule = ntuple_filter_ptr;
2873 : 0 : flow->filter_type = RTE_ETH_FILTER_NTUPLE;
2874 : 0 : return flow;
2875 : : }
2876 : 0 : goto out;
2877 : : }
2878 : :
2879 : : memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter));
2880 : 0 : ret = ixgbe_parse_ethertype_filter(dev, attr, pattern,
2881 : : actions, ðertype_filter, error);
2882 [ # # ]: 0 : if (!ret) {
2883 : 0 : ret = ixgbe_add_del_ethertype_filter(adapter,
2884 : : ðertype_filter, TRUE);
2885 [ # # ]: 0 : if (!ret) {
2886 : 0 : ethertype_filter_ptr = rte_zmalloc(
2887 : : "ixgbe_ethertype_filter",
2888 : : sizeof(struct ixgbe_ethertype_filter_ele), 0);
2889 [ # # ]: 0 : if (!ethertype_filter_ptr) {
2890 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2891 : 0 : goto out;
2892 : : }
2893 : 0 : memcpy(ðertype_filter_ptr->filter_info,
2894 : : ðertype_filter,
2895 : : sizeof(struct rte_eth_ethertype_filter));
2896 : 0 : flow->rule = ethertype_filter_ptr;
2897 : 0 : flow->filter_type = RTE_ETH_FILTER_ETHERTYPE;
2898 : 0 : return flow;
2899 : : }
2900 : 0 : goto out;
2901 : : }
2902 : :
2903 : : memset(&syn_filter, 0, sizeof(struct rte_eth_syn_filter));
2904 : 0 : ret = ixgbe_parse_syn_filter(dev, attr, pattern,
2905 : : actions, &syn_filter, error);
2906 [ # # ]: 0 : if (!ret) {
2907 : 0 : ret = ixgbe_syn_filter_set(adapter, &syn_filter, TRUE);
2908 [ # # ]: 0 : if (!ret) {
2909 : 0 : syn_filter_ptr = rte_zmalloc("ixgbe_syn_filter",
2910 : : sizeof(struct ixgbe_eth_syn_filter_ele), 0);
2911 [ # # ]: 0 : if (!syn_filter_ptr) {
2912 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2913 : 0 : goto out;
2914 : : }
2915 : 0 : memcpy(&syn_filter_ptr->filter_info,
2916 : : &syn_filter,
2917 : : sizeof(struct rte_eth_syn_filter));
2918 : 0 : flow->rule = syn_filter_ptr;
2919 : 0 : flow->filter_type = RTE_ETH_FILTER_SYN;
2920 : 0 : return flow;
2921 : : }
2922 : 0 : goto out;
2923 : : }
2924 : :
2925 : : memset(&fdir_rule, 0, sizeof(struct ixgbe_fdir_rule));
2926 : 0 : ret = ixgbe_parse_fdir_filter(dev, attr, pattern,
2927 : : actions, &fdir_rule, error);
2928 [ # # ]: 0 : if (!ret) {
2929 : 0 : struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
2930 : 0 : bool first_mask = false;
2931 : :
2932 : 0 : ret = ixgbe_fdir_flow_program(dev, adapter, &fdir_rule,
2933 : : &first_mask, error);
2934 [ # # ]: 0 : if (ret)
2935 : 0 : goto out;
2936 : :
2937 : 0 : fdir_rule_ptr = rte_zmalloc("ixgbe_fdir_filter",
2938 : : sizeof(struct ixgbe_fdir_rule_ele), 0);
2939 [ # # ]: 0 : if (!fdir_rule_ptr) {
2940 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2941 : 0 : goto out;
2942 : : }
2943 : : /* update global state */
2944 [ # # ]: 0 : if (first_mask) {
2945 : 0 : fdir_info->mask_added = TRUE;
2946 : 0 : fdir_info->mask = fdir_rule.mask;
2947 : 0 : fdir_info->flex_bytes_offset = fdir_rule.flex_bytes_offset;
2948 : : }
2949 : 0 : fdir_info->n_flows++;
2950 : 0 : fdir_conf->mode = fdir_rule.mode;
2951 : :
2952 : 0 : memcpy(&fdir_rule_ptr->filter_info,
2953 : : &fdir_rule,
2954 : : sizeof(struct ixgbe_fdir_rule));
2955 : 0 : flow->rule = fdir_rule_ptr;
2956 : 0 : flow->filter_type = RTE_ETH_FILTER_FDIR;
2957 : 0 : return flow;
2958 : : }
2959 : :
2960 : : memset(&l2_tn_filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
2961 : 0 : ret = ixgbe_parse_l2_tn_filter(dev, attr, pattern,
2962 : : actions, &l2_tn_filter, error);
2963 [ # # ]: 0 : if (!ret) {
2964 : 0 : ret = ixgbe_dev_l2_tunnel_filter_add(adapter, &l2_tn_filter, FALSE);
2965 [ # # ]: 0 : if (!ret) {
2966 : 0 : l2_tn_filter_ptr = rte_zmalloc("ixgbe_l2_tn_filter",
2967 : : sizeof(struct ixgbe_eth_l2_tunnel_conf_ele), 0);
2968 [ # # ]: 0 : if (!l2_tn_filter_ptr) {
2969 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2970 : 0 : goto out;
2971 : : }
2972 : 0 : memcpy(&l2_tn_filter_ptr->filter_info,
2973 : : &l2_tn_filter,
2974 : : sizeof(struct ixgbe_l2_tunnel_conf));
2975 : 0 : flow->rule = l2_tn_filter_ptr;
2976 : 0 : flow->filter_type = RTE_ETH_FILTER_L2_TUNNEL;
2977 : 0 : return flow;
2978 : : }
2979 : : }
2980 : :
2981 : : memset(&rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
2982 : 0 : ret = ixgbe_parse_rss_filter(dev, attr,
2983 : : actions, &rss_conf, error);
2984 [ # # ]: 0 : if (!ret) {
2985 : 0 : ret = ixgbe_config_rss_filter(adapter, &rss_conf, TRUE);
2986 [ # # ]: 0 : if (!ret) {
2987 : 0 : rss_filter_ptr = rte_zmalloc("ixgbe_rss_filter",
2988 : : sizeof(struct ixgbe_rss_conf_ele), 0);
2989 [ # # ]: 0 : if (!rss_filter_ptr) {
2990 : 0 : PMD_DRV_LOG(ERR, "failed to allocate memory");
2991 : 0 : goto out;
2992 : : }
2993 : 0 : ixgbe_rss_conf_init(&rss_filter_ptr->filter_info,
2994 : : &rss_conf.conf);
2995 : 0 : flow->rule = rss_filter_ptr;
2996 : 0 : flow->filter_type = RTE_ETH_FILTER_HASH;
2997 : 0 : return flow;
2998 : : }
2999 : : }
3000 : :
3001 : 0 : out:
3002 [ # # ]: 0 : TAILQ_REMOVE(&adapter->flow_list,
3003 : : &ixgbe_flow_mem_ptr->base, entries);
3004 : 0 : rte_flow_error_set(error, -ret,
3005 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
3006 : : "Failed to create flow.");
3007 : 0 : rte_free(ixgbe_flow_mem_ptr);
3008 : 0 : rte_free(flow);
3009 : 0 : return NULL;
3010 : : }
3011 : :
3012 : : /**
3013 : : * Check if the flow rule is supported by ixgbe.
3014 : : * It only checks the format. Don't guarantee the rule can be programmed into
3015 : : * the HW. Because there can be no enough room for the rule.
3016 : : */
3017 : : static int
3018 : 0 : ixgbe_flow_validate(struct rte_eth_dev *dev,
3019 : : const struct rte_flow_attr *attr,
3020 : : const struct rte_flow_item pattern[],
3021 : : const struct rte_flow_action actions[],
3022 : : struct rte_flow_error *error)
3023 : : {
3024 : : struct rte_eth_ntuple_filter ntuple_filter;
3025 : : struct rte_eth_ethertype_filter ethertype_filter;
3026 : : struct rte_eth_syn_filter syn_filter;
3027 : : struct ixgbe_l2_tunnel_conf l2_tn_filter;
3028 : : struct ixgbe_fdir_rule fdir_rule;
3029 : : struct ixgbe_rte_flow_rss_conf rss_conf;
3030 : : int ret;
3031 : :
3032 : : /**
3033 : : * Special case for flow action type RTE_FLOW_ACTION_TYPE_SECURITY
3034 : : */
3035 : 0 : ret = ixgbe_parse_security_filter(dev, attr, pattern, actions, error);
3036 [ # # ]: 0 : if (!ret)
3037 : : return 0;
3038 : :
3039 : : memset(&ntuple_filter, 0, sizeof(struct rte_eth_ntuple_filter));
3040 : 0 : ret = ixgbe_parse_ntuple_filter(dev, attr, pattern,
3041 : : actions, &ntuple_filter, error);
3042 [ # # ]: 0 : if (!ret)
3043 : : return 0;
3044 : :
3045 : : memset(ðertype_filter, 0, sizeof(struct rte_eth_ethertype_filter));
3046 : 0 : ret = ixgbe_parse_ethertype_filter(dev, attr, pattern,
3047 : : actions, ðertype_filter, error);
3048 [ # # ]: 0 : if (!ret)
3049 : : return 0;
3050 : :
3051 : : memset(&syn_filter, 0, sizeof(struct rte_eth_syn_filter));
3052 : 0 : ret = ixgbe_parse_syn_filter(dev, attr, pattern,
3053 : : actions, &syn_filter, error);
3054 [ # # ]: 0 : if (!ret)
3055 : : return 0;
3056 : :
3057 : : memset(&fdir_rule, 0, sizeof(struct ixgbe_fdir_rule));
3058 : 0 : ret = ixgbe_parse_fdir_filter(dev, attr, pattern,
3059 : : actions, &fdir_rule, error);
3060 [ # # ]: 0 : if (!ret)
3061 : : return 0;
3062 : :
3063 : : memset(&l2_tn_filter, 0, sizeof(struct ixgbe_l2_tunnel_conf));
3064 : 0 : ret = ixgbe_parse_l2_tn_filter(dev, attr, pattern,
3065 : : actions, &l2_tn_filter, error);
3066 [ # # ]: 0 : if (!ret)
3067 : : return 0;
3068 : :
3069 : : memset(&rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
3070 : 0 : ret = ixgbe_parse_rss_filter(dev, attr,
3071 : : actions, &rss_conf, error);
3072 : :
3073 : 0 : return ret;
3074 : : }
3075 : :
3076 : : /* Destroy a flow rule on ixgbe. */
3077 : : static int
3078 : 0 : ixgbe_flow_destroy(struct rte_eth_dev *dev,
3079 : : struct rte_flow *flow,
3080 : : struct rte_flow_error *error)
3081 : : {
3082 : : int ret;
3083 : 0 : struct ixgbe_adapter *adapter =
3084 : 0 : IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
3085 : : struct rte_flow *pmd_flow = flow;
3086 : 0 : enum rte_filter_type filter_type = pmd_flow->filter_type;
3087 : : struct rte_eth_ntuple_filter ntuple_filter;
3088 : : struct rte_eth_ethertype_filter ethertype_filter;
3089 : : struct rte_eth_syn_filter syn_filter;
3090 : : struct ixgbe_fdir_rule fdir_rule;
3091 : : struct ixgbe_l2_tunnel_conf l2_tn_filter;
3092 : : struct ixgbe_ntuple_filter_ele *ntuple_filter_ptr;
3093 : : struct ixgbe_ethertype_filter_ele *ethertype_filter_ptr;
3094 : : struct ixgbe_eth_syn_filter_ele *syn_filter_ptr;
3095 : : struct ixgbe_eth_l2_tunnel_conf_ele *l2_tn_filter_ptr;
3096 : : struct ixgbe_fdir_rule_ele *fdir_rule_ptr;
3097 : : struct ixgbe_filter_ele_base *flow_mem_base;
3098 : : struct ixgbe_hw_fdir_info *fdir_info =
3099 : : IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter);
3100 : 0 : struct rte_eth_fdir_conf *fdir_conf = IXGBE_DEV_FDIR_CONF(dev);
3101 : : struct ixgbe_rss_conf_ele *rss_filter_ptr;
3102 : :
3103 : : /* Validate ownership before touching HW/SW state. */
3104 [ # # ]: 0 : TAILQ_FOREACH(flow_mem_base, &adapter->flow_list, entries) {
3105 : : struct ixgbe_flow_mem *ixgbe_flow_mem_ptr =
3106 : : (struct ixgbe_flow_mem *)flow_mem_base;
3107 : :
3108 [ # # ]: 0 : if (ixgbe_flow_mem_ptr->flow == pmd_flow)
3109 : : break;
3110 : : }
3111 [ # # ]: 0 : if (flow_mem_base == NULL) {
3112 : 0 : return rte_flow_error_set(error, EINVAL,
3113 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
3114 : : "Flow not found for this port");
3115 : : }
3116 : :
3117 : : /* Special case for SECURITY flows */
3118 [ # # ]: 0 : if (flow->is_security) {
3119 : : ret = 0;
3120 : 0 : goto free;
3121 : : }
3122 : :
3123 [ # # # # : 0 : switch (filter_type) {
# # # ]
3124 : 0 : case RTE_ETH_FILTER_NTUPLE:
3125 : 0 : ntuple_filter_ptr = (struct ixgbe_ntuple_filter_ele *)
3126 : : pmd_flow->rule;
3127 : : memcpy(&ntuple_filter,
3128 : 0 : &ntuple_filter_ptr->filter_info,
3129 : : sizeof(struct rte_eth_ntuple_filter));
3130 : 0 : ret = ixgbe_add_del_ntuple_filter(adapter, &ntuple_filter, FALSE);
3131 [ # # ]: 0 : if (!ret)
3132 : 0 : rte_free(ntuple_filter_ptr);
3133 : : break;
3134 : 0 : case RTE_ETH_FILTER_ETHERTYPE:
3135 : 0 : ethertype_filter_ptr = (struct ixgbe_ethertype_filter_ele *)
3136 : : pmd_flow->rule;
3137 : : memcpy(ðertype_filter,
3138 : 0 : ðertype_filter_ptr->filter_info,
3139 : : sizeof(struct rte_eth_ethertype_filter));
3140 : 0 : ret = ixgbe_add_del_ethertype_filter(adapter,
3141 : : ðertype_filter, FALSE);
3142 [ # # ]: 0 : if (!ret)
3143 : 0 : rte_free(ethertype_filter_ptr);
3144 : : break;
3145 : 0 : case RTE_ETH_FILTER_SYN:
3146 : 0 : syn_filter_ptr = (struct ixgbe_eth_syn_filter_ele *)
3147 : : pmd_flow->rule;
3148 : : memcpy(&syn_filter,
3149 : : &syn_filter_ptr->filter_info,
3150 : : sizeof(struct rte_eth_syn_filter));
3151 : 0 : ret = ixgbe_syn_filter_set(adapter, &syn_filter, FALSE);
3152 [ # # ]: 0 : if (!ret)
3153 : 0 : rte_free(syn_filter_ptr);
3154 : : break;
3155 : 0 : case RTE_ETH_FILTER_FDIR:
3156 : 0 : fdir_rule_ptr = (struct ixgbe_fdir_rule_ele *)pmd_flow->rule;
3157 : : memcpy(&fdir_rule,
3158 : 0 : &fdir_rule_ptr->filter_info,
3159 : : sizeof(struct ixgbe_fdir_rule));
3160 : 0 : ret = ixgbe_fdir_filter_program(adapter, fdir_conf, &fdir_rule, TRUE, FALSE);
3161 [ # # ]: 0 : if (!ret) {
3162 : 0 : rte_free(fdir_rule_ptr);
3163 [ # # # # ]: 0 : if (fdir_info->n_flows > 0 && --(fdir_info->n_flows) == 0) {
3164 : 0 : fdir_info->mask_added = false;
3165 : 0 : fdir_info->mask = (struct ixgbe_hw_fdir_mask){0};
3166 : 0 : fdir_info->flex_bytes_offset = 0;
3167 : 0 : fdir_conf->mode = RTE_FDIR_MODE_NONE;
3168 : : }
3169 : : }
3170 : : break;
3171 : 0 : case RTE_ETH_FILTER_L2_TUNNEL:
3172 : 0 : l2_tn_filter_ptr = (struct ixgbe_eth_l2_tunnel_conf_ele *)
3173 : : pmd_flow->rule;
3174 : 0 : memcpy(&l2_tn_filter, &l2_tn_filter_ptr->filter_info,
3175 : : sizeof(struct ixgbe_l2_tunnel_conf));
3176 : 0 : ret = ixgbe_dev_l2_tunnel_filter_del(adapter, &l2_tn_filter);
3177 [ # # ]: 0 : if (!ret)
3178 : 0 : rte_free(l2_tn_filter_ptr);
3179 : : break;
3180 : 0 : case RTE_ETH_FILTER_HASH:
3181 : 0 : rss_filter_ptr = (struct ixgbe_rss_conf_ele *)
3182 : : pmd_flow->rule;
3183 : 0 : ret = ixgbe_config_rss_filter(adapter,
3184 : : &rss_filter_ptr->filter_info, FALSE);
3185 [ # # ]: 0 : if (!ret)
3186 : 0 : rte_free(rss_filter_ptr);
3187 : : break;
3188 : 0 : default:
3189 : 0 : PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
3190 : : filter_type);
3191 : : ret = -EINVAL;
3192 : : break;
3193 : : }
3194 : :
3195 [ # # ]: 0 : if (ret) {
3196 : 0 : rte_flow_error_set(error, EINVAL,
3197 : : RTE_FLOW_ERROR_TYPE_HANDLE,
3198 : : NULL, "Failed to destroy flow");
3199 : 0 : return ret;
3200 : : }
3201 : :
3202 : 0 : free:
3203 [ # # ]: 0 : TAILQ_REMOVE(&adapter->flow_list, flow_mem_base, entries);
3204 : 0 : rte_free(flow_mem_base);
3205 : 0 : rte_free(flow);
3206 : :
3207 : 0 : return ret;
3208 : : }
3209 : :
3210 : : /* Destroy all flow rules associated with a port on ixgbe. */
3211 : : static int
3212 : 0 : ixgbe_flow_flush(struct rte_eth_dev *dev,
3213 : : struct rte_flow_error *error)
3214 : : {
3215 : : int ret = 0;
3216 : :
3217 : 0 : ixgbe_clear_all_ntuple_filter(dev);
3218 : 0 : ixgbe_clear_all_ethertype_filter(dev);
3219 : 0 : ixgbe_clear_syn_filter(dev);
3220 : :
3221 : 0 : ret = ixgbe_clear_all_fdir_filter(dev);
3222 [ # # ]: 0 : if (ret < 0) {
3223 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
3224 : : NULL, "Failed to flush rule");
3225 : 0 : return ret;
3226 : : }
3227 : :
3228 : 0 : ret = ixgbe_clear_all_l2_tn_filter(dev);
3229 [ # # ]: 0 : if (ret < 0) {
3230 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
3231 : : NULL, "Failed to flush rule");
3232 : 0 : return ret;
3233 : : }
3234 : :
3235 : : ixgbe_clear_rss_filter(dev);
3236 : :
3237 : 0 : ixgbe_filterlist_flush(dev);
3238 : :
3239 : 0 : return 0;
3240 : : }
3241 : :
3242 : : #define IXGBE_FLOW_DUMP_CHUNK_BYTES 32
3243 : :
3244 : : static const char *
3245 : : ixgbe_flow_rule_engine_name(const struct rte_flow *flow)
3246 : : {
3247 [ # # ]: 0 : if (flow->is_security)
3248 : : return "security";
3249 : :
3250 [ # # # # : 0 : switch (flow->filter_type) {
# # # ]
3251 : : case RTE_ETH_FILTER_NTUPLE:
3252 : : return "ntuple";
3253 : 0 : case RTE_ETH_FILTER_ETHERTYPE:
3254 : 0 : return "ethertype";
3255 : 0 : case RTE_ETH_FILTER_SYN:
3256 : 0 : return "syn";
3257 : 0 : case RTE_ETH_FILTER_FDIR:
3258 : 0 : return "fdir";
3259 : 0 : case RTE_ETH_FILTER_L2_TUNNEL:
3260 : 0 : return "l2_tunnel";
3261 : 0 : case RTE_ETH_FILTER_HASH:
3262 : 0 : return "hash";
3263 : 0 : default:
3264 : 0 : return "unknown";
3265 : : }
3266 : : }
3267 : :
3268 : : static size_t
3269 : : ixgbe_flow_rule_size(const struct rte_flow *flow)
3270 : : {
3271 [ # # ]: 0 : if (flow->is_security)
3272 : : return 0;
3273 : :
3274 [ # # ]: 0 : switch (flow->filter_type) {
3275 : : case RTE_ETH_FILTER_NTUPLE:
3276 : : return sizeof(struct rte_eth_ntuple_filter);
3277 : : case RTE_ETH_FILTER_ETHERTYPE:
3278 : : return sizeof(struct rte_eth_ethertype_filter);
3279 : : case RTE_ETH_FILTER_SYN:
3280 : : return sizeof(struct rte_eth_syn_filter);
3281 : : case RTE_ETH_FILTER_FDIR:
3282 : : return sizeof(struct ixgbe_fdir_rule);
3283 : : case RTE_ETH_FILTER_L2_TUNNEL:
3284 : : return sizeof(struct ixgbe_l2_tunnel_conf);
3285 : : case RTE_ETH_FILTER_HASH:
3286 : : return sizeof(struct ixgbe_rte_flow_rss_conf);
3287 : : default:
3288 : : return 0;
3289 : : }
3290 : : }
3291 : :
3292 : : static const void *
3293 : : ixgbe_flow_rule_data(const struct rte_flow *flow)
3294 : : {
3295 [ # # ]: 0 : if (flow->is_security || flow->rule == NULL)
3296 : : return NULL;
3297 : :
3298 : 0 : return RTE_PTR_ADD(flow->rule, sizeof(struct ixgbe_filter_ele_base));
3299 : : }
3300 : :
3301 : : static void
3302 : 0 : ixgbe_flow_dump_blob(FILE *file, const char *engine,
3303 : : const void *data, size_t data_len)
3304 : : {
3305 : : const uint8_t *raw = (const uint8_t *)data;
3306 : 0 : const size_t nchunks =
3307 : 0 : (data_len + IXGBE_FLOW_DUMP_CHUNK_BYTES - 1) /
3308 : : IXGBE_FLOW_DUMP_CHUNK_BYTES;
3309 : : char title[64];
3310 : : size_t ci;
3311 : :
3312 : : fprintf(file, "FLOW DUMP: driver=ixgbe engine=%s\n", engine);
3313 : : fprintf(file, "FLOW DUMP: DATA size=%zu chunks=%zu chunk_bytes=%d\n",
3314 : : data_len, nchunks, IXGBE_FLOW_DUMP_CHUNK_BYTES);
3315 : :
3316 [ # # ]: 0 : for (ci = 0; ci < nchunks; ci++) {
3317 : 0 : const size_t off = ci * IXGBE_FLOW_DUMP_CHUNK_BYTES;
3318 : : const size_t clen =
3319 : 0 : RTE_MIN((size_t)IXGBE_FLOW_DUMP_CHUNK_BYTES, data_len - off);
3320 : :
3321 : 0 : snprintf(title, sizeof(title), "FLOW DUMP: chunk %03zu/%03zu",
3322 : : ci + 1, nchunks);
3323 : 0 : rte_memdump(file, title, raw + off, clen);
3324 : : }
3325 : 0 : }
3326 : :
3327 : : static int
3328 : 0 : ixgbe_flow_dev_dump(struct rte_eth_dev *dev,
3329 : : struct rte_flow *flow,
3330 : : FILE *file,
3331 : : struct rte_flow_error *error)
3332 : : {
3333 : 0 : struct ixgbe_adapter *ad = IXGBE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
3334 : : struct ixgbe_filter_ele_base *flow_mem_base;
3335 : : bool found = false;
3336 : :
3337 [ # # ]: 0 : TAILQ_FOREACH(flow_mem_base, &ad->flow_list, entries) {
3338 : : struct ixgbe_flow_mem *ixgbe_flow_mem_ptr =
3339 : : (struct ixgbe_flow_mem *)flow_mem_base;
3340 : 0 : struct rte_flow *p_flow = ixgbe_flow_mem_ptr->flow;
3341 : : const void *rule_data = NULL;
3342 : : const char *engine_name;
3343 : : size_t rule_size = 0;
3344 : :
3345 [ # # ]: 0 : if (flow != NULL && p_flow != flow)
3346 : 0 : continue;
3347 : :
3348 : : found = true;
3349 [ # # ]: 0 : if (p_flow->rule != NULL) {
3350 : : rule_data = ixgbe_flow_rule_data(p_flow);
3351 : : rule_size = ixgbe_flow_rule_size(p_flow);
3352 : : }
3353 : : engine_name = ixgbe_flow_rule_engine_name(p_flow);
3354 : 0 : ixgbe_flow_dump_blob(file, engine_name,
3355 : : rule_data, rule_size);
3356 : : }
3357 : :
3358 [ # # ]: 0 : if (flow != NULL && !found)
3359 : 0 : return rte_flow_error_set(error, ENOENT,
3360 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
3361 : : "Flow not found");
3362 : :
3363 : : return 0;
3364 : : }
3365 : :
3366 : : const struct rte_flow_ops ixgbe_flow_ops = {
3367 : : .validate = ixgbe_flow_validate,
3368 : : .create = ixgbe_flow_create,
3369 : : .destroy = ixgbe_flow_destroy,
3370 : : .flush = ixgbe_flow_flush,
3371 : : .dev_dump = ixgbe_flow_dev_dump,
3372 : : };
|