xref: /dpdk/drivers/net/sfc/sfc_flow.c (revision e01f84f42cad7cb05edbf9ddea98ce8c1a519814)
1 /*-
2  * Copyright (c) 2017 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * This software was jointly developed between OKTET Labs (under contract
6  * for Solarflare) and Solarflare Communications, Inc.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <rte_tailq.h>
31 #include <rte_common.h>
32 #include <rte_ethdev.h>
33 #include <rte_eth_ctrl.h>
34 #include <rte_ether.h>
35 #include <rte_flow.h>
36 #include <rte_flow_driver.h>
37 
38 #include "efx.h"
39 
40 #include "sfc.h"
41 #include "sfc_rx.h"
42 #include "sfc_filter.h"
43 #include "sfc_flow.h"
44 #include "sfc_log.h"
45 
46 /*
47  * At now flow API is implemented in such a manner that each
48  * flow rule is converted to a hardware filter.
49  * All elements of flow rule (attributes, pattern items, actions)
50  * correspond to one or more fields in the efx_filter_spec_s structure
51  * that is responsible for the hardware filter.
52  */
53 
54 enum sfc_flow_item_layers {
55 	SFC_FLOW_ITEM_ANY_LAYER,
56 	SFC_FLOW_ITEM_START_LAYER,
57 	SFC_FLOW_ITEM_L2,
58 	SFC_FLOW_ITEM_L3,
59 	SFC_FLOW_ITEM_L4,
60 };
61 
62 typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item,
63 				  efx_filter_spec_t *spec,
64 				  struct rte_flow_error *error);
65 
66 struct sfc_flow_item {
67 	enum rte_flow_item_type type;		/* Type of item */
68 	enum sfc_flow_item_layers layer;	/* Layer of item */
69 	enum sfc_flow_item_layers prev_layer;	/* Previous layer of item */
70 	sfc_flow_item_parse *parse;		/* Parsing function */
71 };
72 
73 static sfc_flow_item_parse sfc_flow_parse_void;
74 static sfc_flow_item_parse sfc_flow_parse_eth;
75 static sfc_flow_item_parse sfc_flow_parse_vlan;
76 static sfc_flow_item_parse sfc_flow_parse_ipv4;
77 static sfc_flow_item_parse sfc_flow_parse_ipv6;
78 static sfc_flow_item_parse sfc_flow_parse_tcp;
79 static sfc_flow_item_parse sfc_flow_parse_udp;
80 
81 static boolean_t
82 sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
83 {
84 	uint8_t sum = 0;
85 	unsigned int i;
86 
87 	for (i = 0; i < size; i++)
88 		sum |= buf[i];
89 
90 	return (sum == 0) ? B_TRUE : B_FALSE;
91 }
92 
93 /*
94  * Validate item and prepare structures spec and mask for parsing
95  */
96 static int
97 sfc_flow_parse_init(const struct rte_flow_item *item,
98 		    const void **spec_ptr,
99 		    const void **mask_ptr,
100 		    const void *supp_mask,
101 		    const void *def_mask,
102 		    unsigned int size,
103 		    struct rte_flow_error *error)
104 {
105 	const uint8_t *spec;
106 	const uint8_t *mask;
107 	const uint8_t *last;
108 	uint8_t match;
109 	uint8_t supp;
110 	unsigned int i;
111 
112 	if (item == NULL) {
113 		rte_flow_error_set(error, EINVAL,
114 				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
115 				   "NULL item");
116 		return -rte_errno;
117 	}
118 
119 	if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
120 		rte_flow_error_set(error, EINVAL,
121 				   RTE_FLOW_ERROR_TYPE_ITEM, item,
122 				   "Mask or last is set without spec");
123 		return -rte_errno;
124 	}
125 
126 	/*
127 	 * If "mask" is not set, default mask is used,
128 	 * but if default mask is NULL, "mask" should be set
129 	 */
130 	if (item->mask == NULL) {
131 		if (def_mask == NULL) {
132 			rte_flow_error_set(error, EINVAL,
133 				RTE_FLOW_ERROR_TYPE_ITEM, NULL,
134 				"Mask should be specified");
135 			return -rte_errno;
136 		}
137 
138 		mask = (const uint8_t *)def_mask;
139 	} else {
140 		mask = (const uint8_t *)item->mask;
141 	}
142 
143 	spec = (const uint8_t *)item->spec;
144 	last = (const uint8_t *)item->last;
145 
146 	if (spec == NULL)
147 		goto exit;
148 
149 	/*
150 	 * If field values in "last" are either 0 or equal to the corresponding
151 	 * values in "spec" then they are ignored
152 	 */
153 	if (last != NULL &&
154 	    !sfc_flow_is_zero(last, size) &&
155 	    memcmp(last, spec, size) != 0) {
156 		rte_flow_error_set(error, ENOTSUP,
157 				   RTE_FLOW_ERROR_TYPE_ITEM, item,
158 				   "Ranging is not supported");
159 		return -rte_errno;
160 	}
161 
162 	if (supp_mask == NULL) {
163 		rte_flow_error_set(error, EINVAL,
164 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
165 			"Supported mask for item should be specified");
166 		return -rte_errno;
167 	}
168 
169 	/* Check that mask and spec not asks for more match than supp_mask */
170 	for (i = 0; i < size; i++) {
171 		match = spec[i] | mask[i];
172 		supp = ((const uint8_t *)supp_mask)[i];
173 
174 		if ((match | supp) != supp) {
175 			rte_flow_error_set(error, ENOTSUP,
176 					   RTE_FLOW_ERROR_TYPE_ITEM, item,
177 					   "Item's field is not supported");
178 			return -rte_errno;
179 		}
180 	}
181 
182 exit:
183 	*spec_ptr = spec;
184 	*mask_ptr = mask;
185 	return 0;
186 }
187 
188 /*
189  * Protocol parsers.
190  * Masking is not supported, so masks in items should be either
191  * full or empty (zeroed) and set only for supported fields which
192  * are specified in the supp_mask.
193  */
194 
195 static int
196 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
197 		    __rte_unused efx_filter_spec_t *efx_spec,
198 		    __rte_unused struct rte_flow_error *error)
199 {
200 	return 0;
201 }
202 
203 /**
204  * Convert Ethernet item to EFX filter specification.
205  *
206  * @param item[in]
207  *   Item specification. Only source and destination addresses and
208  *   Ethernet type fields are supported. If the mask is NULL, default
209  *   mask will be used. Ranging is not supported.
210  * @param efx_spec[in, out]
211  *   EFX filter specification to update.
212  * @param[out] error
213  *   Perform verbose error reporting if not NULL.
214  */
215 static int
216 sfc_flow_parse_eth(const struct rte_flow_item *item,
217 		   efx_filter_spec_t *efx_spec,
218 		   struct rte_flow_error *error)
219 {
220 	int rc;
221 	const struct rte_flow_item_eth *spec = NULL;
222 	const struct rte_flow_item_eth *mask = NULL;
223 	const struct rte_flow_item_eth supp_mask = {
224 		.dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
225 		.src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
226 		.type = 0xffff,
227 	};
228 
229 	rc = sfc_flow_parse_init(item,
230 				 (const void **)&spec,
231 				 (const void **)&mask,
232 				 &supp_mask,
233 				 &rte_flow_item_eth_mask,
234 				 sizeof(struct rte_flow_item_eth),
235 				 error);
236 	if (rc != 0)
237 		return rc;
238 
239 	/* If "spec" is not set, could be any Ethernet */
240 	if (spec == NULL)
241 		return 0;
242 
243 	if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) {
244 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
245 		rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes,
246 			   EFX_MAC_ADDR_LEN);
247 	} else if (!is_zero_ether_addr(&mask->dst)) {
248 		goto fail_bad_mask;
249 	}
250 
251 	if (is_same_ether_addr(&mask->src, &supp_mask.src)) {
252 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
253 		rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes,
254 			   EFX_MAC_ADDR_LEN);
255 	} else if (!is_zero_ether_addr(&mask->src)) {
256 		goto fail_bad_mask;
257 	}
258 
259 	/*
260 	 * Ether type is in big-endian byte order in item and
261 	 * in little-endian in efx_spec, so byte swap is used
262 	 */
263 	if (mask->type == supp_mask.type) {
264 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
265 		efx_spec->efs_ether_type = rte_bswap16(spec->type);
266 	} else if (mask->type != 0) {
267 		goto fail_bad_mask;
268 	}
269 
270 	return 0;
271 
272 fail_bad_mask:
273 	rte_flow_error_set(error, EINVAL,
274 			   RTE_FLOW_ERROR_TYPE_ITEM, item,
275 			   "Bad mask in the ETH pattern item");
276 	return -rte_errno;
277 }
278 
279 /**
280  * Convert VLAN item to EFX filter specification.
281  *
282  * @param item[in]
283  *   Item specification. Only VID field is supported.
284  *   The mask can not be NULL. Ranging is not supported.
285  * @param efx_spec[in, out]
286  *   EFX filter specification to update.
287  * @param[out] error
288  *   Perform verbose error reporting if not NULL.
289  */
290 static int
291 sfc_flow_parse_vlan(const struct rte_flow_item *item,
292 		    efx_filter_spec_t *efx_spec,
293 		    struct rte_flow_error *error)
294 {
295 	int rc;
296 	uint16_t vid;
297 	const struct rte_flow_item_vlan *spec = NULL;
298 	const struct rte_flow_item_vlan *mask = NULL;
299 	const struct rte_flow_item_vlan supp_mask = {
300 		.tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
301 	};
302 
303 	rc = sfc_flow_parse_init(item,
304 				 (const void **)&spec,
305 				 (const void **)&mask,
306 				 &supp_mask,
307 				 NULL,
308 				 sizeof(struct rte_flow_item_vlan),
309 				 error);
310 	if (rc != 0)
311 		return rc;
312 
313 	/*
314 	 * VID is in big-endian byte order in item and
315 	 * in little-endian in efx_spec, so byte swap is used.
316 	 * If two VLAN items are included, the first matches
317 	 * the outer tag and the next matches the inner tag.
318 	 */
319 	if (mask->tci == supp_mask.tci) {
320 		vid = rte_bswap16(spec->tci);
321 
322 		if (!(efx_spec->efs_match_flags &
323 		      EFX_FILTER_MATCH_OUTER_VID)) {
324 			efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
325 			efx_spec->efs_outer_vid = vid;
326 		} else if (!(efx_spec->efs_match_flags &
327 			     EFX_FILTER_MATCH_INNER_VID)) {
328 			efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
329 			efx_spec->efs_inner_vid = vid;
330 		} else {
331 			rte_flow_error_set(error, EINVAL,
332 					   RTE_FLOW_ERROR_TYPE_ITEM, item,
333 					   "More than two VLAN items");
334 			return -rte_errno;
335 		}
336 	} else {
337 		rte_flow_error_set(error, EINVAL,
338 				   RTE_FLOW_ERROR_TYPE_ITEM, item,
339 				   "VLAN ID in TCI match is required");
340 		return -rte_errno;
341 	}
342 
343 	return 0;
344 }
345 
346 /**
347  * Convert IPv4 item to EFX filter specification.
348  *
349  * @param item[in]
350  *   Item specification. Only source and destination addresses and
351  *   protocol fields are supported. If the mask is NULL, default
352  *   mask will be used. Ranging is not supported.
353  * @param efx_spec[in, out]
354  *   EFX filter specification to update.
355  * @param[out] error
356  *   Perform verbose error reporting if not NULL.
357  */
358 static int
359 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
360 		    efx_filter_spec_t *efx_spec,
361 		    struct rte_flow_error *error)
362 {
363 	int rc;
364 	const struct rte_flow_item_ipv4 *spec = NULL;
365 	const struct rte_flow_item_ipv4 *mask = NULL;
366 	const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
367 	const struct rte_flow_item_ipv4 supp_mask = {
368 		.hdr = {
369 			.src_addr = 0xffffffff,
370 			.dst_addr = 0xffffffff,
371 			.next_proto_id = 0xff,
372 		}
373 	};
374 
375 	rc = sfc_flow_parse_init(item,
376 				 (const void **)&spec,
377 				 (const void **)&mask,
378 				 &supp_mask,
379 				 &rte_flow_item_ipv4_mask,
380 				 sizeof(struct rte_flow_item_ipv4),
381 				 error);
382 	if (rc != 0)
383 		return rc;
384 
385 	/*
386 	 * Filtering by IPv4 source and destination addresses requires
387 	 * the appropriate ETHER_TYPE in hardware filters
388 	 */
389 	if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
390 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
391 		efx_spec->efs_ether_type = ether_type_ipv4;
392 	} else if (efx_spec->efs_ether_type != ether_type_ipv4) {
393 		rte_flow_error_set(error, EINVAL,
394 			RTE_FLOW_ERROR_TYPE_ITEM, item,
395 			"Ethertype in pattern with IPV4 item should be appropriate");
396 		return -rte_errno;
397 	}
398 
399 	if (spec == NULL)
400 		return 0;
401 
402 	/*
403 	 * IPv4 addresses are in big-endian byte order in item and in
404 	 * efx_spec
405 	 */
406 	if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
407 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
408 		efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
409 	} else if (mask->hdr.src_addr != 0) {
410 		goto fail_bad_mask;
411 	}
412 
413 	if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
414 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
415 		efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
416 	} else if (mask->hdr.dst_addr != 0) {
417 		goto fail_bad_mask;
418 	}
419 
420 	if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
421 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
422 		efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
423 	} else if (mask->hdr.next_proto_id != 0) {
424 		goto fail_bad_mask;
425 	}
426 
427 	return 0;
428 
429 fail_bad_mask:
430 	rte_flow_error_set(error, EINVAL,
431 			   RTE_FLOW_ERROR_TYPE_ITEM, item,
432 			   "Bad mask in the IPV4 pattern item");
433 	return -rte_errno;
434 }
435 
436 /**
437  * Convert IPv6 item to EFX filter specification.
438  *
439  * @param item[in]
440  *   Item specification. Only source and destination addresses and
441  *   next header fields are supported. If the mask is NULL, default
442  *   mask will be used. Ranging is not supported.
443  * @param efx_spec[in, out]
444  *   EFX filter specification to update.
445  * @param[out] error
446  *   Perform verbose error reporting if not NULL.
447  */
448 static int
449 sfc_flow_parse_ipv6(const struct rte_flow_item *item,
450 		    efx_filter_spec_t *efx_spec,
451 		    struct rte_flow_error *error)
452 {
453 	int rc;
454 	const struct rte_flow_item_ipv6 *spec = NULL;
455 	const struct rte_flow_item_ipv6 *mask = NULL;
456 	const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
457 	const struct rte_flow_item_ipv6 supp_mask = {
458 		.hdr = {
459 			.src_addr = { 0xff, 0xff, 0xff, 0xff,
460 				      0xff, 0xff, 0xff, 0xff,
461 				      0xff, 0xff, 0xff, 0xff,
462 				      0xff, 0xff, 0xff, 0xff },
463 			.dst_addr = { 0xff, 0xff, 0xff, 0xff,
464 				      0xff, 0xff, 0xff, 0xff,
465 				      0xff, 0xff, 0xff, 0xff,
466 				      0xff, 0xff, 0xff, 0xff },
467 			.proto = 0xff,
468 		}
469 	};
470 
471 	rc = sfc_flow_parse_init(item,
472 				 (const void **)&spec,
473 				 (const void **)&mask,
474 				 &supp_mask,
475 				 &rte_flow_item_ipv6_mask,
476 				 sizeof(struct rte_flow_item_ipv6),
477 				 error);
478 	if (rc != 0)
479 		return rc;
480 
481 	/*
482 	 * Filtering by IPv6 source and destination addresses requires
483 	 * the appropriate ETHER_TYPE in hardware filters
484 	 */
485 	if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
486 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
487 		efx_spec->efs_ether_type = ether_type_ipv6;
488 	} else if (efx_spec->efs_ether_type != ether_type_ipv6) {
489 		rte_flow_error_set(error, EINVAL,
490 			RTE_FLOW_ERROR_TYPE_ITEM, item,
491 			"Ethertype in pattern with IPV6 item should be appropriate");
492 		return -rte_errno;
493 	}
494 
495 	if (spec == NULL)
496 		return 0;
497 
498 	/*
499 	 * IPv6 addresses are in big-endian byte order in item and in
500 	 * efx_spec
501 	 */
502 	if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
503 		   sizeof(mask->hdr.src_addr)) == 0) {
504 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
505 
506 		RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
507 				 sizeof(spec->hdr.src_addr));
508 		rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
509 			   sizeof(efx_spec->efs_rem_host));
510 	} else if (!sfc_flow_is_zero(mask->hdr.src_addr,
511 				     sizeof(mask->hdr.src_addr))) {
512 		goto fail_bad_mask;
513 	}
514 
515 	if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
516 		   sizeof(mask->hdr.dst_addr)) == 0) {
517 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
518 
519 		RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
520 				 sizeof(spec->hdr.dst_addr));
521 		rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
522 			   sizeof(efx_spec->efs_loc_host));
523 	} else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
524 				     sizeof(mask->hdr.dst_addr))) {
525 		goto fail_bad_mask;
526 	}
527 
528 	if (mask->hdr.proto == supp_mask.hdr.proto) {
529 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
530 		efx_spec->efs_ip_proto = spec->hdr.proto;
531 	} else if (mask->hdr.proto != 0) {
532 		goto fail_bad_mask;
533 	}
534 
535 	return 0;
536 
537 fail_bad_mask:
538 	rte_flow_error_set(error, EINVAL,
539 			   RTE_FLOW_ERROR_TYPE_ITEM, item,
540 			   "Bad mask in the IPV6 pattern item");
541 	return -rte_errno;
542 }
543 
544 /**
545  * Convert TCP item to EFX filter specification.
546  *
547  * @param item[in]
548  *   Item specification. Only source and destination ports fields
549  *   are supported. If the mask is NULL, default mask will be used.
550  *   Ranging is not supported.
551  * @param efx_spec[in, out]
552  *   EFX filter specification to update.
553  * @param[out] error
554  *   Perform verbose error reporting if not NULL.
555  */
556 static int
557 sfc_flow_parse_tcp(const struct rte_flow_item *item,
558 		   efx_filter_spec_t *efx_spec,
559 		   struct rte_flow_error *error)
560 {
561 	int rc;
562 	const struct rte_flow_item_tcp *spec = NULL;
563 	const struct rte_flow_item_tcp *mask = NULL;
564 	const struct rte_flow_item_tcp supp_mask = {
565 		.hdr = {
566 			.src_port = 0xffff,
567 			.dst_port = 0xffff,
568 		}
569 	};
570 
571 	rc = sfc_flow_parse_init(item,
572 				 (const void **)&spec,
573 				 (const void **)&mask,
574 				 &supp_mask,
575 				 &rte_flow_item_tcp_mask,
576 				 sizeof(struct rte_flow_item_tcp),
577 				 error);
578 	if (rc != 0)
579 		return rc;
580 
581 	/*
582 	 * Filtering by TCP source and destination ports requires
583 	 * the appropriate IP_PROTO in hardware filters
584 	 */
585 	if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
586 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
587 		efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
588 	} else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
589 		rte_flow_error_set(error, EINVAL,
590 			RTE_FLOW_ERROR_TYPE_ITEM, item,
591 			"IP proto in pattern with TCP item should be appropriate");
592 		return -rte_errno;
593 	}
594 
595 	if (spec == NULL)
596 		return 0;
597 
598 	/*
599 	 * Source and destination ports are in big-endian byte order in item and
600 	 * in little-endian in efx_spec, so byte swap is used
601 	 */
602 	if (mask->hdr.src_port == supp_mask.hdr.src_port) {
603 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
604 		efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
605 	} else if (mask->hdr.src_port != 0) {
606 		goto fail_bad_mask;
607 	}
608 
609 	if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
610 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
611 		efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
612 	} else if (mask->hdr.dst_port != 0) {
613 		goto fail_bad_mask;
614 	}
615 
616 	return 0;
617 
618 fail_bad_mask:
619 	rte_flow_error_set(error, EINVAL,
620 			   RTE_FLOW_ERROR_TYPE_ITEM, item,
621 			   "Bad mask in the TCP pattern item");
622 	return -rte_errno;
623 }
624 
625 /**
626  * Convert UDP item to EFX filter specification.
627  *
628  * @param item[in]
629  *   Item specification. Only source and destination ports fields
630  *   are supported. If the mask is NULL, default mask will be used.
631  *   Ranging is not supported.
632  * @param efx_spec[in, out]
633  *   EFX filter specification to update.
634  * @param[out] error
635  *   Perform verbose error reporting if not NULL.
636  */
637 static int
638 sfc_flow_parse_udp(const struct rte_flow_item *item,
639 		   efx_filter_spec_t *efx_spec,
640 		   struct rte_flow_error *error)
641 {
642 	int rc;
643 	const struct rte_flow_item_udp *spec = NULL;
644 	const struct rte_flow_item_udp *mask = NULL;
645 	const struct rte_flow_item_udp supp_mask = {
646 		.hdr = {
647 			.src_port = 0xffff,
648 			.dst_port = 0xffff,
649 		}
650 	};
651 
652 	rc = sfc_flow_parse_init(item,
653 				 (const void **)&spec,
654 				 (const void **)&mask,
655 				 &supp_mask,
656 				 &rte_flow_item_udp_mask,
657 				 sizeof(struct rte_flow_item_udp),
658 				 error);
659 	if (rc != 0)
660 		return rc;
661 
662 	/*
663 	 * Filtering by UDP source and destination ports requires
664 	 * the appropriate IP_PROTO in hardware filters
665 	 */
666 	if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
667 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
668 		efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
669 	} else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
670 		rte_flow_error_set(error, EINVAL,
671 			RTE_FLOW_ERROR_TYPE_ITEM, item,
672 			"IP proto in pattern with UDP item should be appropriate");
673 		return -rte_errno;
674 	}
675 
676 	if (spec == NULL)
677 		return 0;
678 
679 	/*
680 	 * Source and destination ports are in big-endian byte order in item and
681 	 * in little-endian in efx_spec, so byte swap is used
682 	 */
683 	if (mask->hdr.src_port == supp_mask.hdr.src_port) {
684 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
685 		efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
686 	} else if (mask->hdr.src_port != 0) {
687 		goto fail_bad_mask;
688 	}
689 
690 	if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
691 		efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
692 		efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
693 	} else if (mask->hdr.dst_port != 0) {
694 		goto fail_bad_mask;
695 	}
696 
697 	return 0;
698 
699 fail_bad_mask:
700 	rte_flow_error_set(error, EINVAL,
701 			   RTE_FLOW_ERROR_TYPE_ITEM, item,
702 			   "Bad mask in the UDP pattern item");
703 	return -rte_errno;
704 }
705 
706 static const struct sfc_flow_item sfc_flow_items[] = {
707 	{
708 		.type = RTE_FLOW_ITEM_TYPE_VOID,
709 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
710 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
711 		.parse = sfc_flow_parse_void,
712 	},
713 	{
714 		.type = RTE_FLOW_ITEM_TYPE_ETH,
715 		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
716 		.layer = SFC_FLOW_ITEM_L2,
717 		.parse = sfc_flow_parse_eth,
718 	},
719 	{
720 		.type = RTE_FLOW_ITEM_TYPE_VLAN,
721 		.prev_layer = SFC_FLOW_ITEM_L2,
722 		.layer = SFC_FLOW_ITEM_L2,
723 		.parse = sfc_flow_parse_vlan,
724 	},
725 	{
726 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
727 		.prev_layer = SFC_FLOW_ITEM_L2,
728 		.layer = SFC_FLOW_ITEM_L3,
729 		.parse = sfc_flow_parse_ipv4,
730 	},
731 	{
732 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
733 		.prev_layer = SFC_FLOW_ITEM_L2,
734 		.layer = SFC_FLOW_ITEM_L3,
735 		.parse = sfc_flow_parse_ipv6,
736 	},
737 	{
738 		.type = RTE_FLOW_ITEM_TYPE_TCP,
739 		.prev_layer = SFC_FLOW_ITEM_L3,
740 		.layer = SFC_FLOW_ITEM_L4,
741 		.parse = sfc_flow_parse_tcp,
742 	},
743 	{
744 		.type = RTE_FLOW_ITEM_TYPE_UDP,
745 		.prev_layer = SFC_FLOW_ITEM_L3,
746 		.layer = SFC_FLOW_ITEM_L4,
747 		.parse = sfc_flow_parse_udp,
748 	},
749 };
750 
751 /*
752  * Protocol-independent flow API support
753  */
754 static int
755 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
756 		    struct rte_flow *flow,
757 		    struct rte_flow_error *error)
758 {
759 	if (attr == NULL) {
760 		rte_flow_error_set(error, EINVAL,
761 				   RTE_FLOW_ERROR_TYPE_ATTR, NULL,
762 				   "NULL attribute");
763 		return -rte_errno;
764 	}
765 	if (attr->group != 0) {
766 		rte_flow_error_set(error, ENOTSUP,
767 				   RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
768 				   "Groups are not supported");
769 		return -rte_errno;
770 	}
771 	if (attr->priority != 0) {
772 		rte_flow_error_set(error, ENOTSUP,
773 				   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
774 				   "Priorities are not supported");
775 		return -rte_errno;
776 	}
777 	if (attr->egress != 0) {
778 		rte_flow_error_set(error, ENOTSUP,
779 				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
780 				   "Egress is not supported");
781 		return -rte_errno;
782 	}
783 	if (attr->ingress == 0) {
784 		rte_flow_error_set(error, ENOTSUP,
785 				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
786 				   "Only ingress is supported");
787 		return -rte_errno;
788 	}
789 
790 	flow->spec.efs_flags |= EFX_FILTER_FLAG_RX;
791 	flow->spec.efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT;
792 
793 	return 0;
794 }
795 
796 /* Get item from array sfc_flow_items */
797 static const struct sfc_flow_item *
798 sfc_flow_get_item(enum rte_flow_item_type type)
799 {
800 	unsigned int i;
801 
802 	for (i = 0; i < RTE_DIM(sfc_flow_items); i++)
803 		if (sfc_flow_items[i].type == type)
804 			return &sfc_flow_items[i];
805 
806 	return NULL;
807 }
808 
809 static int
810 sfc_flow_parse_pattern(const struct rte_flow_item pattern[],
811 		       struct rte_flow *flow,
812 		       struct rte_flow_error *error)
813 {
814 	int rc;
815 	unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
816 	const struct sfc_flow_item *item;
817 
818 	if (pattern == NULL) {
819 		rte_flow_error_set(error, EINVAL,
820 				   RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
821 				   "NULL pattern");
822 		return -rte_errno;
823 	}
824 
825 	for (; pattern != NULL &&
826 	       pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
827 		item = sfc_flow_get_item(pattern->type);
828 		if (item == NULL) {
829 			rte_flow_error_set(error, ENOTSUP,
830 					   RTE_FLOW_ERROR_TYPE_ITEM, pattern,
831 					   "Unsupported pattern item");
832 			return -rte_errno;
833 		}
834 
835 		/*
836 		 * Omitting one or several protocol layers at the beginning
837 		 * of pattern is supported
838 		 */
839 		if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
840 		    prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
841 		    item->prev_layer != prev_layer) {
842 			rte_flow_error_set(error, ENOTSUP,
843 					   RTE_FLOW_ERROR_TYPE_ITEM, pattern,
844 					   "Unexpected sequence of pattern items");
845 			return -rte_errno;
846 		}
847 
848 		rc = item->parse(pattern, &flow->spec, error);
849 		if (rc != 0)
850 			return rc;
851 
852 		if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
853 			prev_layer = item->layer;
854 	}
855 
856 	if (pattern == NULL) {
857 		rte_flow_error_set(error, EINVAL,
858 				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
859 				   "NULL item");
860 		return -rte_errno;
861 	}
862 
863 	return 0;
864 }
865 
866 static int
867 sfc_flow_parse_queue(struct sfc_adapter *sa,
868 		     const struct rte_flow_action_queue *queue,
869 		     struct rte_flow *flow)
870 {
871 	struct sfc_rxq *rxq;
872 
873 	if (queue->index >= sa->rxq_count)
874 		return -EINVAL;
875 
876 	rxq = sa->rxq_info[queue->index].rxq;
877 	flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index;
878 
879 	return 0;
880 }
881 
882 static int
883 sfc_flow_parse_actions(struct sfc_adapter *sa,
884 		       const struct rte_flow_action actions[],
885 		       struct rte_flow *flow,
886 		       struct rte_flow_error *error)
887 {
888 	int rc;
889 	boolean_t is_specified = B_FALSE;
890 
891 	if (actions == NULL) {
892 		rte_flow_error_set(error, EINVAL,
893 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
894 				   "NULL actions");
895 		return -rte_errno;
896 	}
897 
898 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
899 		switch (actions->type) {
900 		case RTE_FLOW_ACTION_TYPE_VOID:
901 			break;
902 
903 		case RTE_FLOW_ACTION_TYPE_QUEUE:
904 			rc = sfc_flow_parse_queue(sa, actions->conf, flow);
905 			if (rc != 0) {
906 				rte_flow_error_set(error, EINVAL,
907 					RTE_FLOW_ERROR_TYPE_ACTION, actions,
908 					"Bad QUEUE action");
909 				return -rte_errno;
910 			}
911 
912 			is_specified = B_TRUE;
913 			break;
914 
915 		default:
916 			rte_flow_error_set(error, ENOTSUP,
917 					   RTE_FLOW_ERROR_TYPE_ACTION, actions,
918 					   "Action is not supported");
919 			return -rte_errno;
920 		}
921 	}
922 
923 	if (!is_specified) {
924 		rte_flow_error_set(error, EINVAL,
925 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
926 				   "Action is unspecified");
927 		return -rte_errno;
928 	}
929 
930 	return 0;
931 }
932 
933 static int
934 sfc_flow_parse(struct rte_eth_dev *dev,
935 	       const struct rte_flow_attr *attr,
936 	       const struct rte_flow_item pattern[],
937 	       const struct rte_flow_action actions[],
938 	       struct rte_flow *flow,
939 	       struct rte_flow_error *error)
940 {
941 	struct sfc_adapter *sa = dev->data->dev_private;
942 	int rc;
943 
944 	memset(&flow->spec, 0, sizeof(flow->spec));
945 
946 	rc = sfc_flow_parse_attr(attr, flow, error);
947 	if (rc != 0)
948 		goto fail_bad_value;
949 
950 	rc = sfc_flow_parse_pattern(pattern, flow, error);
951 	if (rc != 0)
952 		goto fail_bad_value;
953 
954 	rc = sfc_flow_parse_actions(sa, actions, flow, error);
955 	if (rc != 0)
956 		goto fail_bad_value;
957 
958 	if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) {
959 		rte_flow_error_set(error, ENOTSUP,
960 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
961 				   "Flow rule pattern is not supported");
962 		return -rte_errno;
963 	}
964 
965 fail_bad_value:
966 	return rc;
967 }
968 
969 static int
970 sfc_flow_validate(struct rte_eth_dev *dev,
971 		  const struct rte_flow_attr *attr,
972 		  const struct rte_flow_item pattern[],
973 		  const struct rte_flow_action actions[],
974 		  struct rte_flow_error *error)
975 {
976 	struct rte_flow flow;
977 
978 	return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
979 }
980 
981 static struct rte_flow *
982 sfc_flow_create(struct rte_eth_dev *dev,
983 		const struct rte_flow_attr *attr,
984 		const struct rte_flow_item pattern[],
985 		const struct rte_flow_action actions[],
986 		struct rte_flow_error *error)
987 {
988 	struct sfc_adapter *sa = dev->data->dev_private;
989 	struct rte_flow *flow = NULL;
990 	int rc;
991 
992 	flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
993 	if (flow == NULL) {
994 		rte_flow_error_set(error, ENOMEM,
995 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
996 				   "Failed to allocate memory");
997 		goto fail_no_mem;
998 	}
999 
1000 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1001 	if (rc != 0)
1002 		goto fail_bad_value;
1003 
1004 	TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1005 
1006 	sfc_adapter_lock(sa);
1007 
1008 	if (sa->state == SFC_ADAPTER_STARTED) {
1009 		rc = efx_filter_insert(sa->nic, &flow->spec);
1010 		if (rc != 0) {
1011 			rte_flow_error_set(error, rc,
1012 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1013 				"Failed to insert filter");
1014 			goto fail_filter_insert;
1015 		}
1016 	}
1017 
1018 	sfc_adapter_unlock(sa);
1019 
1020 	return flow;
1021 
1022 fail_filter_insert:
1023 	TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1024 
1025 fail_bad_value:
1026 	rte_free(flow);
1027 	sfc_adapter_unlock(sa);
1028 
1029 fail_no_mem:
1030 	return NULL;
1031 }
1032 
1033 static int
1034 sfc_flow_remove(struct sfc_adapter *sa,
1035 		struct rte_flow *flow,
1036 		struct rte_flow_error *error)
1037 {
1038 	int rc = 0;
1039 
1040 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1041 
1042 	if (sa->state == SFC_ADAPTER_STARTED) {
1043 		rc = efx_filter_remove(sa->nic, &flow->spec);
1044 		if (rc != 0)
1045 			rte_flow_error_set(error, rc,
1046 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1047 				"Failed to destroy flow rule");
1048 	}
1049 
1050 	TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1051 	rte_free(flow);
1052 
1053 	return rc;
1054 }
1055 
1056 static int
1057 sfc_flow_destroy(struct rte_eth_dev *dev,
1058 		 struct rte_flow *flow,
1059 		 struct rte_flow_error *error)
1060 {
1061 	struct sfc_adapter *sa = dev->data->dev_private;
1062 	struct rte_flow *flow_ptr;
1063 	int rc = EINVAL;
1064 
1065 	sfc_adapter_lock(sa);
1066 
1067 	TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1068 		if (flow_ptr == flow)
1069 			rc = 0;
1070 	}
1071 	if (rc != 0) {
1072 		rte_flow_error_set(error, rc,
1073 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1074 				   "Failed to find flow rule to destroy");
1075 		goto fail_bad_value;
1076 	}
1077 
1078 	rc = sfc_flow_remove(sa, flow, error);
1079 
1080 fail_bad_value:
1081 	sfc_adapter_unlock(sa);
1082 
1083 	return -rc;
1084 }
1085 
1086 static int
1087 sfc_flow_flush(struct rte_eth_dev *dev,
1088 	       struct rte_flow_error *error)
1089 {
1090 	struct sfc_adapter *sa = dev->data->dev_private;
1091 	struct rte_flow *flow;
1092 	int rc = 0;
1093 	int ret = 0;
1094 
1095 	sfc_adapter_lock(sa);
1096 
1097 	while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1098 		rc = sfc_flow_remove(sa, flow, error);
1099 		if (rc != 0)
1100 			ret = rc;
1101 	}
1102 
1103 	sfc_adapter_unlock(sa);
1104 
1105 	return -ret;
1106 }
1107 
1108 const struct rte_flow_ops sfc_flow_ops = {
1109 	.validate = sfc_flow_validate,
1110 	.create = sfc_flow_create,
1111 	.destroy = sfc_flow_destroy,
1112 	.flush = sfc_flow_flush,
1113 	.query = NULL,
1114 };
1115 
1116 void
1117 sfc_flow_init(struct sfc_adapter *sa)
1118 {
1119 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1120 
1121 	TAILQ_INIT(&sa->filter.flow_list);
1122 }
1123 
1124 void
1125 sfc_flow_fini(struct sfc_adapter *sa)
1126 {
1127 	struct rte_flow *flow;
1128 
1129 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1130 
1131 	while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1132 		TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1133 		rte_free(flow);
1134 	}
1135 }
1136 
1137 void
1138 sfc_flow_stop(struct sfc_adapter *sa)
1139 {
1140 	struct rte_flow *flow;
1141 
1142 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1143 
1144 	TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
1145 		efx_filter_remove(sa->nic, &flow->spec);
1146 }
1147 
1148 int
1149 sfc_flow_start(struct sfc_adapter *sa)
1150 {
1151 	struct rte_flow *flow;
1152 	int rc = 0;
1153 
1154 	sfc_log_init(sa, "entry");
1155 
1156 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1157 
1158 	TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
1159 		rc = efx_filter_insert(sa->nic, &flow->spec);
1160 		if (rc != 0)
1161 			goto fail_bad_flow;
1162 	}
1163 
1164 	sfc_log_init(sa, "done");
1165 
1166 fail_bad_flow:
1167 	return rc;
1168 }
1169