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 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.
34 enum sfc_flow_item_layers {
35 SFC_FLOW_ITEM_ANY_LAYER,
36 SFC_FLOW_ITEM_START_LAYER,
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);
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 */
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 static sfc_flow_item_parse sfc_flow_parse_vxlan;
63 sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
68 for (i = 0; i < size; i++)
71 return (sum == 0) ? B_TRUE : B_FALSE;
75 * Validate item and prepare structures spec and mask for parsing
78 sfc_flow_parse_init(const struct rte_flow_item *item,
79 const void **spec_ptr,
80 const void **mask_ptr,
81 const void *supp_mask,
84 struct rte_flow_error *error)
94 rte_flow_error_set(error, EINVAL,
95 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
100 if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
101 rte_flow_error_set(error, EINVAL,
102 RTE_FLOW_ERROR_TYPE_ITEM, item,
103 "Mask or last is set without spec");
108 * If "mask" is not set, default mask is used,
109 * but if default mask is NULL, "mask" should be set
111 if (item->mask == NULL) {
112 if (def_mask == NULL) {
113 rte_flow_error_set(error, EINVAL,
114 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
115 "Mask should be specified");
131 * If field values in "last" are either 0 or equal to the corresponding
132 * values in "spec" then they are ignored
135 !sfc_flow_is_zero(last, size) &&
136 memcmp(last, spec, size) != 0) {
137 rte_flow_error_set(error, ENOTSUP,
138 RTE_FLOW_ERROR_TYPE_ITEM, item,
139 "Ranging is not supported");
143 if (supp_mask == NULL) {
144 rte_flow_error_set(error, EINVAL,
145 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
146 "Supported mask for item should be specified");
150 /* Check that mask and spec not asks for more match than supp_mask */
151 for (i = 0; i < size; i++) {
152 match = spec[i] | mask[i];
153 supp = ((const uint8_t *)supp_mask)[i];
155 if ((match | supp) != supp) {
156 rte_flow_error_set(error, ENOTSUP,
157 RTE_FLOW_ERROR_TYPE_ITEM, item,
158 "Item's field is not supported");
171 * Masking is not supported, so masks in items should be either
172 * full or empty (zeroed) and set only for supported fields which
173 * are specified in the supp_mask.
177 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
178 __rte_unused efx_filter_spec_t *efx_spec,
179 __rte_unused struct rte_flow_error *error)
185 * Convert Ethernet item to EFX filter specification.
188 * Item specification. Only source and destination addresses and
189 * Ethernet type fields are supported. In addition to full and
190 * empty masks of destination address, individual/group mask is
191 * also supported. If the mask is NULL, default mask will be used.
192 * Ranging is not supported.
193 * @param efx_spec[in, out]
194 * EFX filter specification to update.
196 * Perform verbose error reporting if not NULL.
199 sfc_flow_parse_eth(const struct rte_flow_item *item,
200 efx_filter_spec_t *efx_spec,
201 struct rte_flow_error *error)
204 const struct rte_flow_item_eth *spec = NULL;
205 const struct rte_flow_item_eth *mask = NULL;
206 const struct rte_flow_item_eth supp_mask = {
207 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
208 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
211 const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
212 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
215 rc = sfc_flow_parse_init(item,
216 (const void **)&spec,
217 (const void **)&mask,
219 &rte_flow_item_eth_mask,
220 sizeof(struct rte_flow_item_eth),
225 /* If "spec" is not set, could be any Ethernet */
229 if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) {
230 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
231 rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes,
233 } else if (memcmp(mask->dst.addr_bytes, ig_mask,
234 EFX_MAC_ADDR_LEN) == 0) {
235 if (is_unicast_ether_addr(&spec->dst))
236 efx_spec->efs_match_flags |=
237 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
239 efx_spec->efs_match_flags |=
240 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
241 } else if (!is_zero_ether_addr(&mask->dst)) {
245 if (is_same_ether_addr(&mask->src, &supp_mask.src)) {
246 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
247 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes,
249 } else if (!is_zero_ether_addr(&mask->src)) {
254 * Ether type is in big-endian byte order in item and
255 * in little-endian in efx_spec, so byte swap is used
257 if (mask->type == supp_mask.type) {
258 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
259 efx_spec->efs_ether_type = rte_bswap16(spec->type);
260 } else if (mask->type != 0) {
267 rte_flow_error_set(error, EINVAL,
268 RTE_FLOW_ERROR_TYPE_ITEM, item,
269 "Bad mask in the ETH pattern item");
274 * Convert VLAN item to EFX filter specification.
277 * Item specification. Only VID field is supported.
278 * The mask can not be NULL. Ranging is not supported.
279 * @param efx_spec[in, out]
280 * EFX filter specification to update.
282 * Perform verbose error reporting if not NULL.
285 sfc_flow_parse_vlan(const struct rte_flow_item *item,
286 efx_filter_spec_t *efx_spec,
287 struct rte_flow_error *error)
291 const struct rte_flow_item_vlan *spec = NULL;
292 const struct rte_flow_item_vlan *mask = NULL;
293 const struct rte_flow_item_vlan supp_mask = {
294 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
297 rc = sfc_flow_parse_init(item,
298 (const void **)&spec,
299 (const void **)&mask,
302 sizeof(struct rte_flow_item_vlan),
308 * VID is in big-endian byte order in item and
309 * in little-endian in efx_spec, so byte swap is used.
310 * If two VLAN items are included, the first matches
311 * the outer tag and the next matches the inner tag.
313 if (mask->tci == supp_mask.tci) {
314 vid = rte_bswap16(spec->tci);
316 if (!(efx_spec->efs_match_flags &
317 EFX_FILTER_MATCH_OUTER_VID)) {
318 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
319 efx_spec->efs_outer_vid = vid;
320 } else if (!(efx_spec->efs_match_flags &
321 EFX_FILTER_MATCH_INNER_VID)) {
322 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
323 efx_spec->efs_inner_vid = vid;
325 rte_flow_error_set(error, EINVAL,
326 RTE_FLOW_ERROR_TYPE_ITEM, item,
327 "More than two VLAN items");
331 rte_flow_error_set(error, EINVAL,
332 RTE_FLOW_ERROR_TYPE_ITEM, item,
333 "VLAN ID in TCI match is required");
341 * Convert IPv4 item to EFX filter specification.
344 * Item specification. Only source and destination addresses and
345 * protocol fields are supported. If the mask is NULL, default
346 * mask will be used. Ranging is not supported.
347 * @param efx_spec[in, out]
348 * EFX filter specification to update.
350 * Perform verbose error reporting if not NULL.
353 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
354 efx_filter_spec_t *efx_spec,
355 struct rte_flow_error *error)
358 const struct rte_flow_item_ipv4 *spec = NULL;
359 const struct rte_flow_item_ipv4 *mask = NULL;
360 const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
361 const struct rte_flow_item_ipv4 supp_mask = {
363 .src_addr = 0xffffffff,
364 .dst_addr = 0xffffffff,
365 .next_proto_id = 0xff,
369 rc = sfc_flow_parse_init(item,
370 (const void **)&spec,
371 (const void **)&mask,
373 &rte_flow_item_ipv4_mask,
374 sizeof(struct rte_flow_item_ipv4),
380 * Filtering by IPv4 source and destination addresses requires
381 * the appropriate ETHER_TYPE in hardware filters
383 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
384 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
385 efx_spec->efs_ether_type = ether_type_ipv4;
386 } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
387 rte_flow_error_set(error, EINVAL,
388 RTE_FLOW_ERROR_TYPE_ITEM, item,
389 "Ethertype in pattern with IPV4 item should be appropriate");
397 * IPv4 addresses are in big-endian byte order in item and in
400 if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
401 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
402 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
403 } else if (mask->hdr.src_addr != 0) {
407 if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
408 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
409 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
410 } else if (mask->hdr.dst_addr != 0) {
414 if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
415 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
416 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
417 } else if (mask->hdr.next_proto_id != 0) {
424 rte_flow_error_set(error, EINVAL,
425 RTE_FLOW_ERROR_TYPE_ITEM, item,
426 "Bad mask in the IPV4 pattern item");
431 * Convert IPv6 item to EFX filter specification.
434 * Item specification. Only source and destination addresses and
435 * next header fields are supported. If the mask is NULL, default
436 * mask will be used. Ranging is not supported.
437 * @param efx_spec[in, out]
438 * EFX filter specification to update.
440 * Perform verbose error reporting if not NULL.
443 sfc_flow_parse_ipv6(const struct rte_flow_item *item,
444 efx_filter_spec_t *efx_spec,
445 struct rte_flow_error *error)
448 const struct rte_flow_item_ipv6 *spec = NULL;
449 const struct rte_flow_item_ipv6 *mask = NULL;
450 const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
451 const struct rte_flow_item_ipv6 supp_mask = {
453 .src_addr = { 0xff, 0xff, 0xff, 0xff,
454 0xff, 0xff, 0xff, 0xff,
455 0xff, 0xff, 0xff, 0xff,
456 0xff, 0xff, 0xff, 0xff },
457 .dst_addr = { 0xff, 0xff, 0xff, 0xff,
458 0xff, 0xff, 0xff, 0xff,
459 0xff, 0xff, 0xff, 0xff,
460 0xff, 0xff, 0xff, 0xff },
465 rc = sfc_flow_parse_init(item,
466 (const void **)&spec,
467 (const void **)&mask,
469 &rte_flow_item_ipv6_mask,
470 sizeof(struct rte_flow_item_ipv6),
476 * Filtering by IPv6 source and destination addresses requires
477 * the appropriate ETHER_TYPE in hardware filters
479 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
480 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
481 efx_spec->efs_ether_type = ether_type_ipv6;
482 } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
483 rte_flow_error_set(error, EINVAL,
484 RTE_FLOW_ERROR_TYPE_ITEM, item,
485 "Ethertype in pattern with IPV6 item should be appropriate");
493 * IPv6 addresses are in big-endian byte order in item and in
496 if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
497 sizeof(mask->hdr.src_addr)) == 0) {
498 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
500 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
501 sizeof(spec->hdr.src_addr));
502 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
503 sizeof(efx_spec->efs_rem_host));
504 } else if (!sfc_flow_is_zero(mask->hdr.src_addr,
505 sizeof(mask->hdr.src_addr))) {
509 if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
510 sizeof(mask->hdr.dst_addr)) == 0) {
511 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
513 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
514 sizeof(spec->hdr.dst_addr));
515 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
516 sizeof(efx_spec->efs_loc_host));
517 } else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
518 sizeof(mask->hdr.dst_addr))) {
522 if (mask->hdr.proto == supp_mask.hdr.proto) {
523 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
524 efx_spec->efs_ip_proto = spec->hdr.proto;
525 } else if (mask->hdr.proto != 0) {
532 rte_flow_error_set(error, EINVAL,
533 RTE_FLOW_ERROR_TYPE_ITEM, item,
534 "Bad mask in the IPV6 pattern item");
539 * Convert TCP item to EFX filter specification.
542 * Item specification. Only source and destination ports fields
543 * are supported. If the mask is NULL, default mask will be used.
544 * Ranging is not supported.
545 * @param efx_spec[in, out]
546 * EFX filter specification to update.
548 * Perform verbose error reporting if not NULL.
551 sfc_flow_parse_tcp(const struct rte_flow_item *item,
552 efx_filter_spec_t *efx_spec,
553 struct rte_flow_error *error)
556 const struct rte_flow_item_tcp *spec = NULL;
557 const struct rte_flow_item_tcp *mask = NULL;
558 const struct rte_flow_item_tcp supp_mask = {
565 rc = sfc_flow_parse_init(item,
566 (const void **)&spec,
567 (const void **)&mask,
569 &rte_flow_item_tcp_mask,
570 sizeof(struct rte_flow_item_tcp),
576 * Filtering by TCP source and destination ports requires
577 * the appropriate IP_PROTO in hardware filters
579 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
580 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
581 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
582 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
583 rte_flow_error_set(error, EINVAL,
584 RTE_FLOW_ERROR_TYPE_ITEM, item,
585 "IP proto in pattern with TCP item should be appropriate");
593 * Source and destination ports are in big-endian byte order in item and
594 * in little-endian in efx_spec, so byte swap is used
596 if (mask->hdr.src_port == supp_mask.hdr.src_port) {
597 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
598 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
599 } else if (mask->hdr.src_port != 0) {
603 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
604 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
605 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
606 } else if (mask->hdr.dst_port != 0) {
613 rte_flow_error_set(error, EINVAL,
614 RTE_FLOW_ERROR_TYPE_ITEM, item,
615 "Bad mask in the TCP pattern item");
620 * Convert UDP item to EFX filter specification.
623 * Item specification. Only source and destination ports fields
624 * are supported. If the mask is NULL, default mask will be used.
625 * Ranging is not supported.
626 * @param efx_spec[in, out]
627 * EFX filter specification to update.
629 * Perform verbose error reporting if not NULL.
632 sfc_flow_parse_udp(const struct rte_flow_item *item,
633 efx_filter_spec_t *efx_spec,
634 struct rte_flow_error *error)
637 const struct rte_flow_item_udp *spec = NULL;
638 const struct rte_flow_item_udp *mask = NULL;
639 const struct rte_flow_item_udp supp_mask = {
646 rc = sfc_flow_parse_init(item,
647 (const void **)&spec,
648 (const void **)&mask,
650 &rte_flow_item_udp_mask,
651 sizeof(struct rte_flow_item_udp),
657 * Filtering by UDP source and destination ports requires
658 * the appropriate IP_PROTO in hardware filters
660 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
661 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
662 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
663 } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
664 rte_flow_error_set(error, EINVAL,
665 RTE_FLOW_ERROR_TYPE_ITEM, item,
666 "IP proto in pattern with UDP item should be appropriate");
674 * Source and destination ports are in big-endian byte order in item and
675 * in little-endian in efx_spec, so byte swap is used
677 if (mask->hdr.src_port == supp_mask.hdr.src_port) {
678 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
679 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
680 } else if (mask->hdr.src_port != 0) {
684 if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
685 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
686 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
687 } else if (mask->hdr.dst_port != 0) {
694 rte_flow_error_set(error, EINVAL,
695 RTE_FLOW_ERROR_TYPE_ITEM, item,
696 "Bad mask in the UDP pattern item");
701 * Filters for encapsulated packets match based on the EtherType and IP
702 * protocol in the outer frame.
705 sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item,
706 efx_filter_spec_t *efx_spec,
708 struct rte_flow_error *error)
710 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
711 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
712 efx_spec->efs_ip_proto = ip_proto;
713 } else if (efx_spec->efs_ip_proto != ip_proto) {
715 case EFX_IPPROTO_UDP:
716 rte_flow_error_set(error, EINVAL,
717 RTE_FLOW_ERROR_TYPE_ITEM, item,
718 "Outer IP header protocol must be UDP "
723 rte_flow_error_set(error, EINVAL,
724 RTE_FLOW_ERROR_TYPE_ITEM, item,
725 "Only VxLAN tunneling patterns "
731 if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
732 rte_flow_error_set(error, EINVAL,
733 RTE_FLOW_ERROR_TYPE_ITEM, item,
734 "Outer frame EtherType in pattern with tunneling "
737 } else if (efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 &&
738 efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) {
739 rte_flow_error_set(error, EINVAL,
740 RTE_FLOW_ERROR_TYPE_ITEM, item,
741 "Outer frame EtherType in pattern with tunneling "
742 "must be IPv4 or IPv6");
750 sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec,
751 const uint8_t *vni_or_vsid_val,
752 const uint8_t *vni_or_vsid_mask,
753 const struct rte_flow_item *item,
754 struct rte_flow_error *error)
756 const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = {
760 if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask,
761 EFX_VNI_OR_VSID_LEN) == 0) {
762 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
763 rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val,
764 EFX_VNI_OR_VSID_LEN);
765 } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) {
766 rte_flow_error_set(error, EINVAL,
767 RTE_FLOW_ERROR_TYPE_ITEM, item,
768 "Unsupported VNI/VSID mask");
776 * Convert VXLAN item to EFX filter specification.
779 * Item specification. Only VXLAN network identifier field is supported.
780 * If the mask is NULL, default mask will be used.
781 * Ranging is not supported.
782 * @param efx_spec[in, out]
783 * EFX filter specification to update.
785 * Perform verbose error reporting if not NULL.
788 sfc_flow_parse_vxlan(const struct rte_flow_item *item,
789 efx_filter_spec_t *efx_spec,
790 struct rte_flow_error *error)
793 const struct rte_flow_item_vxlan *spec = NULL;
794 const struct rte_flow_item_vxlan *mask = NULL;
795 const struct rte_flow_item_vxlan supp_mask = {
796 .vni = { 0xff, 0xff, 0xff }
799 rc = sfc_flow_parse_init(item,
800 (const void **)&spec,
801 (const void **)&mask,
803 &rte_flow_item_vxlan_mask,
804 sizeof(struct rte_flow_item_vxlan),
809 rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
810 EFX_IPPROTO_UDP, error);
814 efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
815 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
820 rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
821 mask->vni, item, error);
826 static const struct sfc_flow_item sfc_flow_items[] = {
828 .type = RTE_FLOW_ITEM_TYPE_VOID,
829 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
830 .layer = SFC_FLOW_ITEM_ANY_LAYER,
831 .parse = sfc_flow_parse_void,
834 .type = RTE_FLOW_ITEM_TYPE_ETH,
835 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
836 .layer = SFC_FLOW_ITEM_L2,
837 .parse = sfc_flow_parse_eth,
840 .type = RTE_FLOW_ITEM_TYPE_VLAN,
841 .prev_layer = SFC_FLOW_ITEM_L2,
842 .layer = SFC_FLOW_ITEM_L2,
843 .parse = sfc_flow_parse_vlan,
846 .type = RTE_FLOW_ITEM_TYPE_IPV4,
847 .prev_layer = SFC_FLOW_ITEM_L2,
848 .layer = SFC_FLOW_ITEM_L3,
849 .parse = sfc_flow_parse_ipv4,
852 .type = RTE_FLOW_ITEM_TYPE_IPV6,
853 .prev_layer = SFC_FLOW_ITEM_L2,
854 .layer = SFC_FLOW_ITEM_L3,
855 .parse = sfc_flow_parse_ipv6,
858 .type = RTE_FLOW_ITEM_TYPE_TCP,
859 .prev_layer = SFC_FLOW_ITEM_L3,
860 .layer = SFC_FLOW_ITEM_L4,
861 .parse = sfc_flow_parse_tcp,
864 .type = RTE_FLOW_ITEM_TYPE_UDP,
865 .prev_layer = SFC_FLOW_ITEM_L3,
866 .layer = SFC_FLOW_ITEM_L4,
867 .parse = sfc_flow_parse_udp,
870 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
871 .prev_layer = SFC_FLOW_ITEM_L4,
872 .layer = SFC_FLOW_ITEM_START_LAYER,
873 .parse = sfc_flow_parse_vxlan,
878 * Protocol-independent flow API support
881 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
882 struct rte_flow *flow,
883 struct rte_flow_error *error)
886 rte_flow_error_set(error, EINVAL,
887 RTE_FLOW_ERROR_TYPE_ATTR, NULL,
891 if (attr->group != 0) {
892 rte_flow_error_set(error, ENOTSUP,
893 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
894 "Groups are not supported");
897 if (attr->priority != 0) {
898 rte_flow_error_set(error, ENOTSUP,
899 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
900 "Priorities are not supported");
903 if (attr->egress != 0) {
904 rte_flow_error_set(error, ENOTSUP,
905 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
906 "Egress is not supported");
909 if (attr->ingress == 0) {
910 rte_flow_error_set(error, ENOTSUP,
911 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
912 "Only ingress is supported");
916 flow->spec.efs_flags |= EFX_FILTER_FLAG_RX;
917 flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
922 /* Get item from array sfc_flow_items */
923 static const struct sfc_flow_item *
924 sfc_flow_get_item(enum rte_flow_item_type type)
928 for (i = 0; i < RTE_DIM(sfc_flow_items); i++)
929 if (sfc_flow_items[i].type == type)
930 return &sfc_flow_items[i];
936 sfc_flow_parse_pattern(const struct rte_flow_item pattern[],
937 struct rte_flow *flow,
938 struct rte_flow_error *error)
941 unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
942 boolean_t is_ifrm = B_FALSE;
943 const struct sfc_flow_item *item;
945 if (pattern == NULL) {
946 rte_flow_error_set(error, EINVAL,
947 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
952 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
953 item = sfc_flow_get_item(pattern->type);
955 rte_flow_error_set(error, ENOTSUP,
956 RTE_FLOW_ERROR_TYPE_ITEM, pattern,
957 "Unsupported pattern item");
962 * Omitting one or several protocol layers at the beginning
963 * of pattern is supported
965 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
966 prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
967 item->prev_layer != prev_layer) {
968 rte_flow_error_set(error, ENOTSUP,
969 RTE_FLOW_ERROR_TYPE_ITEM, pattern,
970 "Unexpected sequence of pattern items");
975 * Allow only VOID pattern item in the inner frame.
976 * Also check that there is only one tunneling protocol.
978 switch (item->type) {
979 case RTE_FLOW_ITEM_TYPE_VOID:
982 case RTE_FLOW_ITEM_TYPE_VXLAN:
984 rte_flow_error_set(error, EINVAL,
985 RTE_FLOW_ERROR_TYPE_ITEM,
987 "More than one tunneling protocol");
995 rte_flow_error_set(error, EINVAL,
996 RTE_FLOW_ERROR_TYPE_ITEM,
998 "There is an unsupported pattern item "
999 "in the inner frame");
1005 rc = item->parse(pattern, &flow->spec, error);
1009 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
1010 prev_layer = item->layer;
1017 sfc_flow_parse_queue(struct sfc_adapter *sa,
1018 const struct rte_flow_action_queue *queue,
1019 struct rte_flow *flow)
1021 struct sfc_rxq *rxq;
1023 if (queue->index >= sa->rxq_count)
1026 rxq = sa->rxq_info[queue->index].rxq;
1027 flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index;
1032 #if EFSYS_OPT_RX_SCALE
1034 sfc_flow_parse_rss(struct sfc_adapter *sa,
1035 const struct rte_flow_action_rss *rss,
1036 struct rte_flow *flow)
1038 unsigned int rxq_sw_index;
1039 struct sfc_rxq *rxq;
1040 unsigned int rxq_hw_index_min;
1041 unsigned int rxq_hw_index_max;
1042 const struct rte_eth_rss_conf *rss_conf = rss->rss_conf;
1044 uint8_t *rss_key = NULL;
1045 struct sfc_flow_rss *sfc_rss_conf = &flow->rss_conf;
1051 rxq_sw_index = sa->rxq_count - 1;
1052 rxq = sa->rxq_info[rxq_sw_index].rxq;
1053 rxq_hw_index_min = rxq->hw_index;
1054 rxq_hw_index_max = 0;
1056 for (i = 0; i < rss->num; ++i) {
1057 rxq_sw_index = rss->queue[i];
1059 if (rxq_sw_index >= sa->rxq_count)
1062 rxq = sa->rxq_info[rxq_sw_index].rxq;
1064 if (rxq->hw_index < rxq_hw_index_min)
1065 rxq_hw_index_min = rxq->hw_index;
1067 if (rxq->hw_index > rxq_hw_index_max)
1068 rxq_hw_index_max = rxq->hw_index;
1071 rss_hf = (rss_conf != NULL) ? rss_conf->rss_hf : SFC_RSS_OFFLOADS;
1072 if ((rss_hf & ~SFC_RSS_OFFLOADS) != 0)
1075 if (rss_conf != NULL) {
1076 if (rss_conf->rss_key_len != sizeof(sa->rss_key))
1079 rss_key = rss_conf->rss_key;
1081 rss_key = sa->rss_key;
1086 sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
1087 sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
1088 sfc_rss_conf->rss_hash_types = sfc_rte_to_efx_hash_type(rss_hf);
1089 rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(sa->rss_key));
1091 for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
1092 unsigned int rxq_sw_index = rss->queue[i % rss->num];
1093 struct sfc_rxq *rxq = sa->rxq_info[rxq_sw_index].rxq;
1095 sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
1100 #endif /* EFSYS_OPT_RX_SCALE */
1103 sfc_flow_filter_insert(struct sfc_adapter *sa,
1104 struct rte_flow *flow)
1106 efx_filter_spec_t *spec = &flow->spec;
1108 #if EFSYS_OPT_RX_SCALE
1109 struct sfc_flow_rss *rss = &flow->rss_conf;
1113 unsigned int rss_spread = MIN(rss->rxq_hw_index_max -
1114 rss->rxq_hw_index_min + 1,
1117 rc = efx_rx_scale_context_alloc(sa->nic,
1118 EFX_RX_SCALE_EXCLUSIVE,
1120 &spec->efs_rss_context);
1122 goto fail_scale_context_alloc;
1124 rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context,
1125 EFX_RX_HASHALG_TOEPLITZ,
1126 rss->rss_hash_types, B_TRUE);
1128 goto fail_scale_mode_set;
1130 rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context,
1132 sizeof(sa->rss_key));
1134 goto fail_scale_key_set;
1136 spec->efs_dmaq_id = rss->rxq_hw_index_min;
1137 spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
1140 rc = efx_filter_insert(sa->nic, spec);
1142 goto fail_filter_insert;
1146 * Scale table is set after filter insertion because
1147 * the table entries are relative to the base RxQ ID
1148 * and the latter is submitted to the HW by means of
1149 * inserting a filter, so by the time of the request
1150 * the HW knows all the information needed to verify
1151 * the table entries, and the operation will succeed
1153 rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context,
1154 rss->rss_tbl, RTE_DIM(rss->rss_tbl));
1156 goto fail_scale_tbl_set;
1162 efx_filter_remove(sa->nic, spec);
1166 fail_scale_mode_set:
1168 efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1170 fail_scale_context_alloc:
1172 #else /* !EFSYS_OPT_RX_SCALE */
1173 return efx_filter_insert(sa->nic, spec);
1174 #endif /* EFSYS_OPT_RX_SCALE */
1178 sfc_flow_filter_remove(struct sfc_adapter *sa,
1179 struct rte_flow *flow)
1181 efx_filter_spec_t *spec = &flow->spec;
1184 rc = efx_filter_remove(sa->nic, spec);
1188 #if EFSYS_OPT_RX_SCALE
1190 rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1191 #endif /* EFSYS_OPT_RX_SCALE */
1197 sfc_flow_parse_actions(struct sfc_adapter *sa,
1198 const struct rte_flow_action actions[],
1199 struct rte_flow *flow,
1200 struct rte_flow_error *error)
1203 boolean_t is_specified = B_FALSE;
1205 if (actions == NULL) {
1206 rte_flow_error_set(error, EINVAL,
1207 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
1212 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1213 switch (actions->type) {
1214 case RTE_FLOW_ACTION_TYPE_VOID:
1217 case RTE_FLOW_ACTION_TYPE_QUEUE:
1218 rc = sfc_flow_parse_queue(sa, actions->conf, flow);
1220 rte_flow_error_set(error, EINVAL,
1221 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1222 "Bad QUEUE action");
1226 is_specified = B_TRUE;
1229 #if EFSYS_OPT_RX_SCALE
1230 case RTE_FLOW_ACTION_TYPE_RSS:
1231 rc = sfc_flow_parse_rss(sa, actions->conf, flow);
1233 rte_flow_error_set(error, rc,
1234 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1239 is_specified = B_TRUE;
1241 #endif /* EFSYS_OPT_RX_SCALE */
1244 rte_flow_error_set(error, ENOTSUP,
1245 RTE_FLOW_ERROR_TYPE_ACTION, actions,
1246 "Action is not supported");
1251 if (!is_specified) {
1252 rte_flow_error_set(error, EINVAL,
1253 RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
1254 "Action is unspecified");
1262 sfc_flow_parse(struct rte_eth_dev *dev,
1263 const struct rte_flow_attr *attr,
1264 const struct rte_flow_item pattern[],
1265 const struct rte_flow_action actions[],
1266 struct rte_flow *flow,
1267 struct rte_flow_error *error)
1269 struct sfc_adapter *sa = dev->data->dev_private;
1272 rc = sfc_flow_parse_attr(attr, flow, error);
1274 goto fail_bad_value;
1276 rc = sfc_flow_parse_pattern(pattern, flow, error);
1278 goto fail_bad_value;
1280 rc = sfc_flow_parse_actions(sa, actions, flow, error);
1282 goto fail_bad_value;
1284 if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) {
1285 rte_flow_error_set(error, ENOTSUP,
1286 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1287 "Flow rule pattern is not supported");
1296 sfc_flow_validate(struct rte_eth_dev *dev,
1297 const struct rte_flow_attr *attr,
1298 const struct rte_flow_item pattern[],
1299 const struct rte_flow_action actions[],
1300 struct rte_flow_error *error)
1302 struct rte_flow flow;
1304 memset(&flow, 0, sizeof(flow));
1306 return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
1309 static struct rte_flow *
1310 sfc_flow_create(struct rte_eth_dev *dev,
1311 const struct rte_flow_attr *attr,
1312 const struct rte_flow_item pattern[],
1313 const struct rte_flow_action actions[],
1314 struct rte_flow_error *error)
1316 struct sfc_adapter *sa = dev->data->dev_private;
1317 struct rte_flow *flow = NULL;
1320 flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
1322 rte_flow_error_set(error, ENOMEM,
1323 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1324 "Failed to allocate memory");
1328 rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1330 goto fail_bad_value;
1332 TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1334 sfc_adapter_lock(sa);
1336 if (sa->state == SFC_ADAPTER_STARTED) {
1337 rc = sfc_flow_filter_insert(sa, flow);
1339 rte_flow_error_set(error, rc,
1340 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1341 "Failed to insert filter");
1342 goto fail_filter_insert;
1346 sfc_adapter_unlock(sa);
1351 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1355 sfc_adapter_unlock(sa);
1362 sfc_flow_remove(struct sfc_adapter *sa,
1363 struct rte_flow *flow,
1364 struct rte_flow_error *error)
1368 SFC_ASSERT(sfc_adapter_is_locked(sa));
1370 if (sa->state == SFC_ADAPTER_STARTED) {
1371 rc = sfc_flow_filter_remove(sa, flow);
1373 rte_flow_error_set(error, rc,
1374 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1375 "Failed to destroy flow rule");
1378 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1385 sfc_flow_destroy(struct rte_eth_dev *dev,
1386 struct rte_flow *flow,
1387 struct rte_flow_error *error)
1389 struct sfc_adapter *sa = dev->data->dev_private;
1390 struct rte_flow *flow_ptr;
1393 sfc_adapter_lock(sa);
1395 TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1396 if (flow_ptr == flow)
1400 rte_flow_error_set(error, rc,
1401 RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1402 "Failed to find flow rule to destroy");
1403 goto fail_bad_value;
1406 rc = sfc_flow_remove(sa, flow, error);
1409 sfc_adapter_unlock(sa);
1415 sfc_flow_flush(struct rte_eth_dev *dev,
1416 struct rte_flow_error *error)
1418 struct sfc_adapter *sa = dev->data->dev_private;
1419 struct rte_flow *flow;
1423 sfc_adapter_lock(sa);
1425 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1426 rc = sfc_flow_remove(sa, flow, error);
1431 sfc_adapter_unlock(sa);
1437 sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
1438 struct rte_flow_error *error)
1440 struct sfc_adapter *sa = dev->data->dev_private;
1441 struct sfc_port *port = &sa->port;
1444 sfc_adapter_lock(sa);
1445 if (sa->state != SFC_ADAPTER_INITIALIZED) {
1446 rte_flow_error_set(error, EBUSY,
1447 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1448 NULL, "please close the port first");
1451 port->isolated = (enable) ? B_TRUE : B_FALSE;
1453 sfc_adapter_unlock(sa);
1458 const struct rte_flow_ops sfc_flow_ops = {
1459 .validate = sfc_flow_validate,
1460 .create = sfc_flow_create,
1461 .destroy = sfc_flow_destroy,
1462 .flush = sfc_flow_flush,
1464 .isolate = sfc_flow_isolate,
1468 sfc_flow_init(struct sfc_adapter *sa)
1470 SFC_ASSERT(sfc_adapter_is_locked(sa));
1472 TAILQ_INIT(&sa->filter.flow_list);
1476 sfc_flow_fini(struct sfc_adapter *sa)
1478 struct rte_flow *flow;
1480 SFC_ASSERT(sfc_adapter_is_locked(sa));
1482 while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1483 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1489 sfc_flow_stop(struct sfc_adapter *sa)
1491 struct rte_flow *flow;
1493 SFC_ASSERT(sfc_adapter_is_locked(sa));
1495 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
1496 sfc_flow_filter_remove(sa, flow);
1500 sfc_flow_start(struct sfc_adapter *sa)
1502 struct rte_flow *flow;
1505 sfc_log_init(sa, "entry");
1507 SFC_ASSERT(sfc_adapter_is_locked(sa));
1509 TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
1510 rc = sfc_flow_filter_insert(sa, flow);
1515 sfc_log_init(sa, "done");