From 7f83738b46e6e0dd17c7a23392ceaaef686ac08a Mon Sep 17 00:00:00 2001 From: Chenmin Sun Date: Sat, 28 Mar 2020 00:34:19 +0800 Subject: dpdk: DPDK 20.05 iavf flow director backporting to DPDK 20.02 0001 ~ 0014 patches are for virtual channel and PMD 0015 is the iavf fdir framework 0016 ~ 0017 are for the iavf fidr driver Type: feature Signed-off-by: Chenmin Sun Change-Id: I38e69ca0065a71cc6ba0b44ef7c7db51193a0899 --- .../0015-net-iavf-support-generic-flow.patch | 1531 ++++++++++++++++++++ 1 file changed, 1531 insertions(+) create mode 100644 build/external/patches/dpdk_20.02/0015-net-iavf-support-generic-flow.patch (limited to 'build/external/patches/dpdk_20.02/0015-net-iavf-support-generic-flow.patch') diff --git a/build/external/patches/dpdk_20.02/0015-net-iavf-support-generic-flow.patch b/build/external/patches/dpdk_20.02/0015-net-iavf-support-generic-flow.patch new file mode 100644 index 00000000000..61ed8e5e209 --- /dev/null +++ b/build/external/patches/dpdk_20.02/0015-net-iavf-support-generic-flow.patch @@ -0,0 +1,1531 @@ +From 0692e4be875c64c5d26f2e6df80bbb1a24df36a6 Mon Sep 17 00:00:00 2001 +From: Chenmin Sun +Date: Fri, 17 Apr 2020 05:02:22 +0800 +Subject: [DPDK 15/17] net/iavf: support generic flow + +This patch added iavf_flow_create, iavf_flow_destroy, +iavf_flow_flush and iavf_flow_validate support, +these are used to handle all the generic filters. + +This patch supported basic L2, L3, L4 and GTPU patterns. + +Signed-off-by: Qiming Yang +Acked-by: Qi Zhang +Signed-off-by: Chenmin Sun +--- + doc/guides/nics/features/iavf.ini | 1 + + drivers/net/iavf/Makefile | 1 + + drivers/net/iavf/iavf.h | 10 + + drivers/net/iavf/iavf_ethdev.c | 45 ++ + drivers/net/iavf/iavf_generic_flow.c | 1008 ++++++++++++++++++++++++++ + drivers/net/iavf/iavf_generic_flow.h | 313 ++++++++ + drivers/net/iavf/meson.build | 1 + + 7 files changed, 1379 insertions(+) + create mode 100644 drivers/net/iavf/iavf_generic_flow.c + create mode 100644 drivers/net/iavf/iavf_generic_flow.h + +diff --git a/doc/guides/nics/features/iavf.ini b/doc/guides/nics/features/iavf.ini +index 80143059e..3bf368785 100644 +--- a/doc/guides/nics/features/iavf.ini ++++ b/doc/guides/nics/features/iavf.ini +@@ -19,6 +19,7 @@ Multicast MAC filter = Y + RSS hash = Y + RSS key update = Y + RSS reta update = Y ++Flow API = Y + VLAN filter = Y + CRC offload = Y + VLAN offload = Y +diff --git a/drivers/net/iavf/Makefile b/drivers/net/iavf/Makefile +index 514073d76..1bf0f26b5 100644 +--- a/drivers/net/iavf/Makefile ++++ b/drivers/net/iavf/Makefile +@@ -23,6 +23,7 @@ EXPORT_MAP := rte_pmd_iavf_version.map + SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_ethdev.c + SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_vchnl.c + SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx.c ++SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_generic_flow.c + ifeq ($(CONFIG_RTE_ARCH_X86), y) + SRCS-$(CONFIG_RTE_LIBRTE_IAVF_PMD) += iavf_rxtx_vec_sse.c + endif +diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h +index b63efd4e8..78bdaff20 100644 +--- a/drivers/net/iavf/iavf.h ++++ b/drivers/net/iavf/iavf.h +@@ -86,6 +86,12 @@ struct iavf_vsi { + struct virtchnl_eth_stats eth_stats_offset; + }; + ++struct rte_flow; ++TAILQ_HEAD(iavf_flow_list, rte_flow); ++ ++struct iavf_flow_parser_node; ++TAILQ_HEAD(iavf_parser_list, iavf_flow_parser_node); ++ + /* TODO: is that correct to assume the max number to be 16 ?*/ + #define IAVF_MAX_MSIX_VECTORS 16 + +@@ -121,6 +127,10 @@ struct iavf_info { + uint16_t msix_base; /* msix vector base from */ + /* queue bitmask for each vector */ + uint16_t rxq_map[IAVF_MAX_MSIX_VECTORS]; ++ struct iavf_flow_list flow_list; ++ rte_spinlock_t flow_ops_lock; ++ struct iavf_parser_list rss_parser_list; ++ struct iavf_parser_list dist_parser_list; + }; + + #define IAVF_MAX_PKT_TYPE 1024 +diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c +index d3a121eac..95ab6e246 100644 +--- a/drivers/net/iavf/iavf_ethdev.c ++++ b/drivers/net/iavf/iavf_ethdev.c +@@ -27,6 +27,7 @@ + + #include "iavf.h" + #include "iavf_rxtx.h" ++#include "iavf_generic_flow.h" + + static int iavf_dev_configure(struct rte_eth_dev *dev); + static int iavf_dev_start(struct rte_eth_dev *dev); +@@ -67,6 +68,11 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, + uint16_t queue_id); + static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, + uint16_t queue_id); ++static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev, ++ enum rte_filter_type filter_type, ++ enum rte_filter_op filter_op, ++ void *arg); ++ + + int iavf_logtype_init; + int iavf_logtype_driver; +@@ -125,6 +131,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = { + .mtu_set = iavf_dev_mtu_set, + .rx_queue_intr_enable = iavf_dev_rx_queue_intr_enable, + .rx_queue_intr_disable = iavf_dev_rx_queue_intr_disable, ++ .filter_ctrl = iavf_dev_filter_ctrl, + }; + + static int +@@ -1298,6 +1305,33 @@ iavf_dev_interrupt_handler(void *param) + iavf_enable_irq0(hw); + } + ++static int ++iavf_dev_filter_ctrl(struct rte_eth_dev *dev, ++ enum rte_filter_type filter_type, ++ enum rte_filter_op filter_op, ++ void *arg) ++{ ++ int ret = 0; ++ ++ if (!dev) ++ return -EINVAL; ++ ++ switch (filter_type) { ++ case RTE_ETH_FILTER_GENERIC: ++ if (filter_op != RTE_ETH_FILTER_GET) ++ return -EINVAL; ++ *(const void **)arg = &iavf_flow_ops; ++ break; ++ default: ++ PMD_DRV_LOG(WARNING, "Filter type (%d) not supported", ++ filter_type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ + static int + iavf_dev_init(struct rte_eth_dev *eth_dev) + { +@@ -1305,6 +1339,7 @@ iavf_dev_init(struct rte_eth_dev *eth_dev) + IAVF_DEV_PRIVATE_TO_ADAPTER(eth_dev->data->dev_private); + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(adapter); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev); ++ int ret = 0; + + PMD_INIT_FUNC_TRACE(); + +@@ -1374,6 +1409,12 @@ iavf_dev_init(struct rte_eth_dev *eth_dev) + /* configure and enable device interrupt */ + iavf_enable_irq0(hw); + ++ ret = iavf_flow_init(adapter); ++ if (ret) { ++ PMD_INIT_LOG(ERR, "Failed to initialize flow"); ++ return ret; ++ } ++ + return 0; + } + +@@ -1383,6 +1424,8 @@ iavf_dev_close(struct rte_eth_dev *dev) + struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; ++ struct iavf_adapter *adapter = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); + + iavf_dev_stop(dev); + iavf_shutdown_adminq(hw); +@@ -1393,6 +1436,8 @@ iavf_dev_close(struct rte_eth_dev *dev) + rte_intr_callback_unregister(intr_handle, + iavf_dev_interrupt_handler, dev); + iavf_disable_irq0(hw); ++ ++ iavf_flow_uninit(adapter); + } + + static int +diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c +new file mode 100644 +index 000000000..98f1626d6 +--- /dev/null ++++ b/drivers/net/iavf/iavf_generic_flow.c +@@ -0,0 +1,1008 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2019 Intel Corporation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "iavf.h" ++#include "iavf_generic_flow.h" ++ ++static struct iavf_engine_list engine_list = ++ TAILQ_HEAD_INITIALIZER(engine_list); ++ ++static int iavf_flow_validate(struct rte_eth_dev *dev, ++ const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error); ++static struct rte_flow *iavf_flow_create(struct rte_eth_dev *dev, ++ const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error); ++static int iavf_flow_destroy(struct rte_eth_dev *dev, ++ struct rte_flow *flow, ++ struct rte_flow_error *error); ++static int iavf_flow_flush(struct rte_eth_dev *dev, ++ struct rte_flow_error *error); ++static int iavf_flow_query(struct rte_eth_dev *dev, ++ struct rte_flow *flow, ++ const struct rte_flow_action *actions, ++ void *data, ++ struct rte_flow_error *error); ++ ++const struct rte_flow_ops iavf_flow_ops = { ++ .validate = iavf_flow_validate, ++ .create = iavf_flow_create, ++ .destroy = iavf_flow_destroy, ++ .flush = iavf_flow_flush, ++ .query = iavf_flow_query, ++}; ++ ++/* empty */ ++enum rte_flow_item_type iavf_pattern_empty[] = { ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* L2 */ ++enum rte_flow_item_type iavf_pattern_ethertype[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_ethertype_vlan[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_ethertype_qinq[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* ARP */ ++enum rte_flow_item_type iavf_pattern_eth_arp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* non-tunnel IPv4 */ ++enum rte_flow_item_type iavf_pattern_eth_ipv4[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_ICMP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_ICMP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_ICMP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* non-tunnel IPv6 */ ++enum rte_flow_item_type iavf_pattern_eth_ipv6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_SCTP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_ICMP6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_ICMP6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_VLAN, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_ICMP6, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* GTPU */ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_GTP_PSC, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_GTP_PSC, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_GTP_PSC, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_GTP_PSC, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_TCP, ++ RTE_FLOW_ITEM_TYPE_END, ++ ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_GTPU, ++ RTE_FLOW_ITEM_TYPE_GTP_PSC, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_ICMP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* ESP */ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_ESP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_ESP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_ESP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_UDP, ++ RTE_FLOW_ITEM_TYPE_ESP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* AH */ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_AH, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_AH, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++/* L2TPV3 */ ++enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV4, ++ RTE_FLOW_ITEM_TYPE_L2TPV3OIP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[] = { ++ RTE_FLOW_ITEM_TYPE_ETH, ++ RTE_FLOW_ITEM_TYPE_IPV6, ++ RTE_FLOW_ITEM_TYPE_L2TPV3OIP, ++ RTE_FLOW_ITEM_TYPE_END, ++}; ++ ++typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ struct iavf_parser_list *parser_list, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error); ++ ++void ++iavf_register_flow_engine(struct iavf_flow_engine *engine) ++{ ++ TAILQ_INSERT_TAIL(&engine_list, engine, node); ++} ++ ++int ++iavf_flow_init(struct iavf_adapter *ad) ++{ ++ int ret; ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ void *temp; ++ struct iavf_flow_engine *engine; ++ ++ TAILQ_INIT(&vf->flow_list); ++ TAILQ_INIT(&vf->rss_parser_list); ++ TAILQ_INIT(&vf->dist_parser_list); ++ rte_spinlock_init(&vf->flow_ops_lock); ++ ++ TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) { ++ if (engine->init == NULL) { ++ PMD_INIT_LOG(ERR, "Invalid engine type (%d)", ++ engine->type); ++ return -ENOTSUP; ++ } ++ ++ ret = engine->init(ad); ++ if (ret && ret != -ENOTSUP) { ++ PMD_INIT_LOG(ERR, "Failed to initialize engine %d", ++ engine->type); ++ return ret; ++ } ++ } ++ return 0; ++} ++ ++void ++iavf_flow_uninit(struct iavf_adapter *ad) ++{ ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ struct iavf_flow_engine *engine; ++ struct rte_flow *p_flow; ++ struct iavf_flow_parser_node *p_parser; ++ void *temp; ++ ++ TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) { ++ if (engine->uninit) ++ engine->uninit(ad); ++ } ++ ++ /* Remove all flows */ ++ while ((p_flow = TAILQ_FIRST(&vf->flow_list))) { ++ TAILQ_REMOVE(&vf->flow_list, p_flow, node); ++ if (p_flow->engine->free) ++ p_flow->engine->free(p_flow); ++ rte_free(p_flow); ++ } ++ ++ /* Cleanup parser list */ ++ while ((p_parser = TAILQ_FIRST(&vf->rss_parser_list))) { ++ TAILQ_REMOVE(&vf->rss_parser_list, p_parser, node); ++ rte_free(p_parser); ++ } ++ ++ while ((p_parser = TAILQ_FIRST(&vf->dist_parser_list))) { ++ TAILQ_REMOVE(&vf->dist_parser_list, p_parser, node); ++ rte_free(p_parser); ++ } ++} ++ ++int ++iavf_register_parser(struct iavf_flow_parser *parser, ++ struct iavf_adapter *ad) ++{ ++ struct iavf_parser_list *list = NULL; ++ struct iavf_flow_parser_node *parser_node; ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ ++ parser_node = rte_zmalloc("iavf_parser", sizeof(*parser_node), 0); ++ if (parser_node == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate memory."); ++ return -ENOMEM; ++ } ++ parser_node->parser = parser; ++ ++ if (parser->engine->type == IAVF_FLOW_ENGINE_HASH) { ++ list = &vf->rss_parser_list; ++ TAILQ_INSERT_TAIL(list, parser_node, node); ++ } else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR) { ++ list = &vf->dist_parser_list; ++ TAILQ_INSERT_HEAD(list, parser_node, node); ++ } else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void ++iavf_unregister_parser(struct iavf_flow_parser *parser, ++ struct iavf_adapter *ad) ++{ ++ struct iavf_parser_list *list = NULL; ++ struct iavf_flow_parser_node *p_parser; ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ void *temp; ++ ++ if (parser->engine->type == IAVF_FLOW_ENGINE_HASH) ++ list = &vf->rss_parser_list; ++ else if (parser->engine->type == IAVF_FLOW_ENGINE_FDIR) ++ list = &vf->dist_parser_list; ++ ++ if (list == NULL) ++ return; ++ ++ TAILQ_FOREACH_SAFE(p_parser, list, node, temp) { ++ if (p_parser->parser->engine->type == parser->engine->type) { ++ TAILQ_REMOVE(list, p_parser, node); ++ rte_free(p_parser); ++ } ++ } ++} ++ ++static int ++iavf_flow_valid_attr(const struct rte_flow_attr *attr, ++ struct rte_flow_error *error) ++{ ++ /* Must be input direction */ ++ if (!attr->ingress) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, ++ attr, "Only support ingress."); ++ return -rte_errno; ++ } ++ ++ /* Not supported */ ++ if (attr->egress) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, ++ attr, "Not support egress."); ++ return -rte_errno; ++ } ++ ++ /* Not supported */ ++ if (attr->priority) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, ++ attr, "Not support priority."); ++ return -rte_errno; ++ } ++ ++ /* Not supported */ ++ if (attr->group) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ATTR_GROUP, ++ attr, "Not support group."); ++ return -rte_errno; ++ } ++ ++ return 0; ++} ++ ++/* Find the first VOID or non-VOID item pointer */ ++static const struct rte_flow_item * ++iavf_find_first_item(const struct rte_flow_item *item, bool is_void) ++{ ++ bool is_find; ++ ++ while (item->type != RTE_FLOW_ITEM_TYPE_END) { ++ if (is_void) ++ is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID; ++ else ++ is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID; ++ if (is_find) ++ break; ++ item++; ++ } ++ return item; ++} ++ ++/* Skip all VOID items of the pattern */ ++static void ++iavf_pattern_skip_void_item(struct rte_flow_item *items, ++ const struct rte_flow_item *pattern) ++{ ++ uint32_t cpy_count = 0; ++ const struct rte_flow_item *pb = pattern, *pe = pattern; ++ ++ for (;;) { ++ /* Find a non-void item first */ ++ pb = iavf_find_first_item(pb, false); ++ if (pb->type == RTE_FLOW_ITEM_TYPE_END) { ++ pe = pb; ++ break; ++ } ++ ++ /* Find a void item */ ++ pe = iavf_find_first_item(pb + 1, true); ++ ++ cpy_count = pe - pb; ++ rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count); ++ ++ items += cpy_count; ++ ++ if (pe->type == RTE_FLOW_ITEM_TYPE_END) ++ break; ++ ++ pb = pe + 1; ++ } ++ /* Copy the END item. */ ++ rte_memcpy(items, pe, sizeof(struct rte_flow_item)); ++} ++ ++/* Check if the pattern matches a supported item type array */ ++static bool ++iavf_match_pattern(enum rte_flow_item_type *item_array, ++ const struct rte_flow_item *pattern) ++{ ++ const struct rte_flow_item *item = pattern; ++ ++ while ((*item_array == item->type) && ++ (*item_array != RTE_FLOW_ITEM_TYPE_END)) { ++ item_array++; ++ item++; ++ } ++ ++ return (*item_array == RTE_FLOW_ITEM_TYPE_END && ++ item->type == RTE_FLOW_ITEM_TYPE_END); ++} ++ ++struct iavf_pattern_match_item * ++iavf_search_pattern_match_item(const struct rte_flow_item pattern[], ++ struct iavf_pattern_match_item *array, ++ uint32_t array_len, ++ struct rte_flow_error *error) ++{ ++ uint16_t i = 0; ++ struct iavf_pattern_match_item *pattern_match_item; ++ /* need free by each filter */ ++ struct rte_flow_item *items; /* used for pattern without VOID items */ ++ uint32_t item_num = 0; /* non-void item number */ ++ ++ /* Get the non-void item number of pattern */ ++ while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) { ++ if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID) ++ item_num++; ++ i++; ++ } ++ item_num++; ++ ++ items = rte_zmalloc("iavf_pattern", ++ item_num * sizeof(struct rte_flow_item), 0); ++ if (!items) { ++ rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM, ++ NULL, "No memory for PMD internal items."); ++ return NULL; ++ } ++ pattern_match_item = rte_zmalloc("iavf_pattern_match_item", ++ sizeof(struct iavf_pattern_match_item), 0); ++ if (!pattern_match_item) { ++ rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, ++ NULL, "Failed to allocate memory."); ++ return NULL; ++ } ++ ++ iavf_pattern_skip_void_item(items, pattern); ++ ++ for (i = 0; i < array_len; i++) ++ if (iavf_match_pattern(array[i].pattern_list, ++ items)) { ++ pattern_match_item->input_set_mask = ++ array[i].input_set_mask; ++ pattern_match_item->pattern_list = ++ array[i].pattern_list; ++ pattern_match_item->meta = array[i].meta; ++ rte_free(items); ++ return pattern_match_item; ++ } ++ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, ++ pattern, "Unsupported pattern"); ++ ++ rte_free(items); ++ rte_free(pattern_match_item); ++ return NULL; ++} ++ ++static struct iavf_flow_engine * ++iavf_parse_engine_create(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ struct iavf_parser_list *parser_list, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error) ++{ ++ struct iavf_flow_engine *engine = NULL; ++ struct iavf_flow_parser_node *parser_node; ++ void *temp; ++ void *meta = NULL; ++ ++ TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) { ++ if (parser_node->parser->parse_pattern_action(ad, ++ parser_node->parser->array, ++ parser_node->parser->array_len, ++ pattern, actions, &meta, error) < 0) ++ continue; ++ ++ engine = parser_node->parser->engine; ++ ++ RTE_ASSERT(engine->create != NULL); ++ if (!(engine->create(ad, flow, meta, error))) ++ return engine; ++ } ++ return NULL; ++} ++ ++static struct iavf_flow_engine * ++iavf_parse_engine_validate(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ struct iavf_parser_list *parser_list, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error) ++{ ++ struct iavf_flow_engine *engine = NULL; ++ struct iavf_flow_parser_node *parser_node; ++ void *temp; ++ void *meta = NULL; ++ ++ TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) { ++ if (parser_node->parser->parse_pattern_action(ad, ++ parser_node->parser->array, ++ parser_node->parser->array_len, ++ pattern, actions, &meta, error) < 0) ++ continue; ++ ++ engine = parser_node->parser->engine; ++ if (engine->validation == NULL) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_HANDLE, ++ NULL, "Validation not support"); ++ continue; ++ } ++ ++ if (engine->validation(ad, flow, meta, error)) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_HANDLE, ++ NULL, "Validation failed"); ++ break; ++ } ++ } ++ return engine; ++} ++ ++ ++static int ++iavf_flow_process_filter(struct rte_eth_dev *dev, ++ struct rte_flow *flow, ++ const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct iavf_flow_engine **engine, ++ parse_engine_t iavf_parse_engine, ++ struct rte_flow_error *error) ++{ ++ int ret = IAVF_ERR_CONFIG; ++ struct iavf_adapter *ad = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ ++ if (!pattern) { ++ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM, ++ NULL, "NULL pattern."); ++ return -rte_errno; ++ } ++ ++ if (!actions) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ACTION_NUM, ++ NULL, "NULL action."); ++ return -rte_errno; ++ } ++ ++ if (!attr) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ATTR, ++ NULL, "NULL attribute."); ++ return -rte_errno; ++ } ++ ++ ret = iavf_flow_valid_attr(attr, error); ++ if (ret) ++ return ret; ++ ++ *engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list, pattern, ++ actions, error); ++ if (*engine != NULL) ++ return 0; ++ ++ *engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list, pattern, ++ actions, error); ++ ++ if (*engine == NULL) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int ++iavf_flow_validate(struct rte_eth_dev *dev, ++ const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error) ++{ ++ struct iavf_flow_engine *engine; ++ ++ return iavf_flow_process_filter(dev, NULL, attr, pattern, actions, ++ &engine, iavf_parse_engine_validate, error); ++} ++ ++static struct rte_flow * ++iavf_flow_create(struct rte_eth_dev *dev, ++ const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct rte_flow_error *error) ++{ ++ struct iavf_adapter *ad = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ struct iavf_flow_engine *engine = NULL; ++ struct rte_flow *flow = NULL; ++ int ret; ++ ++ flow = rte_zmalloc("iavf_flow", sizeof(struct rte_flow), 0); ++ if (!flow) { ++ rte_flow_error_set(error, ENOMEM, ++ RTE_FLOW_ERROR_TYPE_HANDLE, NULL, ++ "Failed to allocate memory"); ++ return flow; ++ } ++ ++ ret = iavf_flow_process_filter(dev, flow, attr, pattern, actions, ++ &engine, iavf_parse_engine_create, error); ++ if (ret < 0) { ++ PMD_DRV_LOG(ERR, "Failed to create flow"); ++ rte_free(flow); ++ flow = NULL; ++ goto free_flow; ++ } ++ ++ flow->engine = engine; ++ TAILQ_INSERT_TAIL(&vf->flow_list, flow, node); ++ PMD_DRV_LOG(INFO, "Succeeded to create (%d) flow", engine->type); ++ ++free_flow: ++ rte_spinlock_unlock(&vf->flow_ops_lock); ++ return flow; ++} ++ ++static int ++iavf_flow_destroy(struct rte_eth_dev *dev, ++ struct rte_flow *flow, ++ struct rte_flow_error *error) ++{ ++ struct iavf_adapter *ad = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ int ret = 0; ++ ++ if (!flow || !flow->engine || !flow->engine->destroy) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_HANDLE, ++ NULL, "Invalid flow"); ++ return -rte_errno; ++ } ++ ++ rte_spinlock_lock(&vf->flow_ops_lock); ++ ++ ret = flow->engine->destroy(ad, flow, error); ++ ++ if (!ret) { ++ TAILQ_REMOVE(&vf->flow_list, flow, node); ++ rte_free(flow); ++ } else { ++ PMD_DRV_LOG(ERR, "Failed to destroy flow"); ++ } ++ ++ rte_spinlock_unlock(&vf->flow_ops_lock); ++ ++ return ret; ++} ++ ++static int ++iavf_flow_flush(struct rte_eth_dev *dev, ++ struct rte_flow_error *error) ++{ ++ struct iavf_adapter *ad = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); ++ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad); ++ struct rte_flow *p_flow; ++ void *temp; ++ int ret = 0; ++ ++ TAILQ_FOREACH_SAFE(p_flow, &vf->flow_list, node, temp) { ++ ret = iavf_flow_destroy(dev, p_flow, error); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failed to flush flows"); ++ return -EINVAL; ++ } ++ } ++ ++ return ret; ++} ++ ++static int ++iavf_flow_query(struct rte_eth_dev *dev, ++ struct rte_flow *flow, ++ const struct rte_flow_action *actions, ++ void *data, ++ struct rte_flow_error *error) ++{ ++ int ret = -EINVAL; ++ struct iavf_adapter *ad = ++ IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private); ++ struct rte_flow_query_count *count = data; ++ ++ if (!flow || !flow->engine || !flow->engine->query_count) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_HANDLE, ++ NULL, "Invalid flow"); ++ return -rte_errno; ++ } ++ ++ for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { ++ switch (actions->type) { ++ case RTE_FLOW_ACTION_TYPE_VOID: ++ break; ++ case RTE_FLOW_ACTION_TYPE_COUNT: ++ ret = flow->engine->query_count(ad, flow, count, error); ++ break; ++ default: ++ return rte_flow_error_set(error, ENOTSUP, ++ RTE_FLOW_ERROR_TYPE_ACTION, ++ actions, ++ "action not supported"); ++ } ++ } ++ return ret; ++} +diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h +new file mode 100644 +index 000000000..f4906b43a +--- /dev/null ++++ b/drivers/net/iavf/iavf_generic_flow.h +@@ -0,0 +1,313 @@ ++/* SPDX-License-Identifier: BSD-3-Clause ++ * Copyright(c) 2019 Intel Corporation ++ */ ++ ++#ifndef _IAVF_GENERIC_FLOW_H_ ++#define _IAVF_GENERIC_FLOW_H_ ++ ++#include ++ ++/* protocol */ ++ ++#define IAVF_PROT_MAC_INNER (1ULL << 1) ++#define IAVF_PROT_MAC_OUTER (1ULL << 2) ++#define IAVF_PROT_VLAN_INNER (1ULL << 3) ++#define IAVF_PROT_VLAN_OUTER (1ULL << 4) ++#define IAVF_PROT_IPV4_INNER (1ULL << 5) ++#define IAVF_PROT_IPV4_OUTER (1ULL << 6) ++#define IAVF_PROT_IPV6_INNER (1ULL << 7) ++#define IAVF_PROT_IPV6_OUTER (1ULL << 8) ++#define IAVF_PROT_TCP_INNER (1ULL << 9) ++#define IAVF_PROT_TCP_OUTER (1ULL << 10) ++#define IAVF_PROT_UDP_INNER (1ULL << 11) ++#define IAVF_PROT_UDP_OUTER (1ULL << 12) ++#define IAVF_PROT_SCTP_INNER (1ULL << 13) ++#define IAVF_PROT_SCTP_OUTER (1ULL << 14) ++#define IAVF_PROT_ICMP4_INNER (1ULL << 15) ++#define IAVF_PROT_ICMP4_OUTER (1ULL << 16) ++#define IAVF_PROT_ICMP6_INNER (1ULL << 17) ++#define IAVF_PROT_ICMP6_OUTER (1ULL << 18) ++#define IAVF_PROT_VXLAN (1ULL << 19) ++#define IAVF_PROT_NVGRE (1ULL << 20) ++#define IAVF_PROT_GTPU (1ULL << 21) ++#define IAVF_PROT_ESP (1ULL << 22) ++#define IAVF_PROT_AH (1ULL << 23) ++#define IAVF_PROT_L2TPV3OIP (1ULL << 24) ++#define IAVF_PROT_PFCP (1ULL << 25) ++ ++ ++/* field */ ++ ++#define IAVF_SMAC (1ULL << 63) ++#define IAVF_DMAC (1ULL << 62) ++#define IAVF_ETHERTYPE (1ULL << 61) ++#define IAVF_IP_SRC (1ULL << 60) ++#define IAVF_IP_DST (1ULL << 59) ++#define IAVF_IP_PROTO (1ULL << 58) ++#define IAVF_IP_TTL (1ULL << 57) ++#define IAVF_IP_TOS (1ULL << 56) ++#define IAVF_SPORT (1ULL << 55) ++#define IAVF_DPORT (1ULL << 54) ++#define IAVF_ICMP_TYPE (1ULL << 53) ++#define IAVF_ICMP_CODE (1ULL << 52) ++#define IAVF_VXLAN_VNI (1ULL << 51) ++#define IAVF_NVGRE_TNI (1ULL << 50) ++#define IAVF_GTPU_TEID (1ULL << 49) ++#define IAVF_GTPU_QFI (1ULL << 48) ++#define IAVF_ESP_SPI (1ULL << 47) ++#define IAVF_AH_SPI (1ULL << 46) ++#define IAVF_L2TPV3OIP_SESSION_ID (1ULL << 45) ++#define IAVF_PFCP_S_FIELD (1ULL << 44) ++#define IAVF_PFCP_SEID (1ULL << 43) ++ ++/* input set */ ++ ++#define IAVF_INSET_NONE 0ULL ++ ++/* non-tunnel */ ++ ++#define IAVF_INSET_SMAC (IAVF_PROT_MAC_OUTER | IAVF_SMAC) ++#define IAVF_INSET_DMAC (IAVF_PROT_MAC_OUTER | IAVF_DMAC) ++#define IAVF_INSET_VLAN_INNER (IAVF_PROT_VLAN_INNER) ++#define IAVF_INSET_VLAN_OUTER (IAVF_PROT_VLAN_OUTER) ++#define IAVF_INSET_ETHERTYPE (IAVF_ETHERTYPE) ++ ++#define IAVF_INSET_IPV4_SRC \ ++ (IAVF_PROT_IPV4_OUTER | IAVF_IP_SRC) ++#define IAVF_INSET_IPV4_DST \ ++ (IAVF_PROT_IPV4_OUTER | IAVF_IP_DST) ++#define IAVF_INSET_IPV4_TOS \ ++ (IAVF_PROT_IPV4_OUTER | IAVF_IP_TOS) ++#define IAVF_INSET_IPV4_PROTO \ ++ (IAVF_PROT_IPV4_OUTER | IAVF_IP_PROTO) ++#define IAVF_INSET_IPV4_TTL \ ++ (IAVF_PROT_IPV4_OUTER | IAVF_IP_TTL) ++#define IAVF_INSET_IPV6_SRC \ ++ (IAVF_PROT_IPV6_OUTER | IAVF_IP_SRC) ++#define IAVF_INSET_IPV6_DST \ ++ (IAVF_PROT_IPV6_OUTER | IAVF_IP_DST) ++#define IAVF_INSET_IPV6_NEXT_HDR \ ++ (IAVF_PROT_IPV6_OUTER | IAVF_IP_PROTO) ++#define IAVF_INSET_IPV6_HOP_LIMIT \ ++ (IAVF_PROT_IPV6_OUTER | IAVF_IP_TTL) ++#define IAVF_INSET_IPV6_TC \ ++ (IAVF_PROT_IPV6_OUTER | IAVF_IP_TOS) ++ ++#define IAVF_INSET_TCP_SRC_PORT \ ++ (IAVF_PROT_TCP_OUTER | IAVF_SPORT) ++#define IAVF_INSET_TCP_DST_PORT \ ++ (IAVF_PROT_TCP_OUTER | IAVF_DPORT) ++#define IAVF_INSET_UDP_SRC_PORT \ ++ (IAVF_PROT_UDP_OUTER | IAVF_SPORT) ++#define IAVF_INSET_UDP_DST_PORT \ ++ (IAVF_PROT_UDP_OUTER | IAVF_DPORT) ++#define IAVF_INSET_SCTP_SRC_PORT \ ++ (IAVF_PROT_SCTP_OUTER | IAVF_SPORT) ++#define IAVF_INSET_SCTP_DST_PORT \ ++ (IAVF_PROT_SCTP_OUTER | IAVF_DPORT) ++#define IAVF_INSET_ICMP4_SRC_PORT \ ++ (IAVF_PROT_ICMP4_OUTER | IAVF_SPORT) ++#define IAVF_INSET_ICMP4_DST_PORT \ ++ (IAVF_PROT_ICMP4_OUTER | IAVF_DPORT) ++#define IAVF_INSET_ICMP6_SRC_PORT \ ++ (IAVF_PROT_ICMP6_OUTER | IAVF_SPORT) ++#define IAVF_INSET_ICMP6_DST_PORT \ ++ (IAVF_PROT_ICMP6_OUTER | IAVF_DPORT) ++#define IAVF_INSET_ICMP4_TYPE \ ++ (IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_TYPE) ++#define IAVF_INSET_ICMP4_CODE \ ++ (IAVF_PROT_ICMP4_OUTER | IAVF_ICMP_CODE) ++#define IAVF_INSET_ICMP6_TYPE \ ++ (IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_TYPE) ++#define IAVF_INSET_ICMP6_CODE \ ++ (IAVF_PROT_ICMP6_OUTER | IAVF_ICMP_CODE) ++#define IAVF_INSET_GTPU_TEID \ ++ (IAVF_PROT_GTPU | IAVF_GTPU_TEID) ++#define IAVF_INSET_GTPU_QFI \ ++ (IAVF_PROT_GTPU | IAVF_GTPU_QFI) ++#define IAVF_INSET_ESP_SPI \ ++ (IAVF_PROT_ESP | IAVF_ESP_SPI) ++#define IAVF_INSET_AH_SPI \ ++ (IAVF_PROT_AH | IAVF_AH_SPI) ++#define IAVF_INSET_L2TPV3OIP_SESSION_ID \ ++ (IAVF_PROT_L2TPV3OIP | IAVF_L2TPV3OIP_SESSION_ID) ++#define IAVF_INSET_PFCP_S_FIELD \ ++ (IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD) ++#define IAVF_INSET_PFCP_SEID \ ++ (IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID) ++ ++ ++/* empty pattern */ ++extern enum rte_flow_item_type iavf_pattern_empty[]; ++ ++/* L2 */ ++extern enum rte_flow_item_type iavf_pattern_ethertype[]; ++extern enum rte_flow_item_type iavf_pattern_ethertype_vlan[]; ++extern enum rte_flow_item_type iavf_pattern_ethertype_qinq[]; ++ ++/* ARP */ ++extern enum rte_flow_item_type iavf_pattern_eth_arp[]; ++ ++/* non-tunnel IPv4 */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_icmp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv4_icmp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv4_icmp[]; ++ ++/* non-tunnel IPv6 */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_sctp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_icmp6[]; ++extern enum rte_flow_item_type iavf_pattern_eth_vlan_ipv6_icmp6[]; ++extern enum rte_flow_item_type iavf_pattern_eth_qinq_ipv6_icmp6[]; ++ ++/* GTPU */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_ipv4[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_gtpu_eh_ipv4_icmp[]; ++ ++/* ESP */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_esp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_esp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_esp[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_esp[]; ++ ++/* AH */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_ah[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_ah[]; ++ ++/* L2TPV3 */ ++extern enum rte_flow_item_type iavf_pattern_eth_ipv4_l2tpv3[]; ++extern enum rte_flow_item_type iavf_pattern_eth_ipv6_l2tpv3[]; ++ ++extern const struct rte_flow_ops iavf_flow_ops; ++ ++/* pattern structure */ ++struct iavf_pattern_match_item { ++ enum rte_flow_item_type *pattern_list; ++ /* pattern_list must end with RTE_FLOW_ITEM_TYPE_END */ ++ uint64_t input_set_mask; ++ void *meta; ++}; ++ ++typedef int (*engine_init_t)(struct iavf_adapter *ad); ++typedef void (*engine_uninit_t)(struct iavf_adapter *ad); ++typedef int (*engine_validation_t)(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ void *meta, ++ struct rte_flow_error *error); ++typedef int (*engine_create_t)(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ void *meta, ++ struct rte_flow_error *error); ++typedef int (*engine_destroy_t)(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ struct rte_flow_error *error); ++typedef int (*engine_query_t)(struct iavf_adapter *ad, ++ struct rte_flow *flow, ++ struct rte_flow_query_count *count, ++ struct rte_flow_error *error); ++typedef void (*engine_free_t) (struct rte_flow *flow); ++typedef int (*parse_pattern_action_t)(struct iavf_adapter *ad, ++ struct iavf_pattern_match_item *array, ++ uint32_t array_len, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ void **meta, ++ struct rte_flow_error *error); ++ ++/* engine types. */ ++enum iavf_flow_engine_type { ++ IAVF_FLOW_ENGINE_NONE = 0, ++ IAVF_FLOW_ENGINE_FDIR, ++ IAVF_FLOW_ENGINE_HASH, ++ IAVF_FLOW_ENGINE_MAX, ++}; ++ ++/** ++ * classification stages. ++ * for non-pipeline mode, we have two classification stages: Distributor/RSS ++ * for pipeline-mode we have three classification stages: ++ * Permission/Distributor/RSS ++ */ ++enum iavf_flow_classification_stage { ++ IAVF_FLOW_STAGE_NONE = 0, ++ IAVF_FLOW_STAGE_RSS, ++ IAVF_FLOW_STAGE_DISTRIBUTOR, ++ IAVF_FLOW_STAGE_MAX, ++}; ++ ++/* Struct to store engine created. */ ++struct iavf_flow_engine { ++ TAILQ_ENTRY(iavf_flow_engine) node; ++ engine_init_t init; ++ engine_uninit_t uninit; ++ engine_validation_t validation; ++ engine_create_t create; ++ engine_destroy_t destroy; ++ engine_query_t query_count; ++ engine_free_t free; ++ enum iavf_flow_engine_type type; ++}; ++ ++TAILQ_HEAD(iavf_engine_list, iavf_flow_engine); ++ ++/* Struct to store flow created. */ ++struct rte_flow { ++ TAILQ_ENTRY(rte_flow) node; ++ struct iavf_flow_engine *engine; ++ void *rule; ++}; ++ ++struct iavf_flow_parser { ++ struct iavf_flow_engine *engine; ++ struct iavf_pattern_match_item *array; ++ uint32_t array_len; ++ parse_pattern_action_t parse_pattern_action; ++ enum iavf_flow_classification_stage stage; ++}; ++ ++/* Struct to store parser created. */ ++struct iavf_flow_parser_node { ++ TAILQ_ENTRY(iavf_flow_parser_node) node; ++ struct iavf_flow_parser *parser; ++}; ++ ++void iavf_register_flow_engine(struct iavf_flow_engine *engine); ++int iavf_flow_init(struct iavf_adapter *ad); ++void iavf_flow_uninit(struct iavf_adapter *ad); ++int iavf_register_parser(struct iavf_flow_parser *parser, ++ struct iavf_adapter *ad); ++void iavf_unregister_parser(struct iavf_flow_parser *parser, ++ struct iavf_adapter *ad); ++struct iavf_pattern_match_item * ++iavf_search_pattern_match_item(const struct rte_flow_item pattern[], ++ struct iavf_pattern_match_item *array, ++ uint32_t array_len, ++ struct rte_flow_error *error); ++#endif +diff --git a/drivers/net/iavf/meson.build b/drivers/net/iavf/meson.build +index dbd0b01db..32eabca4b 100644 +--- a/drivers/net/iavf/meson.build ++++ b/drivers/net/iavf/meson.build +@@ -12,6 +12,7 @@ sources = files( + 'iavf_ethdev.c', + 'iavf_rxtx.c', + 'iavf_vchnl.c', ++ 'iavf_generic_flow.c', + ) + + if arch_subdir == 'x86' +-- +2.17.1 + -- cgit 1.2.3-korg