xref: /dpdk/drivers/net/sfc/sfc_flow.c (revision 0857b942113874c69dc3db5df11a828ee3cc9b6b)
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 != NULL &&
841 	       pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
842 		item = sfc_flow_get_item(pattern->type);
843 		if (item == NULL) {
844 			rte_flow_error_set(error, ENOTSUP,
845 					   RTE_FLOW_ERROR_TYPE_ITEM, pattern,
846 					   "Unsupported pattern item");
847 			return -rte_errno;
848 		}
849 
850 		/*
851 		 * Omitting one or several protocol layers at the beginning
852 		 * of pattern is supported
853 		 */
854 		if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
855 		    prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
856 		    item->prev_layer != prev_layer) {
857 			rte_flow_error_set(error, ENOTSUP,
858 					   RTE_FLOW_ERROR_TYPE_ITEM, pattern,
859 					   "Unexpected sequence of pattern items");
860 			return -rte_errno;
861 		}
862 
863 		rc = item->parse(pattern, &flow->spec, error);
864 		if (rc != 0)
865 			return rc;
866 
867 		if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
868 			prev_layer = item->layer;
869 	}
870 
871 	if (pattern == NULL) {
872 		rte_flow_error_set(error, EINVAL,
873 				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
874 				   "NULL item");
875 		return -rte_errno;
876 	}
877 
878 	return 0;
879 }
880 
881 static int
882 sfc_flow_parse_queue(struct sfc_adapter *sa,
883 		     const struct rte_flow_action_queue *queue,
884 		     struct rte_flow *flow)
885 {
886 	struct sfc_rxq *rxq;
887 
888 	if (queue->index >= sa->rxq_count)
889 		return -EINVAL;
890 
891 	rxq = sa->rxq_info[queue->index].rxq;
892 	flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index;
893 
894 	return 0;
895 }
896 
897 static int
898 sfc_flow_parse_actions(struct sfc_adapter *sa,
899 		       const struct rte_flow_action actions[],
900 		       struct rte_flow *flow,
901 		       struct rte_flow_error *error)
902 {
903 	int rc;
904 	boolean_t is_specified = B_FALSE;
905 
906 	if (actions == NULL) {
907 		rte_flow_error_set(error, EINVAL,
908 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
909 				   "NULL actions");
910 		return -rte_errno;
911 	}
912 
913 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
914 		switch (actions->type) {
915 		case RTE_FLOW_ACTION_TYPE_VOID:
916 			break;
917 
918 		case RTE_FLOW_ACTION_TYPE_QUEUE:
919 			rc = sfc_flow_parse_queue(sa, actions->conf, flow);
920 			if (rc != 0) {
921 				rte_flow_error_set(error, EINVAL,
922 					RTE_FLOW_ERROR_TYPE_ACTION, actions,
923 					"Bad QUEUE action");
924 				return -rte_errno;
925 			}
926 
927 			is_specified = B_TRUE;
928 			break;
929 
930 		default:
931 			rte_flow_error_set(error, ENOTSUP,
932 					   RTE_FLOW_ERROR_TYPE_ACTION, actions,
933 					   "Action is not supported");
934 			return -rte_errno;
935 		}
936 	}
937 
938 	if (!is_specified) {
939 		rte_flow_error_set(error, EINVAL,
940 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
941 				   "Action is unspecified");
942 		return -rte_errno;
943 	}
944 
945 	return 0;
946 }
947 
948 static int
949 sfc_flow_parse(struct rte_eth_dev *dev,
950 	       const struct rte_flow_attr *attr,
951 	       const struct rte_flow_item pattern[],
952 	       const struct rte_flow_action actions[],
953 	       struct rte_flow *flow,
954 	       struct rte_flow_error *error)
955 {
956 	struct sfc_adapter *sa = dev->data->dev_private;
957 	int rc;
958 
959 	memset(&flow->spec, 0, sizeof(flow->spec));
960 
961 	rc = sfc_flow_parse_attr(attr, flow, error);
962 	if (rc != 0)
963 		goto fail_bad_value;
964 
965 	rc = sfc_flow_parse_pattern(pattern, flow, error);
966 	if (rc != 0)
967 		goto fail_bad_value;
968 
969 	rc = sfc_flow_parse_actions(sa, actions, flow, error);
970 	if (rc != 0)
971 		goto fail_bad_value;
972 
973 	if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) {
974 		rte_flow_error_set(error, ENOTSUP,
975 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
976 				   "Flow rule pattern is not supported");
977 		return -rte_errno;
978 	}
979 
980 fail_bad_value:
981 	return rc;
982 }
983 
984 static int
985 sfc_flow_validate(struct rte_eth_dev *dev,
986 		  const struct rte_flow_attr *attr,
987 		  const struct rte_flow_item pattern[],
988 		  const struct rte_flow_action actions[],
989 		  struct rte_flow_error *error)
990 {
991 	struct rte_flow flow;
992 
993 	return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
994 }
995 
996 static struct rte_flow *
997 sfc_flow_create(struct rte_eth_dev *dev,
998 		const struct rte_flow_attr *attr,
999 		const struct rte_flow_item pattern[],
1000 		const struct rte_flow_action actions[],
1001 		struct rte_flow_error *error)
1002 {
1003 	struct sfc_adapter *sa = dev->data->dev_private;
1004 	struct rte_flow *flow = NULL;
1005 	int rc;
1006 
1007 	flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
1008 	if (flow == NULL) {
1009 		rte_flow_error_set(error, ENOMEM,
1010 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1011 				   "Failed to allocate memory");
1012 		goto fail_no_mem;
1013 	}
1014 
1015 	rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1016 	if (rc != 0)
1017 		goto fail_bad_value;
1018 
1019 	TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1020 
1021 	sfc_adapter_lock(sa);
1022 
1023 	if (sa->state == SFC_ADAPTER_STARTED) {
1024 		rc = efx_filter_insert(sa->nic, &flow->spec);
1025 		if (rc != 0) {
1026 			rte_flow_error_set(error, rc,
1027 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1028 				"Failed to insert filter");
1029 			goto fail_filter_insert;
1030 		}
1031 	}
1032 
1033 	sfc_adapter_unlock(sa);
1034 
1035 	return flow;
1036 
1037 fail_filter_insert:
1038 	TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1039 
1040 fail_bad_value:
1041 	rte_free(flow);
1042 	sfc_adapter_unlock(sa);
1043 
1044 fail_no_mem:
1045 	return NULL;
1046 }
1047 
1048 static int
1049 sfc_flow_remove(struct sfc_adapter *sa,
1050 		struct rte_flow *flow,
1051 		struct rte_flow_error *error)
1052 {
1053 	int rc = 0;
1054 
1055 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1056 
1057 	if (sa->state == SFC_ADAPTER_STARTED) {
1058 		rc = efx_filter_remove(sa->nic, &flow->spec);
1059 		if (rc != 0)
1060 			rte_flow_error_set(error, rc,
1061 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1062 				"Failed to destroy flow rule");
1063 	}
1064 
1065 	TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1066 	rte_free(flow);
1067 
1068 	return rc;
1069 }
1070 
1071 static int
1072 sfc_flow_destroy(struct rte_eth_dev *dev,
1073 		 struct rte_flow *flow,
1074 		 struct rte_flow_error *error)
1075 {
1076 	struct sfc_adapter *sa = dev->data->dev_private;
1077 	struct rte_flow *flow_ptr;
1078 	int rc = EINVAL;
1079 
1080 	sfc_adapter_lock(sa);
1081 
1082 	TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1083 		if (flow_ptr == flow)
1084 			rc = 0;
1085 	}
1086 	if (rc != 0) {
1087 		rte_flow_error_set(error, rc,
1088 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1089 				   "Failed to find flow rule to destroy");
1090 		goto fail_bad_value;
1091 	}
1092 
1093 	rc = sfc_flow_remove(sa, flow, error);
1094 
1095 fail_bad_value:
1096 	sfc_adapter_unlock(sa);
1097 
1098 	return -rc;
1099 }
1100 
1101 static int
1102 sfc_flow_flush(struct rte_eth_dev *dev,
1103 	       struct rte_flow_error *error)
1104 {
1105 	struct sfc_adapter *sa = dev->data->dev_private;
1106 	struct rte_flow *flow;
1107 	int rc = 0;
1108 	int ret = 0;
1109 
1110 	sfc_adapter_lock(sa);
1111 
1112 	while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1113 		rc = sfc_flow_remove(sa, flow, error);
1114 		if (rc != 0)
1115 			ret = rc;
1116 	}
1117 
1118 	sfc_adapter_unlock(sa);
1119 
1120 	return -ret;
1121 }
1122 
1123 const struct rte_flow_ops sfc_flow_ops = {
1124 	.validate = sfc_flow_validate,
1125 	.create = sfc_flow_create,
1126 	.destroy = sfc_flow_destroy,
1127 	.flush = sfc_flow_flush,
1128 	.query = NULL,
1129 };
1130 
1131 void
1132 sfc_flow_init(struct sfc_adapter *sa)
1133 {
1134 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1135 
1136 	TAILQ_INIT(&sa->filter.flow_list);
1137 }
1138 
1139 void
1140 sfc_flow_fini(struct sfc_adapter *sa)
1141 {
1142 	struct rte_flow *flow;
1143 
1144 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1145 
1146 	while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1147 		TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1148 		rte_free(flow);
1149 	}
1150 }
1151 
1152 void
1153 sfc_flow_stop(struct sfc_adapter *sa)
1154 {
1155 	struct rte_flow *flow;
1156 
1157 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1158 
1159 	TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
1160 		efx_filter_remove(sa->nic, &flow->spec);
1161 }
1162 
1163 int
1164 sfc_flow_start(struct sfc_adapter *sa)
1165 {
1166 	struct rte_flow *flow;
1167 	int rc = 0;
1168 
1169 	sfc_log_init(sa, "entry");
1170 
1171 	SFC_ASSERT(sfc_adapter_is_locked(sa));
1172 
1173 	TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
1174 		rc = efx_filter_insert(sa->nic, &flow->spec);
1175 		if (rc != 0)
1176 			goto fail_bad_flow;
1177 	}
1178 
1179 	sfc_log_init(sa, "done");
1180 
1181 fail_bad_flow:
1182 	return rc;
1183 }
1184