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