1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright (c) 2017-2018 Solarflare Communications Inc.
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
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>
16 #include <rte_flow_driver.h>
22 #include "sfc_filter.h"
27 * At now flow API is implemented in such a manner that each
28 * flow rule is converted to one or more hardware filters.
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 * If some required field is unset in the flow rule, then a handful
33 * of filter copies will be created to cover all possible values
37 enum sfc_flow_item_layers {
38 SFC_FLOW_ITEM_ANY_LAYER,
39 SFC_FLOW_ITEM_START_LAYER,
45 typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item,
46 efx_filter_spec_t *spec,
47 struct rte_flow_error *error);
49 struct sfc_flow_item {
50 enum rte_flow_item_type type; /* Type of item */
51 enum sfc_flow_item_layers layer; /* Layer of item */
52 enum sfc_flow_item_layers prev_layer; /* Previous layer of item */
53 sfc_flow_item_parse *parse; /* Parsing function */
56 static sfc_flow_item_parse sfc_flow_parse_void;
57 static sfc_flow_item_parse sfc_flow_parse_eth;
58 static sfc_flow_item_parse sfc_flow_parse_vlan;
59 static sfc_flow_item_parse sfc_flow_parse_ipv4;
60 static sfc_flow_item_parse sfc_flow_parse_ipv6;
61 static sfc_flow_item_parse sfc_flow_parse_tcp;
62 static sfc_flow_item_parse sfc_flow_parse_udp;
63 static sfc_flow_item_parse sfc_flow_parse_vxlan;
64 static sfc_flow_item_parse sfc_flow_parse_geneve;
65 static sfc_flow_item_parse sfc_flow_parse_nvgre;
67 typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec,
68 unsigned int filters_count_for_one_val,
69 struct rte_flow_error *error);
71 typedef boolean_t (sfc_flow_spec_check)(efx_filter_match_flags_t match,
72 efx_filter_spec_t *spec,
73 struct sfc_filter *filter);
75 struct sfc_flow_copy_flag {
76 /* EFX filter specification match flag */
77 efx_filter_match_flags_t flag;
78 /* Number of values of corresponding field */
79 unsigned int vals_count;
80 /* Function to set values in specifications */
81 sfc_flow_spec_set_vals *set_vals;
83 * Function to check that the specification is suitable
84 * for adding this match flag
86 sfc_flow_spec_check *spec_check;
89 static sfc_flow_spec_set_vals sfc_flow_set_ethertypes;
90 static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags;
91 static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags;
94 sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
99 for (i = 0; i < size; i++)
102 return (sum == 0) ? B_TRUE : B_FALSE;
106 * Validate item and prepare structures spec and mask for parsing
109 sfc_flow_parse_init(const struct rte_flow_item *item,
110 const void **spec_ptr,
111 const void **mask_ptr,
112 const void *supp_mask,
113 const void *def_mask,
115 struct rte_flow_error *error)
125 rte_flow_error_set(error, EINVAL,
126 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
131 if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
132 rte_flow_error_set(error, EINVAL,
133 RTE_FLOW_ERROR_TYPE_ITEM, item,
134 "Mask or last is set without spec");
139 * If "mask" is not set, default mask is used,
140 * but if default mask is NULL, "mask" should be set
142 if (item->mask == NULL) {
143 if (def_mask == NULL) {
144 rte_flow_error_set(error, EINVAL,
145 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
146 "Mask should be specified");
162 * If field values in "last" are either 0 or equal to the corresponding
163 * values in "spec" then they are ignored
166 !sfc_flow_is_zero(last, size) &&
167 memcmp(last, spec, size) != 0) {
168 rte_flow_error_set(error, ENOTSUP,
169 RTE_FLOW_ERROR_TYPE_ITEM, item,
170 "Ranging is not supported");
174 if (supp_mask == NULL) {
175 rte_flow_error_set(error, EINVAL,
176 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
177 "Supported mask for item should be specified");
181 /* Check that mask and spec not asks for more match than supp_mask */
182 for (i = 0; i < size; i++) {
183 match = spec[i] | mask[i];
184 supp = ((const uint8_t *)supp_mask)[i];
186 if ((match | supp) != supp) {
187 rte_flow_error_set(error, ENOTSUP,
188 RTE_FLOW_ERROR_TYPE_ITEM, item,
189 "Item's field is not supported");
202 * Masking is not supported, so masks in items should be either
203 * full or empty (zeroed) and set only for supported fields which
204 * are specified in the supp_mask.
208 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
209 __rte_unused efx_filter_spec_t *efx_spec,
210 __rte_unused struct rte_flow_error *error)
216 * Convert Ethernet item to EFX filter specification.
219 * Item specification. Outer frame specification may only comprise
220 * source/destination addresses and Ethertype field.
221 * Inner frame specification may contain destination address only.
222 * There is support for individual/group mask as well as for empty and full.
223 * If the mask is NULL, default mask will be used. Ranging is not supported.
224 * @param efx_spec[in, out]
225 * EFX filter specification to update.
227 * Perform verbose error reporting if not NULL.
230 sfc_flow_parse_eth(const struct rte_flow_item *item,
231 efx_filter_spec_t *efx_spec,
232 struct rte_flow_error *error)
235 const struct rte_flow_item_eth *spec = NULL;
236 const struct rte_flow_item_eth *mask = NULL;
237 const struct rte_flow_item_eth supp_mask = {
238 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
239 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
242 const struct rte_flow_item_eth ifrm_supp_mask = {
243 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
245 const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
246 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
248 const struct rte_flow_item_eth *supp_mask_p;
249 const struct rte_flow_item_eth *def_mask_p;
250 uint8_t *loc_mac = NULL;
251 boolean_t is_ifrm = (efx_spec->efs_encap_type !=
252 EFX_TUNNEL_PROTOCOL_NONE);
255 supp_mask_p = &ifrm_supp_mask;
256 def_mask_p = &ifrm_supp_mask;
257 loc_mac = efx_spec->efs_ifrm_loc_mac;
259 supp_mask_p = &supp_mask;
260 def_mask_p = &rte_flow_item_eth_mask;
261 loc_mac = efx_spec->efs_loc_mac;
264 rc = sfc_flow_parse_init(item,
265 (const void **)&spec,
266 (const void **)&mask,
267 supp_mask_p, def_mask_p,
268 sizeof(struct rte_flow_item_eth),
273 /* If "spec" is not set, could be any Ethernet */
277 if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) {
278 efx_spec->efs_match_flags |= is_ifrm ?
279 EFX_FILTER_MATCH_IFRM_LOC_MAC :
280 EFX_FILTER_MATCH_LOC_MAC;
281 rte_memcpy(loc_mac, spec->dst.addr_bytes,
283 } else if (memcmp(mask->dst.addr_bytes, ig_mask,
284 EFX_MAC_ADDR_LEN) == 0) {
285 if (is_unicast_ether_addr(&spec->dst))
286 efx_spec->efs_match_flags |= is_ifrm ?
287 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST :
288 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
290 efx_spec->efs_match_flags |= is_ifrm ?
291 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST :
292 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
293 } else if (!is_zero_ether_addr(&mask->dst)) {
298 * ifrm_supp_mask ensures that the source address and
299 * ethertype masks are equal to zero in inner frame,
300 * so these fields are filled in only for the outer frame
302 if (is_same_ether_addr(&mask->src, &supp_mask.src)) {
303 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
304 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes,
306 } else if (!is_zero_ether_addr(&mask->src)) {
311 * Ether type is in big-endian byte order in item and
312 * in little-endian in efx_spec, so byte swap is used
314 if (mask->type == supp_mask.type) {
315 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
316 efx_spec->efs_ether_type = rte_bswap16(spec->type);
317 } else if (mask->type != 0) {
324 rte_flow_error_set(error, EINVAL,
325 RTE_FLOW_ERROR_TYPE_ITEM, item,
326 "Bad mask in the ETH pattern item");
331 * Convert VLAN item to EFX filter specification.
334 * Item specification. Only VID field is supported.
335 * The mask can not be NULL. Ranging is not supported.
336 * @param efx_spec[in, out]
337 * EFX filter specification to update.
339 * Perform verbose error reporting if not NULL.
342 sfc_flow_parse_vlan(const struct rte_flow_item *item,
343 efx_filter_spec_t *efx_spec,
344 struct rte_flow_error *error)
348 const struct rte_flow_item_vlan *spec = NULL;
349 const struct rte_flow_item_vlan *mask = NULL;
350 const struct rte_flow_item_vlan supp_mask = {
351 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
354 rc = sfc_flow_parse_init(item,
355 (const void **)&spec,
356 (const void **)&mask,
359 sizeof(struct rte_flow_item_vlan),
365 * VID is in big-endian byte order in item and
366 * in little-endian in efx_spec, so byte swap is used.
367 * If two VLAN items are included, the first matches
368 * the outer tag and the next matches the inner tag.
370 if (mask->tci == supp_mask.tci) {
371 vid = rte_bswap16(spec->tci);
373 if (!(efx_spec->efs_match_flags &
374 EFX_FILTER_MATCH_OUTER_VID)) {
375 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
376 efx_spec->efs_outer_vid = vid;
377 } else if (!(efx_spec->efs_match_flags &
378 EFX_FILTER_MATCH_INNER_VID)) {
379 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
380 efx_spec->efs_inner_vid = vid;
382 rte_flow_error_set(error, EINVAL,
383 RTE_FLOW_ERROR_TYPE_ITEM, item,
384 "More than two VLAN items");
388 rte_flow_error_set(error, EINVAL,
389 RTE_FLOW_ERROR_TYPE_ITEM, item,
390 "VLAN ID in TCI match is required");
398 * Convert IPv4 item to EFX filter specification.
401 * Item specification. Only source and destination addresses and
402 * protocol fields are supported. If the mask is NULL, default
403 * mask will be used. Ranging is not supported.
404 * @param efx_spec[in, out]
405 * EFX filter specification to update.
407 * Perform verbose error reporting if not NULL.
410 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
411 efx_filter_spec_t *efx_spec,
412 struct rte_flow_error *error)
415 const struct rte_flow_item_ipv4 *spec = NULL;
416 const struct rte_flow_item_ipv4 *mask = NULL;
417 const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
418 const struct rte_flow_item_ipv4 supp_mask = {
420 .src_addr = 0xffffffff,
421 .dst_addr = 0xffffffff,
422 .next_proto_id = 0xff,
426 rc = sfc_flow_parse_init(item,
427 (const void **)&spec,
428 (const void **)&mask,
430 &rte_flow_item_ipv4_mask,
431 sizeof(struct rte_flow_item_ipv4),
437 * Filtering by IPv4 source and destination addresses requires
438 * the appropriate ETHER_TYPE in hardware filters
440 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
441 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
442 efx_spec->efs_ether_type = ether_type_ipv4;
443 } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
444 rte_flow_error_set(error, EINVAL,
445 RTE_FLOW_ERROR_TYPE_ITEM, item,
446 "Ethertype in pattern with IPV4 item should be appropriate");
454 * IPv4 addresses are in big-endian byte order in item and in
457 if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
458 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
459 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
460 } else if (mask->hdr.src_addr != 0) {
464 if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
465 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
466 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
467 } else if (mask->hdr.dst_addr != 0) {
471 if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
472 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
473 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
474 } else if (mask->hdr.next_proto_id != 0) {
481 rte_flow_error_set(error, EINVAL,
482 RTE_FLOW_ERROR_TYPE_ITEM, item,
483 "Bad mask in the IPV4 pattern item");
488 * Convert IPv6 item to EFX filter specification.
491 * Item specification. Only source and destination addresses and
492 * next header fields are supported. If the mask is NULL, default
493 * mask will be used. Ranging is not supported.
494 * @param efx_spec[in, out]
495 * EFX filter specification to update.
497 * Perform verbose error reporting if not NULL.
500 sfc_flow_parse_ipv6(const struct rte_flow_item *item,
501 efx_filter_spec_t *efx_spec,
502 struct rte_flow_error *error)
505 const struct rte_flow_item_ipv6 *spec = NULL;
506 const struct rte_flow_item_ipv6 *mask = NULL;
507 const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
508 const struct rte_flow_item_ipv6 supp_mask = {
510 .src_addr = { 0xff, 0xff, 0xff, 0xff,
511 0xff, 0xff, 0xff, 0xff,
512 0xff, 0xff, 0xff, 0xff,
513 0xff, 0xff, 0xff, 0xff },
514 .dst_addr = { 0xff, 0xff, 0xff, 0xff,
515 0xff, 0xff, 0xff, 0xff,
516 0xff, 0xff, 0xff, 0xff,
517 0xff, 0xff, 0xff, 0xff },
522 rc = sfc_flow_parse_init(item,
523 (const void **)&spec,
524 (const void **)&mask,
526 &rte_flow_item_ipv6_mask,
527 sizeof(struct rte_flow_item_ipv6),
533 * Filtering by IPv6 source and destination addresses requires
534 * the appropriate ETHER_TYPE in hardware filters
536 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
537 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
538 efx_spec->efs_ether_type = ether_type_ipv6;
539 } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
540 rte_flow_error_set(error, EINVAL,
541 RTE_FLOW_ERROR_TYPE_ITEM, item,
542 "Ethertype in pattern with IPV6 item should be appropriate");
550 * IPv6 addresses are in big-endian byte order in item and in
553 if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
554 sizeof(mask->hdr.src_addr)) == 0) {
555 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
557 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
558 sizeof(spec->hdr.src_addr));
559 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
560 sizeof(efx_spec->efs_rem_host));
561 } else if (!sfc_flow_is_zero(mask->hdr.src_addr,
562 sizeof(mask->hdr.src_addr))) {
566 if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
567 sizeof(mask->hdr.dst_addr)) == 0) {
568 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
570 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
571 sizeof(spec->hdr.dst_addr));
572 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
573 sizeof(efx_spec->efs_loc_host));
574 } else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
575 sizeof(mask->hdr.dst_addr))) {
579 if (mask->hdr.proto == supp_mask.hdr.proto) {
580 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
581 efx_spec->efs_ip_proto = spec->hdr.proto;
582 } else if (mask->hdr.proto != 0) {
589 rte_flow_error_set(error, EINVAL,
590 RTE_FLOW_ERROR_TYPE_ITEM, item,
591 "Bad mask in the IPV6 pattern item");
596 * Convert TCP item to EFX filter specification.
599 * Item specification. Only source and destination ports fields
600 * are supported. If the mask is NULL, default mask will be used.
601 * Ranging is not supported.
602 * @param efx_spec[in, out]
603 * EFX filter specification to update.
605 * Perform verbose error reporting if not NULL.
608 sfc_flow_parse_tcp(const struct rte_flow_item *item,
609 efx_filter_spec_t *efx_spec,
610 struct rte_flow_error *error)
613 const struct rte_flow_item_tcp *spec = NULL;
614 const struct rte_flow_item_tcp *mask = NULL;
615 const struct rte_flow_item_tcp supp_mask = {
622 rc = sfc_flow_parse_init(item,
623 (const void **)&spec,
624 (const void **)&mask,
626 &rte_flow_item_tcp_mask,
627 sizeof(struct rte_flow_item_tcp),
633 * Filtering by TCP source and destination ports requires
634 * the appropriate IP_PROTO in hardware filters
636 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
637 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
638 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
639 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
640 rte_flow_error_set(error, EINVAL,
641 RTE_FLOW_ERROR_TYPE_ITEM, item,
642 "IP proto in pattern with TCP item should be appropriate");
650 * Source and destination ports are in big-endian byte order in item and
651 * in little-endian in efx_spec, so byte swap is used
653 if (mask->hdr.src_port == supp_mask.hdr.src_port) {
654 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
655 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
656 } else if (mask->hdr.src_port != 0) {
660 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
661 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
662 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
663 } else if (mask->hdr.dst_port != 0) {
670 rte_flow_error_set(error, EINVAL,
671 RTE_FLOW_ERROR_TYPE_ITEM, item,
672 "Bad mask in the TCP pattern item");
677 * Convert UDP item to EFX filter specification.
680 * Item specification. Only source and destination ports fields
681 * are supported. If the mask is NULL, default mask will be used.
682 * Ranging is not supported.
683 * @param efx_spec[in, out]
684 * EFX filter specification to update.
686 * Perform verbose error reporting if not NULL.
689 sfc_flow_parse_udp(const struct rte_flow_item *item,
690 efx_filter_spec_t *efx_spec,
691 struct rte_flow_error *error)
694 const struct rte_flow_item_udp *spec = NULL;
695 const struct rte_flow_item_udp *mask = NULL;
696 const struct rte_flow_item_udp supp_mask = {
703 rc = sfc_flow_parse_init(item,
704 (const void **)&spec,
705 (const void **)&mask,
707 &rte_flow_item_udp_mask,
708 sizeof(struct rte_flow_item_udp),
714 * Filtering by UDP source and destination ports requires
715 * the appropriate IP_PROTO in hardware filters
717 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
718 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
719 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
720 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
721 rte_flow_error_set(error, EINVAL,
722 RTE_FLOW_ERROR_TYPE_ITEM, item,
723 "IP proto in pattern with UDP item should be appropriate");
731 * Source and destination ports are in big-endian byte order in item and
732 * in little-endian in efx_spec, so byte swap is used
734 if (mask->hdr.src_port == supp_mask.hdr.src_port) {
735 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
736 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
737 } else if (mask->hdr.src_port != 0) {
741 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
742 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
743 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
744 } else if (mask->hdr.dst_port != 0) {
751 rte_flow_error_set(error, EINVAL,
752 RTE_FLOW_ERROR_TYPE_ITEM, item,
753 "Bad mask in the UDP pattern item");
758 * Filters for encapsulated packets match based on the EtherType and IP
759 * protocol in the outer frame.
762 sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item,
763 efx_filter_spec_t *efx_spec,
765 struct rte_flow_error *error)
767 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
768 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
769 efx_spec->efs_ip_proto = ip_proto;
770 } else if (efx_spec->efs_ip_proto != ip_proto) {
772 case EFX_IPPROTO_UDP:
773 rte_flow_error_set(error, EINVAL,
774 RTE_FLOW_ERROR_TYPE_ITEM, item,
775 "Outer IP header protocol must be UDP "
776 "in VxLAN/GENEVE pattern");
779 case EFX_IPPROTO_GRE:
780 rte_flow_error_set(error, EINVAL,
781 RTE_FLOW_ERROR_TYPE_ITEM, item,
782 "Outer IP header protocol must be GRE "
787 rte_flow_error_set(error, EINVAL,
788 RTE_FLOW_ERROR_TYPE_ITEM, item,
789 "Only VxLAN/GENEVE/NVGRE tunneling patterns "
795 if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE &&
796 efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 &&
797 efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) {
798 rte_flow_error_set(error, EINVAL,
799 RTE_FLOW_ERROR_TYPE_ITEM, item,
800 "Outer frame EtherType in pattern with tunneling "
801 "must be IPv4 or IPv6");
809 sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec,
810 const uint8_t *vni_or_vsid_val,
811 const uint8_t *vni_or_vsid_mask,
812 const struct rte_flow_item *item,
813 struct rte_flow_error *error)
815 const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = {
819 if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask,
820 EFX_VNI_OR_VSID_LEN) == 0) {
821 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
822 rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val,
823 EFX_VNI_OR_VSID_LEN);
824 } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) {
825 rte_flow_error_set(error, EINVAL,
826 RTE_FLOW_ERROR_TYPE_ITEM, item,
827 "Unsupported VNI/VSID mask");
835 * Convert VXLAN item to EFX filter specification.
838 * Item specification. Only VXLAN network identifier field is supported.
839 * If the mask is NULL, default mask will be used.
840 * Ranging is not supported.
841 * @param efx_spec[in, out]
842 * EFX filter specification to update.
844 * Perform verbose error reporting if not NULL.
847 sfc_flow_parse_vxlan(const struct rte_flow_item *item,
848 efx_filter_spec_t *efx_spec,
849 struct rte_flow_error *error)
852 const struct rte_flow_item_vxlan *spec = NULL;
853 const struct rte_flow_item_vxlan *mask = NULL;
854 const struct rte_flow_item_vxlan supp_mask = {
855 .vni = { 0xff, 0xff, 0xff }
858 rc = sfc_flow_parse_init(item,
859 (const void **)&spec,
860 (const void **)&mask,
862 &rte_flow_item_vxlan_mask,
863 sizeof(struct rte_flow_item_vxlan),
868 rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
869 EFX_IPPROTO_UDP, error);
873 efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
874 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
879 rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
880 mask->vni, item, error);
886 * Convert GENEVE item to EFX filter specification.
889 * Item specification. Only Virtual Network Identifier and protocol type
890 * fields are supported. But protocol type can be only Ethernet (0x6558).
891 * If the mask is NULL, default mask will be used.
892 * Ranging is not supported.
893 * @param efx_spec[in, out]
894 * EFX filter specification to update.
896 * Perform verbose error reporting if not NULL.
899 sfc_flow_parse_geneve(const struct rte_flow_item *item,
900 efx_filter_spec_t *efx_spec,
901 struct rte_flow_error *error)
904 const struct rte_flow_item_geneve *spec = NULL;
905 const struct rte_flow_item_geneve *mask = NULL;
906 const struct rte_flow_item_geneve supp_mask = {
907 .protocol = RTE_BE16(0xffff),
908 .vni = { 0xff, 0xff, 0xff }
911 rc = sfc_flow_parse_init(item,
912 (const void **)&spec,
913 (const void **)&mask,
915 &rte_flow_item_geneve_mask,
916 sizeof(struct rte_flow_item_geneve),
921 rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
922 EFX_IPPROTO_UDP, error);
926 efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
927 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
932 if (mask->protocol == supp_mask.protocol) {
933 if (spec->protocol != rte_cpu_to_be_16(ETHER_TYPE_TEB)) {
934 rte_flow_error_set(error, EINVAL,
935 RTE_FLOW_ERROR_TYPE_ITEM, item,
936 "GENEVE encap. protocol must be Ethernet "
937 "(0x6558) in the GENEVE pattern item");
940 } else if (mask->protocol != 0) {
941 rte_flow_error_set(error, EINVAL,
942 RTE_FLOW_ERROR_TYPE_ITEM, item,
943 "Unsupported mask for GENEVE encap. protocol");
947 rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
948 mask->vni, item, error);
954 * Convert NVGRE item to EFX filter specification.
957 * Item specification. Only virtual subnet ID field is supported.
958 * If the mask is NULL, default mask will be used.
959 * Ranging is not supported.
960 * @param efx_spec[in, out]
961 * EFX filter specification to update.
963 * Perform verbose error reporting if not NULL.
966 sfc_flow_parse_nvgre(const struct rte_flow_item *item,
967 efx_filter_spec_t *efx_spec,
968 struct rte_flow_error *error)
971 const struct rte_flow_item_nvgre *spec = NULL;
972 const struct rte_flow_item_nvgre *mask = NULL;
973 const struct rte_flow_item_nvgre supp_mask = {
974 .tni = { 0xff, 0xff, 0xff }
977 rc = sfc_flow_parse_init(item,
978 (const void **)&spec,
979 (const void **)&mask,
981 &rte_flow_item_nvgre_mask,
982 sizeof(struct rte_flow_item_nvgre),
987 rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
988 EFX_IPPROTO_GRE, error);
992 efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
993 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
998 rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->tni,
999 mask->tni, item, error);
1004 static const struct sfc_flow_item sfc_flow_items[] = {
1006 .type = RTE_FLOW_ITEM_TYPE_VOID,
1007 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1008 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1009 .parse = sfc_flow_parse_void,
1012 .type = RTE_FLOW_ITEM_TYPE_ETH,
1013 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
1014 .layer = SFC_FLOW_ITEM_L2,
1015 .parse = sfc_flow_parse_eth,
1018 .type = RTE_FLOW_ITEM_TYPE_VLAN,
1019 .prev_layer = SFC_FLOW_ITEM_L2,
1020 .layer = SFC_FLOW_ITEM_L2,
1021 .parse = sfc_flow_parse_vlan,
1024 .type = RTE_FLOW_ITEM_TYPE_IPV4,
1025 .prev_layer = SFC_FLOW_ITEM_L2,
1026 .layer = SFC_FLOW_ITEM_L3,
1027 .parse = sfc_flow_parse_ipv4,
1030 .type = RTE_FLOW_ITEM_TYPE_IPV6,
1031 .prev_layer = SFC_FLOW_ITEM_L2,
1032 .layer = SFC_FLOW_ITEM_L3,
1033 .parse = sfc_flow_parse_ipv6,
1036 .type = RTE_FLOW_ITEM_TYPE_TCP,
1037 .prev_layer = SFC_FLOW_ITEM_L3,
1038 .layer = SFC_FLOW_ITEM_L4,
1039 .parse = sfc_flow_parse_tcp,
1042 .type = RTE_FLOW_ITEM_TYPE_UDP,
1043 .prev_layer = SFC_FLOW_ITEM_L3,
1044 .layer = SFC_FLOW_ITEM_L4,
1045 .parse = sfc_flow_parse_udp,
1048 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
1049 .prev_layer = SFC_FLOW_ITEM_L4,
1050 .layer = SFC_FLOW_ITEM_START_LAYER,
1051 .parse = sfc_flow_parse_vxlan,
1054 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
1055 .prev_layer = SFC_FLOW_ITEM_L4,
1056 .layer = SFC_FLOW_ITEM_START_LAYER,
1057 .parse = sfc_flow_parse_geneve,
1060 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
1061 .prev_layer = SFC_FLOW_ITEM_L3,
1062 .layer = SFC_FLOW_ITEM_START_LAYER,
1063 .parse = sfc_flow_parse_nvgre,
1068 * Protocol-independent flow API support
1071 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
1072 struct rte_flow *flow,
1073 struct rte_flow_error *error)
1076 rte_flow_error_set(error, EINVAL,
1077 RTE_FLOW_ERROR_TYPE_ATTR, NULL,
1081 if (attr->group != 0) {
1082 rte_flow_error_set(error, ENOTSUP,
1083 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
1084 "Groups are not supported");
1087 if (attr->priority != 0) {
1088 rte_flow_error_set(error, ENOTSUP,
1089 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
1090 "Priorities are not supported");
1093 if (attr->egress != 0) {
1094 rte_flow_error_set(error, ENOTSUP,
1095 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
1096 "Egress is not supported");
1099 if (attr->ingress == 0) {
1100 rte_flow_error_set(error, ENOTSUP,
1101 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
1102 "Only ingress is supported");
1106 flow->spec.template.efs_flags |= EFX_FILTER_FLAG_RX;
1107 flow->spec.template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
1112 /* Get item from array sfc_flow_items */
1113 static const struct sfc_flow_item *
1114 sfc_flow_get_item(enum rte_flow_item_type type)
1118 for (i = 0; i < RTE_DIM(sfc_flow_items); i++)
1119 if (sfc_flow_items[i].type == type)
1120 return &sfc_flow_items[i];
1126 sfc_flow_parse_pattern(const struct rte_flow_item pattern[],
1127 struct rte_flow *flow,
1128 struct rte_flow_error *error)
1131 unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
1132 boolean_t is_ifrm = B_FALSE;
1133 const struct sfc_flow_item *item;
1135 if (pattern == NULL) {
1136 rte_flow_error_set(error, EINVAL,
1137 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
1142 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
1143 item = sfc_flow_get_item(pattern->type);
1145 rte_flow_error_set(error, ENOTSUP,
1146 RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1147 "Unsupported pattern item");
1152 * Omitting one or several protocol layers at the beginning
1153 * of pattern is supported
1155 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
1156 prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
1157 item->prev_layer != prev_layer) {
1158 rte_flow_error_set(error, ENOTSUP,
1159 RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1160 "Unexpected sequence of pattern items");
1165 * Allow only VOID and ETH pattern items in the inner frame.
1166 * Also check that there is only one tunneling protocol.
1168 switch (item->type) {
1169 case RTE_FLOW_ITEM_TYPE_VOID:
1170 case RTE_FLOW_ITEM_TYPE_ETH:
1173 case RTE_FLOW_ITEM_TYPE_VXLAN:
1174 case RTE_FLOW_ITEM_TYPE_GENEVE:
1175 case RTE_FLOW_ITEM_TYPE_NVGRE:
1177 rte_flow_error_set(error, EINVAL,
1178 RTE_FLOW_ERROR_TYPE_ITEM,
1180 "More than one tunneling protocol");
1188 rte_flow_error_set(error, EINVAL,
1189 RTE_FLOW_ERROR_TYPE_ITEM,
1191 "There is an unsupported pattern item "
1192 "in the inner frame");
1198 rc = item->parse(pattern, &flow->spec.template, error);
1202 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
1203 prev_layer = item->layer;
1210 sfc_flow_parse_queue(struct sfc_adapter *sa,
1211 const struct rte_flow_action_queue *queue,
1212 struct rte_flow *flow)
1214 struct sfc_rxq *rxq;
1216 if (queue->index >= sa->rxq_count)
1219 rxq = sa->rxq_info[queue->index].rxq;
1220 flow->spec.template.efs_dmaq_id = (uint16_t)rxq->hw_index;
1225 #if EFSYS_OPT_RX_SCALE
1227 sfc_flow_parse_rss(struct sfc_adapter *sa,
1228 const struct rte_flow_action_rss *rss,
1229 struct rte_flow *flow)
1231 unsigned int rxq_sw_index;
1232 struct sfc_rxq *rxq;
1233 unsigned int rxq_hw_index_min;
1234 unsigned int rxq_hw_index_max;
1235 const struct rte_eth_rss_conf *rss_conf = rss->rss_conf;
1237 uint8_t *rss_key = NULL;
1238 struct sfc_flow_rss *sfc_rss_conf = &flow->rss_conf;
1244 rxq_sw_index = sa->rxq_count - 1;
1245 rxq = sa->rxq_info[rxq_sw_index].rxq;
1246 rxq_hw_index_min = rxq->hw_index;
1247 rxq_hw_index_max = 0;
1249 for (i = 0; i < rss->num; ++i) {
1250 rxq_sw_index = rss->queue[i];
1252 if (rxq_sw_index >= sa->rxq_count)
1255 rxq = sa->rxq_info[rxq_sw_index].rxq;
1257 if (rxq->hw_index < rxq_hw_index_min)
1258 rxq_hw_index_min = rxq->hw_index;
1260 if (rxq->hw_index > rxq_hw_index_max)
1261 rxq_hw_index_max = rxq->hw_index;
1264 rss_hf = (rss_conf != NULL) ? rss_conf->rss_hf : SFC_RSS_OFFLOADS;
1265 if ((rss_hf & ~SFC_RSS_OFFLOADS) != 0)
1268 if (rss_conf != NULL) {
1269 if (rss_conf->rss_key_len != sizeof(sa->rss_key))
1272 rss_key = rss_conf->rss_key;
1274 rss_key = sa->rss_key;
1279 sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
1280 sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
1281 sfc_rss_conf->rss_hash_types = sfc_rte_to_efx_hash_type(rss_hf);
1282 rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(sa->rss_key));
1284 for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
1285 unsigned int rxq_sw_index = rss->queue[i % rss->num];
1286 struct sfc_rxq *rxq = sa->rxq_info[rxq_sw_index].rxq;
1288 sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
1293 #endif /* EFSYS_OPT_RX_SCALE */
1296 sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec,
1297 unsigned int filters_count)
1302 for (i = 0; i < filters_count; i++) {
1305 rc = efx_filter_remove(sa->nic, &spec->filters[i]);
1306 if (ret == 0 && rc != 0) {
1307 sfc_err(sa, "failed to remove filter specification "
1317 sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
1322 for (i = 0; i < spec->count; i++) {
1323 rc = efx_filter_insert(sa->nic, &spec->filters[i]);
1325 sfc_flow_spec_flush(sa, spec, i);
1334 sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
1336 return sfc_flow_spec_flush(sa, spec, spec->count);
1340 sfc_flow_filter_insert(struct sfc_adapter *sa,
1341 struct rte_flow *flow)
1343 #if EFSYS_OPT_RX_SCALE
1344 struct sfc_flow_rss *rss = &flow->rss_conf;
1345 uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
1350 unsigned int rss_spread = MIN(rss->rxq_hw_index_max -
1351 rss->rxq_hw_index_min + 1,
1354 rc = efx_rx_scale_context_alloc(sa->nic,
1355 EFX_RX_SCALE_EXCLUSIVE,
1359 goto fail_scale_context_alloc;
1361 rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context,
1362 EFX_RX_HASHALG_TOEPLITZ,
1363 rss->rss_hash_types, B_TRUE);
1365 goto fail_scale_mode_set;
1367 rc = efx_rx_scale_key_set(sa->nic, efs_rss_context,
1369 sizeof(sa->rss_key));
1371 goto fail_scale_key_set;
1374 * At this point, fully elaborated filter specifications
1375 * have been produced from the template. To make sure that
1376 * RSS behaviour is consistent between them, set the same
1377 * RSS context value everywhere.
1379 for (i = 0; i < flow->spec.count; i++) {
1380 efx_filter_spec_t *spec = &flow->spec.filters[i];
1382 spec->efs_rss_context = efs_rss_context;
1383 spec->efs_dmaq_id = rss->rxq_hw_index_min;
1384 spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
1388 rc = sfc_flow_spec_insert(sa, &flow->spec);
1390 goto fail_filter_insert;
1394 * Scale table is set after filter insertion because
1395 * the table entries are relative to the base RxQ ID
1396 * and the latter is submitted to the HW by means of
1397 * inserting a filter, so by the time of the request
1398 * the HW knows all the information needed to verify
1399 * the table entries, and the operation will succeed
1401 rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context,
1402 rss->rss_tbl, RTE_DIM(rss->rss_tbl));
1404 goto fail_scale_tbl_set;
1410 sfc_flow_spec_remove(sa, &flow->spec);
1414 fail_scale_mode_set:
1415 if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT)
1416 efx_rx_scale_context_free(sa->nic, efs_rss_context);
1418 fail_scale_context_alloc:
1420 #else /* !EFSYS_OPT_RX_SCALE */
1421 return sfc_flow_spec_insert(sa, &flow->spec);
1422 #endif /* EFSYS_OPT_RX_SCALE */
1426 sfc_flow_filter_remove(struct sfc_adapter *sa,
1427 struct rte_flow *flow)
1431 rc = sfc_flow_spec_remove(sa, &flow->spec);
1435 #if EFSYS_OPT_RX_SCALE
1438 * All specifications for a given flow rule have the same RSS
1439 * context, so that RSS context value is taken from the first
1440 * filter specification
1442 efx_filter_spec_t *spec = &flow->spec.filters[0];
1444 rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1446 #endif /* EFSYS_OPT_RX_SCALE */
1452 sfc_flow_parse_actions(struct sfc_adapter *sa,
1453 const struct rte_flow_action actions[],
1454 struct rte_flow *flow,
1455 struct rte_flow_error *error)
1458 boolean_t is_specified = B_FALSE;
1460 if (actions == NULL) {
1461 rte_flow_error_set(error, EINVAL,
1462 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
1467 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1468 switch (actions->type) {
1469 case RTE_FLOW_ACTION_TYPE_VOID:
1472 case RTE_FLOW_ACTION_TYPE_QUEUE:
1473 rc = sfc_flow_parse_queue(sa, actions->conf, flow);
1475 rte_flow_error_set(error, EINVAL,
1476 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1477 "Bad QUEUE action");
1481 is_specified = B_TRUE;
1484 #if EFSYS_OPT_RX_SCALE
1485 case RTE_FLOW_ACTION_TYPE_RSS:
1486 rc = sfc_flow_parse_rss(sa, actions->conf, flow);
1488 rte_flow_error_set(error, rc,
1489 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1494 is_specified = B_TRUE;
1496 #endif /* EFSYS_OPT_RX_SCALE */
1499 rte_flow_error_set(error, ENOTSUP,
1500 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1501 "Action is not supported");
1506 if (!is_specified) {
1507 rte_flow_error_set(error, EINVAL,
1508 RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
1509 "Action is unspecified");
1517 * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and
1518 * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same
1519 * specifications after copying.
1521 * @param spec[in, out]
1522 * SFC flow specification to update.
1523 * @param filters_count_for_one_val[in]
1524 * How many specifications should have the same EtherType value, what is the
1525 * number of specifications before copying.
1527 * Perform verbose error reporting if not NULL.
1530 sfc_flow_set_ethertypes(struct sfc_flow_spec *spec,
1531 unsigned int filters_count_for_one_val,
1532 struct rte_flow_error *error)
1535 static const uint16_t vals[] = {
1536 EFX_ETHER_TYPE_IPV4, EFX_ETHER_TYPE_IPV6
1539 if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) {
1540 rte_flow_error_set(error, EINVAL,
1541 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1542 "Number of specifications is incorrect "
1543 "while copying by Ethertype");
1547 for (i = 0; i < spec->count; i++) {
1548 spec->filters[i].efs_match_flags |=
1549 EFX_FILTER_MATCH_ETHER_TYPE;
1552 * The check above ensures that
1553 * filters_count_for_one_val is not 0
1555 spec->filters[i].efs_ether_type =
1556 vals[i / filters_count_for_one_val];
1563 * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and
1564 * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same
1565 * specifications after copying.
1567 * @param spec[in, out]
1568 * SFC flow specification to update.
1569 * @param filters_count_for_one_val[in]
1570 * How many specifications should have the same match flag, what is the
1571 * number of specifications before copying.
1573 * Perform verbose error reporting if not NULL.
1576 sfc_flow_set_ifrm_unknown_dst_flags(struct sfc_flow_spec *spec,
1577 unsigned int filters_count_for_one_val,
1578 struct rte_flow_error *error)
1581 static const efx_filter_match_flags_t vals[] = {
1582 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
1583 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST
1586 if (filters_count_for_one_val * RTE_DIM(vals) != spec->count) {
1587 rte_flow_error_set(error, EINVAL,
1588 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1589 "Number of specifications is incorrect while copying "
1590 "by inner frame unknown destination flags");
1594 for (i = 0; i < spec->count; i++) {
1595 /* The check above ensures that divisor can't be zero here */
1596 spec->filters[i].efs_match_flags |=
1597 vals[i / filters_count_for_one_val];
1604 * Check that the following conditions are met:
1605 * - the specification corresponds to a filter for encapsulated traffic
1606 * - the list of supported filters has a filter
1607 * with EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST flag instead of
1608 * EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, since this filter will also
1612 * The match flags of filter.
1614 * Specification to be supplemented.
1616 * SFC filter with list of supported filters.
1619 sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match,
1620 efx_filter_spec_t *spec,
1621 struct sfc_filter *filter)
1624 efx_tunnel_protocol_t encap_type = spec->efs_encap_type;
1625 efx_filter_match_flags_t match_mcast_dst;
1627 if (encap_type == EFX_TUNNEL_PROTOCOL_NONE)
1631 (match & ~EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST) |
1632 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
1633 for (i = 0; i < filter->supported_match_num; i++) {
1634 if (match_mcast_dst == filter->supported_match[i])
1641 /* Match flags that can be automatically added to filters */
1642 static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = {
1644 .flag = EFX_FILTER_MATCH_ETHER_TYPE,
1646 .set_vals = sfc_flow_set_ethertypes,
1650 .flag = EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
1652 .set_vals = sfc_flow_set_ifrm_unknown_dst_flags,
1653 .spec_check = sfc_flow_check_ifrm_unknown_dst_flags,
1657 /* Get item from array sfc_flow_copy_flags */
1658 static const struct sfc_flow_copy_flag *
1659 sfc_flow_get_copy_flag(efx_filter_match_flags_t flag)
1663 for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
1664 if (sfc_flow_copy_flags[i].flag == flag)
1665 return &sfc_flow_copy_flags[i];
1672 * Make copies of the specifications, set match flag and values
1673 * of the field that corresponds to it.
1675 * @param spec[in, out]
1676 * SFC flow specification to update.
1678 * The match flag to add.
1680 * Perform verbose error reporting if not NULL.
1683 sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec,
1684 efx_filter_match_flags_t flag,
1685 struct rte_flow_error *error)
1688 unsigned int new_filters_count;
1689 unsigned int filters_count_for_one_val;
1690 const struct sfc_flow_copy_flag *copy_flag;
1693 copy_flag = sfc_flow_get_copy_flag(flag);
1694 if (copy_flag == NULL) {
1695 rte_flow_error_set(error, ENOTSUP,
1696 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1697 "Unsupported spec field for copying");
1701 new_filters_count = spec->count * copy_flag->vals_count;
1702 if (new_filters_count > SF_FLOW_SPEC_NB_FILTERS_MAX) {
1703 rte_flow_error_set(error, EINVAL,
1704 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1705 "Too much EFX specifications in the flow rule");
1709 /* Copy filters specifications */
1710 for (i = spec->count; i < new_filters_count; i++)
1711 spec->filters[i] = spec->filters[i - spec->count];
1713 filters_count_for_one_val = spec->count;
1714 spec->count = new_filters_count;
1716 rc = copy_flag->set_vals(spec, filters_count_for_one_val, error);
1724 * Check that the given set of match flags missing in the original filter spec
1725 * could be covered by adding spec copies which specify the corresponding
1726 * flags and packet field values to match.
1728 * @param miss_flags[in]
1729 * Flags that are missing until the supported filter.
1731 * Specification to be supplemented.
1736 * Number of specifications after copy or 0, if the flags can not be added.
1739 sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags,
1740 efx_filter_spec_t *spec,
1741 struct sfc_filter *filter)
1744 efx_filter_match_flags_t copy_flags = 0;
1745 efx_filter_match_flags_t flag;
1746 efx_filter_match_flags_t match = spec->efs_match_flags | miss_flags;
1747 sfc_flow_spec_check *check;
1748 unsigned int multiplier = 1;
1750 for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
1751 flag = sfc_flow_copy_flags[i].flag;
1752 check = sfc_flow_copy_flags[i].spec_check;
1753 if ((flag & miss_flags) == flag) {
1754 if (check != NULL && (!check(match, spec, filter)))
1758 multiplier *= sfc_flow_copy_flags[i].vals_count;
1762 if (copy_flags == miss_flags)
1769 * Attempt to supplement the specification template to the minimally
1770 * supported set of match flags. To do this, it is necessary to copy
1771 * the specifications, filling them with the values of fields that
1772 * correspond to the missing flags.
1773 * The necessary and sufficient filter is built from the fewest number
1774 * of copies which could be made to cover the minimally required set
1779 * @param spec[in, out]
1780 * SFC flow specification to update.
1782 * Perform verbose error reporting if not NULL.
1785 sfc_flow_spec_filters_complete(struct sfc_adapter *sa,
1786 struct sfc_flow_spec *spec,
1787 struct rte_flow_error *error)
1789 struct sfc_filter *filter = &sa->filter;
1790 efx_filter_match_flags_t miss_flags;
1791 efx_filter_match_flags_t min_miss_flags = 0;
1792 efx_filter_match_flags_t match;
1793 unsigned int min_multiplier = UINT_MAX;
1794 unsigned int multiplier;
1798 match = spec->template.efs_match_flags;
1799 for (i = 0; i < filter->supported_match_num; i++) {
1800 if ((match & filter->supported_match[i]) == match) {
1801 miss_flags = filter->supported_match[i] & (~match);
1802 multiplier = sfc_flow_check_missing_flags(miss_flags,
1803 &spec->template, filter);
1804 if (multiplier > 0) {
1805 if (multiplier <= min_multiplier) {
1806 min_multiplier = multiplier;
1807 min_miss_flags = miss_flags;
1813 if (min_multiplier == UINT_MAX) {
1814 rte_flow_error_set(error, ENOTSUP,
1815 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1816 "Flow rule pattern is not supported");
1820 for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
1821 efx_filter_match_flags_t flag = sfc_flow_copy_flags[i].flag;
1823 if ((flag & min_miss_flags) == flag) {
1824 rc = sfc_flow_spec_add_match_flag(spec, flag, error);
1834 sfc_flow_validate_match_flags(struct sfc_adapter *sa,
1835 struct rte_flow *flow,
1836 struct rte_flow_error *error)
1838 efx_filter_spec_t *spec_tmpl = &flow->spec.template;
1839 efx_filter_match_flags_t match_flags = spec_tmpl->efs_match_flags;
1842 /* Initialize the first filter spec with template */
1843 flow->spec.filters[0] = *spec_tmpl;
1844 flow->spec.count = 1;
1846 if (!sfc_filter_is_match_supported(sa, match_flags)) {
1847 rc = sfc_flow_spec_filters_complete(sa, &flow->spec, error);
1856 sfc_flow_parse(struct rte_eth_dev *dev,
1857 const struct rte_flow_attr *attr,
1858 const struct rte_flow_item pattern[],
1859 const struct rte_flow_action actions[],
1860 struct rte_flow *flow,
1861 struct rte_flow_error *error)
1863 struct sfc_adapter *sa = dev->data->dev_private;
1866 rc = sfc_flow_parse_attr(attr, flow, error);
1868 goto fail_bad_value;
1870 rc = sfc_flow_parse_pattern(pattern, flow, error);
1872 goto fail_bad_value;
1874 rc = sfc_flow_parse_actions(sa, actions, flow, error);
1876 goto fail_bad_value;
1878 rc = sfc_flow_validate_match_flags(sa, flow, error);
1880 goto fail_bad_value;
1889 sfc_flow_validate(struct rte_eth_dev *dev,
1890 const struct rte_flow_attr *attr,
1891 const struct rte_flow_item pattern[],
1892 const struct rte_flow_action actions[],
1893 struct rte_flow_error *error)
1895 struct rte_flow flow;
1897 memset(&flow, 0, sizeof(flow));
1899 return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
1902 static struct rte_flow *
1903 sfc_flow_create(struct rte_eth_dev *dev,
1904 const struct rte_flow_attr *attr,
1905 const struct rte_flow_item pattern[],
1906 const struct rte_flow_action actions[],
1907 struct rte_flow_error *error)
1909 struct sfc_adapter *sa = dev->data->dev_private;
1910 struct rte_flow *flow = NULL;
1913 flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
1915 rte_flow_error_set(error, ENOMEM,
1916 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1917 "Failed to allocate memory");
1921 rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1923 goto fail_bad_value;
1925 TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1927 sfc_adapter_lock(sa);
1929 if (sa->state == SFC_ADAPTER_STARTED) {
1930 rc = sfc_flow_filter_insert(sa, flow);
1932 rte_flow_error_set(error, rc,
1933 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1934 "Failed to insert filter");
1935 goto fail_filter_insert;
1939 sfc_adapter_unlock(sa);
1944 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1948 sfc_adapter_unlock(sa);
1955 sfc_flow_remove(struct sfc_adapter *sa,
1956 struct rte_flow *flow,
1957 struct rte_flow_error *error)
1961 SFC_ASSERT(sfc_adapter_is_locked(sa));
1963 if (sa->state == SFC_ADAPTER_STARTED) {
1964 rc = sfc_flow_filter_remove(sa, flow);
1966 rte_flow_error_set(error, rc,
1967 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1968 "Failed to destroy flow rule");
1971 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1978 sfc_flow_destroy(struct rte_eth_dev *dev,
1979 struct rte_flow *flow,
1980 struct rte_flow_error *error)
1982 struct sfc_adapter *sa = dev->data->dev_private;
1983 struct rte_flow *flow_ptr;
1986 sfc_adapter_lock(sa);
1988 TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1989 if (flow_ptr == flow)
1993 rte_flow_error_set(error, rc,
1994 RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1995 "Failed to find flow rule to destroy");
1996 goto fail_bad_value;
1999 rc = sfc_flow_remove(sa, flow, error);
2002 sfc_adapter_unlock(sa);
2008 sfc_flow_flush(struct rte_eth_dev *dev,
2009 struct rte_flow_error *error)
2011 struct sfc_adapter *sa = dev->data->dev_private;
2012 struct rte_flow *flow;
2016 sfc_adapter_lock(sa);
2018 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
2019 rc = sfc_flow_remove(sa, flow, error);
2024 sfc_adapter_unlock(sa);
2030 sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
2031 struct rte_flow_error *error)
2033 struct sfc_adapter *sa = dev->data->dev_private;
2034 struct sfc_port *port = &sa->port;
2037 sfc_adapter_lock(sa);
2038 if (sa->state != SFC_ADAPTER_INITIALIZED) {
2039 rte_flow_error_set(error, EBUSY,
2040 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2041 NULL, "please close the port first");
2044 port->isolated = (enable) ? B_TRUE : B_FALSE;
2046 sfc_adapter_unlock(sa);
2051 const struct rte_flow_ops sfc_flow_ops = {
2052 .validate = sfc_flow_validate,
2053 .create = sfc_flow_create,
2054 .destroy = sfc_flow_destroy,
2055 .flush = sfc_flow_flush,
2057 .isolate = sfc_flow_isolate,
2061 sfc_flow_init(struct sfc_adapter *sa)
2063 SFC_ASSERT(sfc_adapter_is_locked(sa));
2065 TAILQ_INIT(&sa->filter.flow_list);
2069 sfc_flow_fini(struct sfc_adapter *sa)
2071 struct rte_flow *flow;
2073 SFC_ASSERT(sfc_adapter_is_locked(sa));
2075 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
2076 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
2082 sfc_flow_stop(struct sfc_adapter *sa)
2084 struct rte_flow *flow;
2086 SFC_ASSERT(sfc_adapter_is_locked(sa));
2088 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
2089 sfc_flow_filter_remove(sa, flow);
2093 sfc_flow_start(struct sfc_adapter *sa)
2095 struct rte_flow *flow;
2098 sfc_log_init(sa, "entry");
2100 SFC_ASSERT(sfc_adapter_is_locked(sa));
2102 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
2103 rc = sfc_flow_filter_insert(sa, flow);
2108 sfc_log_init(sa, "done");