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