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