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