get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/55748/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 55748,
    "url": "http://patches.dpdk.org/api/patches/55748/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/48a5bdc67311ac6ec72de7fb54b3cb99baf52a1e.1561973011.git.motih@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<48a5bdc67311ac6ec72de7fb54b3cb99baf52a1e.1561973011.git.motih@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/48a5bdc67311ac6ec72de7fb54b3cb99baf52a1e.1561973011.git.motih@mellanox.com",
    "date": "2019-07-01T09:34:22",
    "name": "[v6,2/2] net/mlx5: remove TCF support from PMD",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "5f22935d81135376bfc592cd4c1732b6aeddb159",
    "submitter": {
        "id": 748,
        "url": "http://patches.dpdk.org/api/people/748/?format=api",
        "name": "Moti Haimovsky",
        "email": "motih@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/48a5bdc67311ac6ec72de7fb54b3cb99baf52a1e.1561973011.git.motih@mellanox.com/mbox/",
    "series": [
        {
            "id": 5240,
            "url": "http://patches.dpdk.org/api/series/5240/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=5240",
            "date": "2019-07-01T09:34:21",
            "name": "net/mlx5: remove TCF support from PMD",
            "version": 6,
            "mbox": "http://patches.dpdk.org/series/5240/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/55748/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/55748/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7EBF85689;\n\tMon,  1 Jul 2019 11:34:32 +0200 (CEST)",
            "from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130])\n\tby dpdk.org (Postfix) with ESMTP id 397332C60\n\tfor <dev@dpdk.org>; Mon,  1 Jul 2019 11:34:27 +0200 (CEST)"
        ],
        "From": "Moti Haimovsky <motih@mellanox.com>",
        "To": "rasland@mellanox.com,\n\tviacheslavo@mellanox.com",
        "Cc": "dev@dpdk.org",
        "Date": "Mon,  1 Jul 2019 12:34:22 +0300",
        "Message-Id": "<48a5bdc67311ac6ec72de7fb54b3cb99baf52a1e.1561973011.git.motih@mellanox.com>",
        "X-Mailer": "git-send-email 1.7.1",
        "In-Reply-To": "<cover.1561973011.git.motih@mellanox.com>",
        "References": "<cover.1559049191.git.motih@mellanox.com>\n\t<cover.1561973011.git.motih@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v6 2/2] net/mlx5: remove TCF support from PMD",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This commit removes the support of configuring the device E-switch\nusing TCF since it is now possible to configure it via DR (direct\nverbs rules), and by that to also remove the PMD dependency in libmnl.\n\nSigned-off-by: Moti Haimovsky <motih@mellanox.com>\n---\nv6:\n * Rebased on top of latest commits.\n\nv4,v5:\n * Resend the message from a server not inserting DOS line-termination\n   symbols.\n\nv3:\n * Modified patch subject.\n\nv2:\n * Fixed checkpatch warnings.\n---\n doc/guides/nics/mlx5.rst          |   19 -\n doc/guides/platform/bluefield.rst |    4 -\n drivers/net/mlx5/Makefile         |  303 --\n drivers/net/mlx5/meson.build      |  123 +-\n drivers/net/mlx5/mlx5.c           |   32 -\n drivers/net/mlx5/mlx5.h           |    3 -\n drivers/net/mlx5/mlx5_flow.c      |   14 +-\n drivers/net/mlx5/mlx5_flow.h      |   25 -\n drivers/net/mlx5/mlx5_flow_tcf.c  | 6382 -------------------------------------\n mk/rte.app.mk                     |    2 +-\n 10 files changed, 8 insertions(+), 6899 deletions(-)\n delete mode 100644 drivers/net/mlx5/mlx5_flow_tcf.c",
    "diff": "diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst\nindex 87f2763..4cd6cf8 100644\n--- a/doc/guides/nics/mlx5.rst\n+++ b/doc/guides/nics/mlx5.rst\n@@ -551,12 +551,6 @@ DPDK and must be installed separately:\n   This library basically implements send/receive calls to the hardware\n   queues.\n \n-- **libmnl**\n-\n-  Minimalistic Netlink library mainly relied on to manage E-Switch flow\n-  rules (i.e. those with the \"transfer\" attribute and typically involving\n-  port representors).\n-\n - **Kernel modules**\n \n   They provide the kernel-side Verbs API and low level device drivers that\n@@ -652,19 +646,6 @@ required from that distribution.\n    this DPDK release was developed and tested against is strongly\n    recommended. Please check the `prerequisites`_.\n \n-Libmnl\n-^^^^^^\n-\n-Minimal version for libmnl is **1.0.3**.\n-\n-As a dependency of the **iproute2** suite, this library is often installed\n-by default. It is otherwise readily available through standard system\n-packages.\n-\n-Its development headers must be installed in order to compile this PMD.\n-These packages are usually named **libmnl-dev** or **libmnl-devel**\n-depending on the Linux distribution.\n-\n Supported NICs\n --------------\n \ndiff --git a/doc/guides/platform/bluefield.rst b/doc/guides/platform/bluefield.rst\nindex 894db2c..deda675 100644\n--- a/doc/guides/platform/bluefield.rst\n+++ b/doc/guides/platform/bluefield.rst\n@@ -84,7 +84,6 @@ toolchain for ARM64. Base on that, additional header files and libraries are\n required:\n \n    - libibverbs\n-   - libmnl\n    - libmlx5\n    - libnl-3\n    - libnl-route-3\n@@ -105,19 +104,16 @@ tarball for the cross toolchain.\n         # Copy libraries\n         mkdir -p lib64\n         cp -a /lib64/libibverbs* lib64/\n-        cp -a /lib64/libmnl* lib64/\n         cp -a /lib64/libmlx5* lib64/\n         cp -a /lib64/libnl-3* lib64/\n         cp -a /lib64/libnl-route-3* lib64/\n \n         # Copy header files\n         mkdir -p usr/include/infiniband\n-        mkdir -p usr/include/libmnl\n         cp -a /usr/include/infiniband/ib_user_ioctl_verbs.h usr/include/infiniband/\n         cp -a /usr/include/infiniband/mlx5*.h usr/include/infiniband/\n         cp -a /usr/include/infiniband/tm_types.h usr/include/infiniband/\n         cp -a /usr/include/infiniband/verbs*.h usr/include/infiniband/\n-        cp -a /usr/include/libmnl/libmnl.h usr/include/libmnl/\n \n         # Create supplementary tarball\n         popd\ndiff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile\nindex 2694916..619e6b6 100644\n--- a/drivers/net/mlx5/Makefile\n+++ b/drivers/net/mlx5/Makefile\n@@ -32,7 +32,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rss.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mr.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_dv.c\n-SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_tcf.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mp.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c\n@@ -52,7 +51,6 @@ CFLAGS += -D_DEFAULT_SOURCE\n CFLAGS += -D_XOPEN_SOURCE=600\n CFLAGS += $(WERROR_FLAGS)\n CFLAGS += -Wno-strict-prototypes\n-CFLAGS += $(shell command -v pkg-config > /dev/null 2>&1 && pkg-config --cflags libmnl)\n ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y)\n CFLAGS += -DMLX5_GLUE='\"$(LIB_GLUE)\"'\n CFLAGS += -DMLX5_GLUE_VERSION='\"$(LIB_GLUE_VERSION)\"'\n@@ -63,7 +61,6 @@ LDLIBS += $(shell $(RTE_SDK)/buildtools/options-ibverbs-static.sh)\n else\n LDLIBS += -libverbs -lmlx5\n endif\n-LDLIBS += $(shell command -v pkg-config > /dev/null 2>&1 && pkg-config --libs libmnl || echo \"-lmnl\")\n LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring\n LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs\n LDLIBS += -lrte_bus_pci\n@@ -256,306 +253,6 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh\n \t\tenum IFLA_PHYS_PORT_NAME \\\n \t\t$(AUTOCONF_OUTPUT)\n \t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_IFLA_VXLAN_COLLECT_METADATA \\\n-\t\tlinux/if_link.h \\\n-\t\tenum IFLA_VXLAN_COLLECT_METADATA \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_CHAIN \\\n-\t\tlinux/rtnetlink.h \\\n-\t\tenum TCA_CHAIN \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_ACT \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_ACT \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_FLAGS \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_FLAGS \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ETH_TYPE \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ETH_TYPE \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ETH_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ETH_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ETH_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ETH_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ETH_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ETH_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ETH_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ETH_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IP_PROTO \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IP_PROTO \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV4_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV4_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV4_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV4_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV4_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV4_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV4_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV4_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV6_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV6_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV6_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV6_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV6_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV6_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IPV6_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IPV6_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_UDP_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_UDP_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_UDP_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_UDP_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_UDP_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_UDP_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_UDP_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_UDP_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_VLAN_ID \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_VLAN_ID \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_VLAN_PRIO \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_VLAN_PRIO \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_VLAN_ETH_TYPE \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_FLAGS \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_FLAGS \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_TCP_FLAGS_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IP_TOS \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IP_TOS \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IP_TOS_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IP_TOS_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IP_TTL \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IP_TTL \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_IP_TTL_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_IP_TTL_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TC_ACT_GOTO_CHAIN \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tdefine TC_ACT_GOTO_CHAIN \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TC_ACT_VLAN \\\n-\t\tlinux/tc_act/tc_vlan.h \\\n-\t\tenum TCA_VLAN_PUSH_VLAN_PRIORITY \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_KEY_ID \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_KEY_ID \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV4_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV4_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV4_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV4_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV6_SRC \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV6_DST \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV6_DST \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IPV6_DST_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_UDP_SRC_PORT \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_UDP_DST_PORT \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IP_TOS \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IP_TOS \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IP_TOS_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IP_TOS_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IP_TTL \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IP_TTL \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_FLOWER_KEY_ENC_IP_TTL_MASK \\\n-\t\tlinux/pkt_cls.h \\\n-\t\tenum TCA_FLOWER_KEY_ENC_IP_TTL_MASK \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TC_ACT_TUNNEL_KEY \\\n-\t\tlinux/tc_act/tc_tunnel_key.h \\\n-\t\tdefine TCA_ACT_TUNNEL_KEY \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_TUNNEL_KEY_ENC_DST_PORT \\\n-\t\tlinux/tc_act/tc_tunnel_key.h \\\n-\t\tenum TCA_TUNNEL_KEY_ENC_DST_PORT \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_TUNNEL_KEY_ENC_TOS \\\n-\t\tlinux/tc_act/tc_tunnel_key.h \\\n-\t\tenum TCA_TUNNEL_KEY_ENC_TOS \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_TUNNEL_KEY_ENC_TTL \\\n-\t\tlinux/tc_act/tc_tunnel_key.h \\\n-\t\tenum TCA_TUNNEL_KEY_ENC_TTL \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TCA_TUNNEL_KEY_NO_CSUM \\\n-\t\tlinux/tc_act/tc_tunnel_key.h \\\n-\t\tenum TCA_TUNNEL_KEY_NO_CSUM \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n-\t\tHAVE_TC_ACT_PEDIT \\\n-\t\tlinux/tc_act/tc_pedit.h \\\n-\t\tenum TCA_PEDIT_KEY_EX_HDR_TYPE_UDP \\\n-\t\t$(AUTOCONF_OUTPUT)\n-\t$Q sh -- '$<' '$@' \\\n \t\tHAVE_SUPPORTED_40000baseKR4_Full \\\n \t\t/usr/include/linux/ethtool.h \\\n \t\tdefine SUPPORTED_40000baseKR4_Full \\\ndiff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build\nindex ac3b529..4dc5ddd 100644\n--- a/drivers/net/mlx5/meson.build\n+++ b/drivers/net/mlx5/meson.build\n@@ -13,7 +13,7 @@ if pmd_dlopen\n \t\t'-DMLX5_GLUE_VERSION=\"@0@\"'.format(LIB_GLUE_VERSION),\n \t]\n endif\n-libnames = [ 'mnl', 'mlx5', 'ibverbs' ]\n+libnames = [ 'mlx5', 'ibverbs' ]\n libs = []\n build = true\n foreach libname:libnames\n@@ -35,7 +35,6 @@ if build\n \t\t'mlx5_ethdev.c',\n \t\t'mlx5_flow.c',\n \t\t'mlx5_flow_dv.c',\n-\t\t'mlx5_flow_tcf.c',\n \t\t'mlx5_flow_verbs.c',\n \t\t'mlx5_mac.c',\n \t\t'mlx5_mr.c',\n@@ -148,126 +147,6 @@ if build\n \t\t'IFLA_PHYS_SWITCH_ID' ],\n \t\t[ 'HAVE_IFLA_PHYS_PORT_NAME', 'linux/if_link.h',\n \t\t'IFLA_PHYS_PORT_NAME' ],\n-\t\t[ 'HAVE_IFLA_VXLAN_COLLECT_METADATA', 'linux/if_link.h',\n-\t\t'IFLA_VXLAN_COLLECT_METADATA' ],\n-\t\t[ 'HAVE_TCA_CHAIN', 'linux/rtnetlink.h',\n-\t\t'TCA_CHAIN' ],\n-\t\t[ 'HAVE_TCA_FLOWER_ACT', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_ACT' ],\n-\t\t[ 'HAVE_TCA_FLOWER_FLAGS', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_FLAGS' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ETH_TYPE', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ETH_TYPE' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ETH_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ETH_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ETH_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ETH_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ETH_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ETH_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ETH_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ETH_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IP_PROTO', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IP_PROTO' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV4_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV4_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV4_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV4_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV4_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV4_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV4_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV4_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV6_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV6_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV6_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV6_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV6_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV6_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IPV6_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IPV6_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_UDP_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_UDP_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_UDP_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_UDP_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_UDP_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_UDP_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_UDP_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_UDP_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_VLAN_ID', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_VLAN_ID' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_VLAN_PRIO', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_VLAN_PRIO' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_VLAN_ETH_TYPE' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_FLAGS', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_FLAGS' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_TCP_FLAGS_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IP_TOS', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IP_TOS' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IP_TOS_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IP_TOS_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IP_TTL', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IP_TTL' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_IP_TTL_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_IP_TTL_MASK' ],\n-\t\t[ 'HAVE_TC_ACT_GOTO_CHAIN', 'linux/pkt_cls.h',\n-\t\t'TC_ACT_GOTO_CHAIN' ],\n-\t\t[ 'HAVE_TC_ACT_VLAN', 'linux/tc_act/tc_vlan.h',\n-\t\t'TCA_VLAN_PUSH_VLAN_PRIORITY' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_KEY_ID', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_KEY_ID' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV4_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV4_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV4_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV6_SRC' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV6_DST' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IPV6_DST_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_UDP_SRC_PORT' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_UDP_DST_PORT' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IP_TOS', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IP_TOS' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IP_TOS_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IP_TOS_MASK' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IP_TTL', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IP_TTL' ],\n-\t\t[ 'HAVE_TCA_FLOWER_KEY_ENC_IP_TTL_MASK', 'linux/pkt_cls.h',\n-\t\t'TCA_FLOWER_KEY_ENC_IP_TTL_MASK' ],\n-\t\t[ 'HAVE_TC_ACT_TUNNEL_KEY', 'linux/tc_act/tc_tunnel_key.h',\n-\t\t'TCA_ACT_TUNNEL_KEY' ],\n-\t\t[ 'HAVE_TCA_TUNNEL_KEY_ENC_DST_PORT', 'linux/tc_act/tc_tunnel_key.h',\n-\t\t'TCA_TUNNEL_KEY_ENC_DST_PORT' ],\n-\t\t[ 'HAVE_TCA_TUNNEL_KEY_ENC_TOS', 'linux/tc_act/tc_tunnel_key.h',\n-\t\t'TCA_TUNNEL_KEY_ENC_TOS' ],\n-\t\t[ 'HAVE_TCA_TUNNEL_KEY_ENC_TTL', 'linux/tc_act/tc_tunnel_key.h',\n-\t\t'TCA_TUNNEL_KEY_ENC_TTL' ],\n-\t\t[ 'HAVE_TCA_TUNNEL_KEY_NO_CSUM', 'linux/tc_act/tc_tunnel_key.h',\n-\t\t'TCA_TUNNEL_KEY_NO_CSUM' ],\n-\t\t[ 'HAVE_TC_ACT_PEDIT', 'linux/tc_act/tc_pedit.h',\n-\t\t'TCA_PEDIT_KEY_EX_HDR_TYPE_UDP' ],\n \t\t[ 'HAVE_RDMA_NL_NLDEV', 'rdma/rdma_netlink.h',\n \t\t'RDMA_NL_NLDEV' ],\n \t\t[ 'HAVE_RDMA_NLDEV_CMD_GET', 'rdma/rdma_netlink.h',\ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 06a8c67..d93f92d 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -690,8 +690,6 @@ struct mlx5_dev_spawn_data {\n \t\tclose(priv->nl_socket_route);\n \tif (priv->nl_socket_rdma >= 0)\n \t\tclose(priv->nl_socket_rdma);\n-\tif (priv->tcf_context)\n-\t\tmlx5_flow_tcf_context_destroy(priv->tcf_context);\n \tif (priv->sh) {\n \t\t/*\n \t\t * Free the shared context in last turn, because the cleanup\n@@ -1509,34 +1507,6 @@ struct mlx5_dev_spawn_data {\n \tclaim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0));\n \tif (config.vf && config.vf_nl_en)\n \t\tmlx5_nl_mac_addr_sync(eth_dev);\n-\tpriv->tcf_context = mlx5_flow_tcf_context_create();\n-\tif (!priv->tcf_context) {\n-\t\terr = -rte_errno;\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"flow rules relying on switch offloads will not be\"\n-\t\t\t\" supported: cannot open libmnl socket: %s\",\n-\t\t\tstrerror(rte_errno));\n-\t} else {\n-\t\tstruct rte_flow_error error;\n-\t\tunsigned int ifindex = mlx5_ifindex(eth_dev);\n-\n-\t\tif (!ifindex) {\n-\t\t\terr = -rte_errno;\n-\t\t\terror.message =\n-\t\t\t\t\"cannot retrieve network interface index\";\n-\t\t} else {\n-\t\t\terr = mlx5_flow_tcf_init(priv->tcf_context,\n-\t\t\t\t\t\t ifindex, &error);\n-\t\t}\n-\t\tif (err) {\n-\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\"flow rules relying on switch offloads will\"\n-\t\t\t\t\" not be supported: %s: %s\",\n-\t\t\t\terror.message, strerror(rte_errno));\n-\t\t\tmlx5_flow_tcf_context_destroy(priv->tcf_context);\n-\t\t\tpriv->tcf_context = NULL;\n-\t\t}\n-\t}\n \tTAILQ_INIT(&priv->flows);\n \tTAILQ_INIT(&priv->ctrl_flows);\n \t/* Hint libmlx5 to use PMD allocator for data plane resources */\n@@ -1602,8 +1572,6 @@ struct mlx5_dev_spawn_data {\n \t\t\tclose(priv->nl_socket_route);\n \t\tif (priv->nl_socket_rdma >= 0)\n \t\t\tclose(priv->nl_socket_rdma);\n-\t\tif (priv->tcf_context)\n-\t\t\tmlx5_flow_tcf_context_destroy(priv->tcf_context);\n \t\tif (own_domain_id)\n \t\t\tclaim_zero(rte_eth_switch_domain_free(priv->domain_id));\n \t\trte_free(priv);\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex a3689c8..e6d24d7 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -247,8 +247,6 @@ struct mlx5_drop {\n \tstruct mlx5_rxq_ibv *rxq; /* Verbs Rx queue. */\n };\n \n-struct mlx5_flow_tcf_context;\n-\n /* Per port data of shared IB device. */\n struct mlx5_ibv_shared_port {\n \tuint32_t ih_port_id;\n@@ -392,7 +390,6 @@ struct mlx5_priv {\n \trte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];\n \t/* UAR same-page access control required in 32bit implementations. */\n #endif\n-\tstruct mlx5_flow_tcf_context *tcf_context; /* TC flower context. */\n };\n \n #define PORT_ID(priv) ((priv)->dev_data->port_id)\ndiff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c\nindex 251da41..cd04c44 100644\n--- a/drivers/net/mlx5/mlx5_flow.c\n+++ b/drivers/net/mlx5/mlx5_flow.c\n@@ -42,7 +42,6 @@\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n extern const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops;\n #endif\n-extern const struct mlx5_flow_driver_ops mlx5_flow_tcf_drv_ops;\n extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops;\n \n const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops;\n@@ -52,7 +51,6 @@\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n \t[MLX5_FLOW_TYPE_DV] = &mlx5_flow_dv_drv_ops,\n #endif\n-\t[MLX5_FLOW_TYPE_TCF] = &mlx5_flow_tcf_drv_ops,\n \t[MLX5_FLOW_TYPE_VERBS] = &mlx5_flow_verbs_drv_ops,\n \t[MLX5_FLOW_TYPE_MAX] = &mlx5_flow_null_drv_ops\n };\n@@ -1037,7 +1035,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,\n \t\t\t\t\t  \"egress is not supported\");\n-\tif (attributes->transfer)\n+\tif (attributes->transfer && !priv->config.dv_esw_en)\n \t\treturn rte_flow_error_set(error, ENOTSUP,\n \t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,\n \t\t\t\t\t  NULL, \"transfer is not supported\");\n@@ -1294,7 +1292,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n  * @param[in] target_protocol\n  *   The next protocol in the previous item.\n  * @param[in] flow_mask\n- *   mlx5 flow-specific (TCF, DV, verbs, etc.) supported header fields mask.\n+ *   mlx5 flow-specific (DV, verbs, etc.) supported header fields mask.\n  * @param[out] error\n  *   Pointer to error structure.\n  *\n@@ -1784,9 +1782,9 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n \tstruct mlx5_priv *priv = dev->data->dev_private;\n \tenum mlx5_flow_drv_type type = MLX5_FLOW_TYPE_MAX;\n \n-\tif (attr->transfer && !priv->config.dv_esw_en)\n-\t\ttype = MLX5_FLOW_TYPE_TCF;\n-\telse\n+\tif (attr->transfer && priv->config.dv_esw_en)\n+\t\ttype = MLX5_FLOW_TYPE_DV;\n+\tif (!attr->transfer)\n \t\ttype = priv->config.dv_flow_en ? MLX5_FLOW_TYPE_DV :\n \t\t\t\t\t\t MLX5_FLOW_TYPE_VERBS;\n \treturn type;\n@@ -1833,7 +1831,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,\n  * initializes the device flow and returns the pointer.\n  *\n  * @note\n- *   This function initializes device flow structure such as dv, tcf or verbs in\n+ *   This function initializes device flow structure such as dv or verbs in\n  *   struct mlx5_flow. However, it is caller's responsibility to initialize the\n  *   rest. For example, adding returning device flow to flow->dev_flow list and\n  *   setting backward reference to the flow should be done out of this function.\ndiff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h\nindex b665420..65cfdbd 100644\n--- a/drivers/net/mlx5/mlx5_flow.h\n+++ b/drivers/net/mlx5/mlx5_flow.h\n@@ -188,7 +188,6 @@\n enum mlx5_flow_drv_type {\n \tMLX5_FLOW_TYPE_MIN,\n \tMLX5_FLOW_TYPE_DV,\n-\tMLX5_FLOW_TYPE_TCF,\n \tMLX5_FLOW_TYPE_VERBS,\n \tMLX5_FLOW_TYPE_MAX,\n };\n@@ -309,22 +308,6 @@ struct mlx5_flow_dv {\n \tint actions_n; /**< number of actions. */\n };\n \n-/** Linux TC flower driver for E-Switch flow. */\n-struct mlx5_flow_tcf {\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\tuint32_t *ptc_flags; /**< tc rule applied flags. */\n-\tunion { /**< Tunnel encap/decap descriptor. */\n-\t\tstruct flow_tcf_tunnel_hdr *tunnel;\n-\t\tstruct flow_tcf_vxlan_decap *vxlan_decap;\n-\t\tstruct flow_tcf_vxlan_encap *vxlan_encap;\n-\t};\n-\tuint32_t applied:1; /**< Whether rule is currently applied. */\n-#ifndef NDEBUG\n-\tuint32_t nlsize; /**< Size of NL message buffer for debug check. */\n-#endif\n-};\n-\n /* Verbs specification header. */\n struct ibv_spec_header {\n \tenum ibv_flow_spec_type type;\n@@ -355,7 +338,6 @@ struct mlx5_flow {\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n \t\tstruct mlx5_flow_dv dv;\n #endif\n-\t\tstruct mlx5_flow_tcf tcf;\n \t\tstruct mlx5_flow_verbs verbs;\n \t};\n };\n@@ -513,11 +495,4 @@ int mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,\n \t\t\t\t      struct rte_eth_dev *dev,\n \t\t\t\t      struct rte_flow_error *error);\n \n-/* mlx5_flow_tcf.c */\n-\n-int mlx5_flow_tcf_init(struct mlx5_flow_tcf_context *ctx,\n-\t\t       unsigned int ifindex, struct rte_flow_error *error);\n-struct mlx5_flow_tcf_context *mlx5_flow_tcf_context_create(void);\n-void mlx5_flow_tcf_context_destroy(struct mlx5_flow_tcf_context *ctx);\n-\n #endif /* RTE_PMD_MLX5_FLOW_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_flow_tcf.c b/drivers/net/mlx5/mlx5_flow_tcf.c\ndeleted file mode 100644\nindex 223ee4f..0000000\n--- a/drivers/net/mlx5/mlx5_flow_tcf.c\n+++ /dev/null\n@@ -1,6382 +0,0 @@\n-/* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright 2018 6WIND S.A.\n- * Copyright 2018 Mellanox Technologies, Ltd\n- */\n-\n-#include <assert.h>\n-#include <errno.h>\n-#include <libmnl/libmnl.h>\n-#include <linux/gen_stats.h>\n-#include <linux/if_ether.h>\n-#include <linux/netlink.h>\n-#include <linux/pkt_cls.h>\n-#include <linux/pkt_sched.h>\n-#include <linux/rtnetlink.h>\n-#include <linux/tc_act/tc_gact.h>\n-#include <linux/tc_act/tc_mirred.h>\n-#include <netinet/in.h>\n-#include <stdalign.h>\n-#include <stdbool.h>\n-#include <stddef.h>\n-#include <stdint.h>\n-#include <stdlib.h>\n-#include <sys/socket.h>\n-\n-#include <rte_byteorder.h>\n-#include <rte_errno.h>\n-#include <rte_ether.h>\n-#include <rte_flow.h>\n-#include <rte_malloc.h>\n-#include <rte_common.h>\n-#include <rte_cycles.h>\n-\n-#include \"mlx5.h\"\n-#include \"mlx5_flow.h\"\n-#include \"mlx5_autoconf.h\"\n-\n-#ifdef HAVE_TC_ACT_VLAN\n-\n-#include <linux/tc_act/tc_vlan.h>\n-\n-#else /* HAVE_TC_ACT_VLAN */\n-\n-#define TCA_VLAN_ACT_POP 1\n-#define TCA_VLAN_ACT_PUSH 2\n-#define TCA_VLAN_ACT_MODIFY 3\n-#define TCA_VLAN_PARMS 2\n-#define TCA_VLAN_PUSH_VLAN_ID 3\n-#define TCA_VLAN_PUSH_VLAN_PROTOCOL 4\n-#define TCA_VLAN_PAD 5\n-#define TCA_VLAN_PUSH_VLAN_PRIORITY 6\n-\n-struct tc_vlan {\n-\ttc_gen;\n-\tint v_action;\n-};\n-\n-#endif /* HAVE_TC_ACT_VLAN */\n-\n-#ifdef HAVE_TC_ACT_PEDIT\n-\n-#include <linux/tc_act/tc_pedit.h>\n-\n-#else /* HAVE_TC_ACT_VLAN */\n-\n-enum {\n-\tTCA_PEDIT_UNSPEC,\n-\tTCA_PEDIT_TM,\n-\tTCA_PEDIT_PARMS,\n-\tTCA_PEDIT_PAD,\n-\tTCA_PEDIT_PARMS_EX,\n-\tTCA_PEDIT_KEYS_EX,\n-\tTCA_PEDIT_KEY_EX,\n-\t__TCA_PEDIT_MAX\n-};\n-\n-enum {\n-\tTCA_PEDIT_KEY_EX_HTYPE = 1,\n-\tTCA_PEDIT_KEY_EX_CMD = 2,\n-\t__TCA_PEDIT_KEY_EX_MAX\n-};\n-\n-enum pedit_header_type {\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = 0,\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_ETH = 1,\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_IP4 = 2,\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_IP6 = 3,\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_TCP = 4,\n-\tTCA_PEDIT_KEY_EX_HDR_TYPE_UDP = 5,\n-\t__PEDIT_HDR_TYPE_MAX,\n-};\n-\n-enum pedit_cmd {\n-\tTCA_PEDIT_KEY_EX_CMD_SET = 0,\n-\tTCA_PEDIT_KEY_EX_CMD_ADD = 1,\n-\t__PEDIT_CMD_MAX,\n-};\n-\n-struct tc_pedit_key {\n-\t__u32 mask; /* AND */\n-\t__u32 val; /*XOR */\n-\t__u32 off; /*offset */\n-\t__u32 at;\n-\t__u32 offmask;\n-\t__u32 shift;\n-};\n-\n-__extension__\n-struct tc_pedit_sel {\n-\ttc_gen;\n-\tunsigned char nkeys;\n-\tunsigned char flags;\n-\tstruct tc_pedit_key keys[0];\n-};\n-\n-#endif /* HAVE_TC_ACT_VLAN */\n-\n-#ifdef HAVE_TC_ACT_TUNNEL_KEY\n-\n-#include <linux/tc_act/tc_tunnel_key.h>\n-\n-#ifndef HAVE_TCA_TUNNEL_KEY_ENC_DST_PORT\n-#define TCA_TUNNEL_KEY_ENC_DST_PORT 9\n-#endif\n-\n-#ifndef HAVE_TCA_TUNNEL_KEY_NO_CSUM\n-#define TCA_TUNNEL_KEY_NO_CSUM 10\n-#endif\n-\n-#ifndef HAVE_TCA_TUNNEL_KEY_ENC_TOS\n-#define TCA_TUNNEL_KEY_ENC_TOS 12\n-#endif\n-\n-#ifndef\tHAVE_TCA_TUNNEL_KEY_ENC_TTL\n-#define TCA_TUNNEL_KEY_ENC_TTL 13\n-#endif\n-\n-#else /* HAVE_TC_ACT_TUNNEL_KEY */\n-\n-#define TCA_ACT_TUNNEL_KEY 17\n-#define TCA_TUNNEL_KEY_ACT_SET 1\n-#define TCA_TUNNEL_KEY_ACT_RELEASE 2\n-#define TCA_TUNNEL_KEY_PARMS 2\n-#define TCA_TUNNEL_KEY_ENC_IPV4_SRC 3\n-#define TCA_TUNNEL_KEY_ENC_IPV4_DST 4\n-#define TCA_TUNNEL_KEY_ENC_IPV6_SRC 5\n-#define TCA_TUNNEL_KEY_ENC_IPV6_DST 6\n-#define TCA_TUNNEL_KEY_ENC_KEY_ID 7\n-#define TCA_TUNNEL_KEY_ENC_DST_PORT 9\n-#define TCA_TUNNEL_KEY_NO_CSUM 10\n-#define TCA_TUNNEL_KEY_ENC_TOS 12\n-#define TCA_TUNNEL_KEY_ENC_TTL 13\n-\n-struct tc_tunnel_key {\n-\ttc_gen;\n-\tint t_action;\n-};\n-\n-#endif /* HAVE_TC_ACT_TUNNEL_KEY */\n-\n-/* Normally found in linux/netlink.h. */\n-#ifndef NETLINK_CAP_ACK\n-#define NETLINK_CAP_ACK 10\n-#endif\n-\n-/* Normally found in linux/pkt_sched.h. */\n-#ifndef TC_H_MIN_INGRESS\n-#define TC_H_MIN_INGRESS 0xfff2u\n-#endif\n-\n-/* Normally found in linux/pkt_cls.h. */\n-#ifndef TCA_CLS_FLAGS_SKIP_SW\n-#define TCA_CLS_FLAGS_SKIP_SW (1 << 1)\n-#endif\n-#ifndef TCA_CLS_FLAGS_IN_HW\n-#define TCA_CLS_FLAGS_IN_HW (1 << 2)\n-#endif\n-#ifndef HAVE_TCA_CHAIN\n-#define TCA_CHAIN 11\n-#endif\n-#ifndef HAVE_TCA_FLOWER_ACT\n-#define TCA_FLOWER_ACT 3\n-#endif\n-#ifndef HAVE_TCA_FLOWER_FLAGS\n-#define TCA_FLOWER_FLAGS 22\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ETH_TYPE\n-#define TCA_FLOWER_KEY_ETH_TYPE 8\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ETH_DST\n-#define TCA_FLOWER_KEY_ETH_DST 4\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ETH_DST_MASK\n-#define TCA_FLOWER_KEY_ETH_DST_MASK 5\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ETH_SRC\n-#define TCA_FLOWER_KEY_ETH_SRC 6\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ETH_SRC_MASK\n-#define TCA_FLOWER_KEY_ETH_SRC_MASK 7\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IP_PROTO\n-#define TCA_FLOWER_KEY_IP_PROTO 9\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV4_SRC\n-#define TCA_FLOWER_KEY_IPV4_SRC 10\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV4_SRC_MASK\n-#define TCA_FLOWER_KEY_IPV4_SRC_MASK 11\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV4_DST\n-#define TCA_FLOWER_KEY_IPV4_DST 12\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV4_DST_MASK\n-#define TCA_FLOWER_KEY_IPV4_DST_MASK 13\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV6_SRC\n-#define TCA_FLOWER_KEY_IPV6_SRC 14\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV6_SRC_MASK\n-#define TCA_FLOWER_KEY_IPV6_SRC_MASK 15\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV6_DST\n-#define TCA_FLOWER_KEY_IPV6_DST 16\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IPV6_DST_MASK\n-#define TCA_FLOWER_KEY_IPV6_DST_MASK 17\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_SRC\n-#define TCA_FLOWER_KEY_TCP_SRC 18\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_SRC_MASK\n-#define TCA_FLOWER_KEY_TCP_SRC_MASK 35\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_DST\n-#define TCA_FLOWER_KEY_TCP_DST 19\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_DST_MASK\n-#define TCA_FLOWER_KEY_TCP_DST_MASK 36\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_UDP_SRC\n-#define TCA_FLOWER_KEY_UDP_SRC 20\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_UDP_SRC_MASK\n-#define TCA_FLOWER_KEY_UDP_SRC_MASK 37\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_UDP_DST\n-#define TCA_FLOWER_KEY_UDP_DST 21\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_UDP_DST_MASK\n-#define TCA_FLOWER_KEY_UDP_DST_MASK 38\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_VLAN_ID\n-#define TCA_FLOWER_KEY_VLAN_ID 23\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_VLAN_PRIO\n-#define TCA_FLOWER_KEY_VLAN_PRIO 24\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE\n-#define TCA_FLOWER_KEY_VLAN_ETH_TYPE 25\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_KEY_ID\n-#define TCA_FLOWER_KEY_ENC_KEY_ID 26\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC\n-#define TCA_FLOWER_KEY_ENC_IPV4_SRC 27\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK\n-#define TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK 28\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST\n-#define TCA_FLOWER_KEY_ENC_IPV4_DST 29\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV4_DST_MASK\n-#define TCA_FLOWER_KEY_ENC_IPV4_DST_MASK 30\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC\n-#define TCA_FLOWER_KEY_ENC_IPV6_SRC 31\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK\n-#define TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK 32\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST\n-#define TCA_FLOWER_KEY_ENC_IPV6_DST 33\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_IPV6_DST_MASK\n-#define TCA_FLOWER_KEY_ENC_IPV6_DST_MASK 34\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT\n-#define TCA_FLOWER_KEY_ENC_UDP_SRC_PORT 43\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK\n-#define TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK 44\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT\n-#define TCA_FLOWER_KEY_ENC_UDP_DST_PORT 45\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK\n-#define TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK 46\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_FLAGS\n-#define TCA_FLOWER_KEY_TCP_FLAGS 71\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_TCP_FLAGS_MASK\n-#define TCA_FLOWER_KEY_TCP_FLAGS_MASK 72\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_IP_TOS\n-#define\tTCA_FLOWER_KEY_IP_TOS 73\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_IP_TOS_MASK\n-#define TCA_FLOWER_KEY_IP_TOS_MASK 74\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_IP_TTL\n-#define TCA_FLOWER_KEY_IP_TTL 75\n-#endif\n-#ifndef HAVE_TCA_FLOWER_KEY_IP_TTL_MASK\n-#define TCA_FLOWER_KEY_IP_TTL_MASK 76\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_ENC_IP_TOS\n-#define TCA_FLOWER_KEY_ENC_IP_TOS 80\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_ENC_IP_TOS_MASK\n-#define TCA_FLOWER_KEY_ENC_IP_TOS_MASK 81\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_ENC_IP_TTL\n-#define\tTCA_FLOWER_KEY_ENC_IP_TTL 82\n-#endif\n-#ifndef\tHAVE_TCA_FLOWER_KEY_ENC_IP_TTL_MASK\n-#define TCA_FLOWER_KEY_ENC_IP_TTL_MASK 83\n-#endif\n-\n-#ifndef HAVE_TC_ACT_GOTO_CHAIN\n-#define TC_ACT_GOTO_CHAIN 0x20000000\n-#endif\n-\n-#ifndef IPV6_ADDR_LEN\n-#define IPV6_ADDR_LEN 16\n-#endif\n-\n-#ifndef IPV4_ADDR_LEN\n-#define IPV4_ADDR_LEN 4\n-#endif\n-\n-#ifndef TP_PORT_LEN\n-#define TP_PORT_LEN 2 /* Transport Port (UDP/TCP) Length */\n-#endif\n-\n-#ifndef TTL_LEN\n-#define TTL_LEN 1\n-#endif\n-\n-#ifndef TCA_ACT_MAX_PRIO\n-#define TCA_ACT_MAX_PRIO 32\n-#endif\n-\n-/** Parameters of VXLAN devices created by driver. */\n-#define MLX5_VXLAN_DEFAULT_VNI\t1\n-#define MLX5_VXLAN_DEVICE_PFX \"vmlx_\"\n-/**\n- * Timeout in milliseconds to wait VXLAN UDP offloaded port\n- * registration  completed within the mlx5 driver.\n- */\n-#define MLX5_VXLAN_WAIT_PORT_REG_MS 250\n-\n-/** Tunnel action type, used for @p type in header structure. */\n-enum flow_tcf_tunact_type {\n-\tFLOW_TCF_TUNACT_VXLAN_DECAP,\n-\tFLOW_TCF_TUNACT_VXLAN_ENCAP,\n-};\n-\n-/** Flags used for @p mask in tunnel action encap descriptors. */\n-#define FLOW_TCF_ENCAP_ETH_SRC (1u << 0)\n-#define FLOW_TCF_ENCAP_ETH_DST (1u << 1)\n-#define FLOW_TCF_ENCAP_IPV4_SRC (1u << 2)\n-#define FLOW_TCF_ENCAP_IPV4_DST (1u << 3)\n-#define FLOW_TCF_ENCAP_IPV6_SRC (1u << 4)\n-#define FLOW_TCF_ENCAP_IPV6_DST (1u << 5)\n-#define FLOW_TCF_ENCAP_UDP_SRC (1u << 6)\n-#define FLOW_TCF_ENCAP_UDP_DST (1u << 7)\n-#define FLOW_TCF_ENCAP_VXLAN_VNI (1u << 8)\n-#define FLOW_TCF_ENCAP_IP_TTL (1u << 9)\n-#define FLOW_TCF_ENCAP_IP_TOS (1u << 10)\n-\n-/**\n- * Structure for holding netlink context.\n- * Note the size of the message buffer which is MNL_SOCKET_BUFFER_SIZE.\n- * Using this (8KB) buffer size ensures that netlink messages will never be\n- * truncated.\n- */\n-struct mlx5_flow_tcf_context {\n-\tstruct mnl_socket *nl; /* NETLINK_ROUTE libmnl socket. */\n-\tuint32_t seq; /* Message sequence number. */\n-\tuint32_t buf_size; /* Message buffer size. */\n-\tuint8_t *buf; /* Message buffer. */\n-};\n-\n-/**\n- * Neigh rule structure. The neigh rule is applied via Netlink to\n- * outer tunnel iface in order to provide destination MAC address\n- * for the VXLAN encapsultion. The neigh rule is implicitly related\n- * to the Flow itself and can be shared by multiple Flows.\n- */\n-struct tcf_neigh_rule {\n-\tLIST_ENTRY(tcf_neigh_rule) next;\n-\tuint32_t refcnt;\n-\tstruct rte_ether_addr eth;\n-\tuint16_t mask;\n-\tunion {\n-\t\tstruct {\n-\t\t\trte_be32_t dst;\n-\t\t} ipv4;\n-\t\tstruct {\n-\t\t\tuint8_t dst[IPV6_ADDR_LEN];\n-\t\t} ipv6;\n-\t};\n-};\n-\n-/**\n- * Local rule structure. The local rule is applied via Netlink to\n- * outer tunnel iface in order to provide local and peer IP addresses\n- * of the VXLAN tunnel for encapsulation. The local rule is implicitly\n- * related to the Flow itself and can be shared by multiple Flows.\n- */\n-struct tcf_local_rule {\n-\tLIST_ENTRY(tcf_local_rule) next;\n-\tuint32_t refcnt;\n-\tuint16_t mask;\n-\tunion {\n-\t\tstruct {\n-\t\t\trte_be32_t dst;\n-\t\t\trte_be32_t src;\n-\t\t} ipv4;\n-\t\tstruct {\n-\t\t\tuint8_t dst[IPV6_ADDR_LEN];\n-\t\t\tuint8_t src[IPV6_ADDR_LEN];\n-\t\t} ipv6;\n-\t};\n-};\n-\n-/** Outer interface VXLAN encapsulation rules container. */\n-struct tcf_irule {\n-\tLIST_ENTRY(tcf_irule) next;\n-\tLIST_HEAD(, tcf_neigh_rule) neigh;\n-\tLIST_HEAD(, tcf_local_rule) local;\n-\tuint32_t refcnt;\n-\tunsigned int ifouter; /**< Own interface index. */\n-};\n-\n-/** VXLAN virtual netdev. */\n-struct tcf_vtep {\n-\tLIST_ENTRY(tcf_vtep) next;\n-\tuint32_t refcnt;\n-\tunsigned int ifindex; /**< Own interface index. */\n-\tuint16_t port;\n-\tuint32_t created:1; /**< Actually created by PMD. */\n-\tuint32_t waitreg:1; /**< Wait for VXLAN UDP port registration. */\n-};\n-\n-/** Tunnel descriptor header, common for all tunnel types. */\n-struct flow_tcf_tunnel_hdr {\n-\tuint32_t type; /**< Tunnel action type. */\n-\tstruct tcf_vtep *vtep; /**< Virtual tunnel endpoint device. */\n-\tunsigned int ifindex_org; /**< Original dst/src interface */\n-\tunsigned int *ifindex_ptr; /**< Interface ptr in message. */\n-};\n-\n-struct flow_tcf_vxlan_decap {\n-\tstruct flow_tcf_tunnel_hdr hdr;\n-\tuint16_t udp_port;\n-};\n-\n-struct flow_tcf_vxlan_encap {\n-\tstruct flow_tcf_tunnel_hdr hdr;\n-\tstruct tcf_irule *iface;\n-\tuint32_t mask;\n-\tuint8_t ip_tos;\n-\tuint8_t ip_ttl_hop;\n-\tstruct {\n-\t\tstruct rte_ether_addr dst;\n-\t\tstruct rte_ether_addr src;\n-\t} eth;\n-\tunion {\n-\t\tstruct {\n-\t\t\trte_be32_t dst;\n-\t\t\trte_be32_t src;\n-\t\t} ipv4;\n-\t\tstruct {\n-\t\t\tuint8_t dst[IPV6_ADDR_LEN];\n-\t\t\tuint8_t src[IPV6_ADDR_LEN];\n-\t\t} ipv6;\n-\t};\n-\tstruct {\n-\t\trte_be16_t src;\n-\t\trte_be16_t dst;\n-\t} udp;\n-\tstruct {\n-\t\tuint8_t vni[3];\n-\t} vxlan;\n-};\n-\n-/** Structure used when extracting the values of a flow counters\n- * from a netlink message.\n- */\n-struct flow_tcf_stats_basic {\n-\tbool valid;\n-\tstruct gnet_stats_basic counters;\n-};\n-\n-/** Empty masks for known item types. */\n-static const union {\n-\tstruct rte_flow_item_port_id port_id;\n-\tstruct rte_flow_item_eth eth;\n-\tstruct rte_flow_item_vlan vlan;\n-\tstruct rte_flow_item_ipv4 ipv4;\n-\tstruct rte_flow_item_ipv6 ipv6;\n-\tstruct rte_flow_item_tcp tcp;\n-\tstruct rte_flow_item_udp udp;\n-\tstruct rte_flow_item_vxlan vxlan;\n-} flow_tcf_mask_empty = {\n-\t{0},\n-};\n-\n-/** Supported masks for known item types. */\n-static const struct {\n-\tstruct rte_flow_item_port_id port_id;\n-\tstruct rte_flow_item_eth eth;\n-\tstruct rte_flow_item_vlan vlan;\n-\tstruct rte_flow_item_ipv4 ipv4;\n-\tstruct rte_flow_item_ipv6 ipv6;\n-\tstruct rte_flow_item_tcp tcp;\n-\tstruct rte_flow_item_udp udp;\n-\tstruct rte_flow_item_vxlan vxlan;\n-} flow_tcf_mask_supported = {\n-\t.port_id = {\n-\t\t.id = 0xffffffff,\n-\t},\n-\t.eth = {\n-\t\t.type = RTE_BE16(0xffff),\n-\t\t.dst.addr_bytes = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n-\t\t.src.addr_bytes = \"\\xff\\xff\\xff\\xff\\xff\\xff\",\n-\t},\n-\t.vlan = {\n-\t\t/* PCP and VID only, no DEI. */\n-\t\t.tci = RTE_BE16(0xefff),\n-\t\t.inner_type = RTE_BE16(0xffff),\n-\t},\n-\t.ipv4.hdr = {\n-\t\t.next_proto_id = 0xff,\n-\t\t.time_to_live = 0xff,\n-\t\t.type_of_service = 0xff,\n-\t\t.src_addr = RTE_BE32(0xffffffff),\n-\t\t.dst_addr = RTE_BE32(0xffffffff),\n-\t},\n-\t.ipv6.hdr = {\n-\t\t.proto = 0xff,\n-\t\t.vtc_flow = RTE_BE32(0xfful << RTE_IPV6_HDR_FL_SHIFT),\n-\t\t.hop_limits = 0xff,\n-\t\t.src_addr =\n-\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n-\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\",\n-\t\t.dst_addr =\n-\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n-\t\t\t\"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\",\n-\t},\n-\t.tcp.hdr = {\n-\t\t.src_port = RTE_BE16(0xffff),\n-\t\t.dst_port = RTE_BE16(0xffff),\n-\t\t.tcp_flags = 0xff,\n-\t},\n-\t.udp.hdr = {\n-\t\t.src_port = RTE_BE16(0xffff),\n-\t\t.dst_port = RTE_BE16(0xffff),\n-\t},\n-\t.vxlan = {\n-\t       .vni = \"\\xff\\xff\\xff\",\n-\t},\n-};\n-\n-#define SZ_NLATTR_HDR MNL_ALIGN(sizeof(struct nlattr))\n-#define SZ_NLATTR_NEST SZ_NLATTR_HDR\n-#define SZ_NLATTR_DATA_OF(len) MNL_ALIGN(SZ_NLATTR_HDR + (len))\n-#define SZ_NLATTR_TYPE_OF(typ) SZ_NLATTR_DATA_OF(sizeof(typ))\n-#define SZ_NLATTR_STRZ_OF(str) SZ_NLATTR_DATA_OF(strlen(str) + 1)\n-\n-#define PTOI_TABLE_SZ_MAX(dev) (mlx5_dev_to_port_id((dev)->device, NULL, 0) + 2)\n-\n-/** DPDK port to network interface index (ifindex) conversion. */\n-struct flow_tcf_ptoi {\n-\tuint16_t port_id; /**< DPDK port ID. */\n-\tunsigned int ifindex; /**< Network interface index. */\n-};\n-\n-/* Due to a limitation on driver/FW. */\n-#define MLX5_TCF_GROUP_ID_MAX 3\n-\n-/*\n- * Due to a limitation on driver/FW, priority ranges from 1 to 16 in kernel.\n- * Priority in rte_flow attribute starts from 0 and is added by 1 in\n- * translation. This is subject to be changed to determine the max priority\n- * based on trial-and-error like Verbs driver once the restriction is lifted or\n- * the range is extended.\n- */\n-#define MLX5_TCF_GROUP_PRIORITY_MAX 15\n-\n-#define MLX5_TCF_FATE_ACTIONS \\\n-\t(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_PORT_ID | \\\n-\t MLX5_FLOW_ACTION_JUMP)\n-\n-#define MLX5_TCF_VLAN_ACTIONS \\\n-\t(MLX5_FLOW_ACTION_OF_POP_VLAN | MLX5_FLOW_ACTION_OF_PUSH_VLAN | \\\n-\t MLX5_FLOW_ACTION_OF_SET_VLAN_VID | MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)\n-\n-#define MLX5_TCF_VXLAN_ACTIONS \\\n-\t(MLX5_FLOW_ACTION_VXLAN_ENCAP | MLX5_FLOW_ACTION_VXLAN_DECAP)\n-\n-#define MLX5_TCF_PEDIT_ACTIONS \\\n-\t(MLX5_FLOW_ACTION_SET_IPV4_SRC | MLX5_FLOW_ACTION_SET_IPV4_DST | \\\n-\t MLX5_FLOW_ACTION_SET_IPV6_SRC | MLX5_FLOW_ACTION_SET_IPV6_DST | \\\n-\t MLX5_FLOW_ACTION_SET_TP_SRC | MLX5_FLOW_ACTION_SET_TP_DST | \\\n-\t MLX5_FLOW_ACTION_SET_TTL | MLX5_FLOW_ACTION_DEC_TTL | \\\n-\t MLX5_FLOW_ACTION_SET_MAC_SRC | MLX5_FLOW_ACTION_SET_MAC_DST)\n-\n-#define MLX5_TCF_CONFIG_ACTIONS \\\n-\t(MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_JUMP | \\\n-\t MLX5_FLOW_ACTION_OF_PUSH_VLAN | MLX5_FLOW_ACTION_OF_SET_VLAN_VID | \\\n-\t MLX5_FLOW_ACTION_OF_SET_VLAN_PCP | \\\n-\t (MLX5_TCF_PEDIT_ACTIONS & ~MLX5_FLOW_ACTION_DEC_TTL))\n-\n-#define MAX_PEDIT_KEYS 128\n-#define SZ_PEDIT_KEY_VAL 4\n-\n-#define NUM_OF_PEDIT_KEYS(sz) \\\n-\t(((sz) / SZ_PEDIT_KEY_VAL) + (((sz) % SZ_PEDIT_KEY_VAL) ? 1 : 0))\n-\n-struct pedit_key_ex {\n-\tenum pedit_header_type htype;\n-\tenum pedit_cmd cmd;\n-};\n-\n-struct pedit_parser {\n-\tstruct tc_pedit_sel sel;\n-\tstruct tc_pedit_key keys[MAX_PEDIT_KEYS];\n-\tstruct pedit_key_ex keys_ex[MAX_PEDIT_KEYS];\n-};\n-\n-/**\n- * Create space for using the implicitly created TC flow counter.\n- *\n- * @param[in] dev\n- *   Pointer to the Ethernet device structure.\n- *\n- * @return\n- *   A pointer to the counter data structure, NULL otherwise and\n- *   rte_errno is set.\n- */\n-static struct mlx5_flow_counter *\n-flow_tcf_counter_new(void)\n-{\n-\tstruct mlx5_flow_counter *cnt;\n-\n-\t/*\n-\t * eswitch counter cannot be shared and its id is unknown.\n-\t * currently returning all with id 0.\n-\t * in the future maybe better to switch to unique numbers.\n-\t */\n-\tstruct mlx5_flow_counter tmpl = {\n-\t\t.ref_cnt = 1,\n-\t};\n-\tcnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);\n-\tif (!cnt) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn NULL;\n-\t}\n-\t*cnt = tmpl;\n-\t/* Implicit counter, do not add to list. */\n-\treturn cnt;\n-}\n-\n-/**\n- * Set pedit key of MAC address\n- *\n- * @param[in] actions\n- *   pointer to action specification\n- * @param[in,out] p_parser\n- *   pointer to pedit_parser\n- */\n-static void\n-flow_tcf_pedit_key_set_mac(const struct rte_flow_action *actions,\n-\t\t\t   struct pedit_parser *p_parser)\n-{\n-\tint idx = p_parser->sel.nkeys;\n-\tuint32_t off = actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?\n-\t\t\t\t\toffsetof(struct rte_ether_hdr, s_addr) :\n-\t\t\t\t\toffsetof(struct rte_ether_hdr, d_addr);\n-\tconst struct rte_flow_action_set_mac *conf =\n-\t\t(const struct rte_flow_action_set_mac *)actions->conf;\n-\n-\tp_parser->keys[idx].off = off;\n-\tp_parser->keys[idx].mask = ~UINT32_MAX;\n-\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH;\n-\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\tmemcpy(&p_parser->keys[idx].val,\n-\t\tconf->mac_addr, SZ_PEDIT_KEY_VAL);\n-\tidx++;\n-\tp_parser->keys[idx].off = off + SZ_PEDIT_KEY_VAL;\n-\tp_parser->keys[idx].mask = 0xFFFF0000;\n-\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH;\n-\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\tmemcpy(&p_parser->keys[idx].val,\n-\t\tconf->mac_addr + SZ_PEDIT_KEY_VAL,\n-\t\tRTE_ETHER_ADDR_LEN - SZ_PEDIT_KEY_VAL);\n-\tp_parser->sel.nkeys = (++idx);\n-}\n-\n-/**\n- * Set pedit key of decrease/set ttl\n- *\n- * @param[in] actions\n- *   pointer to action specification\n- * @param[in,out] p_parser\n- *   pointer to pedit_parser\n- * @param[in] item_flags\n- *   flags of all items presented\n- */\n-static void\n-flow_tcf_pedit_key_set_dec_ttl(const struct rte_flow_action *actions,\n-\t\t\t\tstruct pedit_parser *p_parser,\n-\t\t\t\tuint64_t item_flags)\n-{\n-\tint idx = p_parser->sel.nkeys;\n-\n-\tp_parser->keys[idx].mask = 0xFFFFFF00;\n-\tif (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4) {\n-\t\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4;\n-\t\tp_parser->keys[idx].off =\n-\t\t\toffsetof(struct rte_ipv4_hdr, time_to_live);\n-\t}\n-\tif (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6) {\n-\t\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6;\n-\t\tp_parser->keys[idx].off =\n-\t\t\toffsetof(struct rte_ipv6_hdr, hop_limits);\n-\t}\n-\tif (actions->type == RTE_FLOW_ACTION_TYPE_DEC_TTL) {\n-\t\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_ADD;\n-\t\tp_parser->keys[idx].val = 0x000000FF;\n-\t} else {\n-\t\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\t\tp_parser->keys[idx].val =\n-\t\t\t(__u32)((const struct rte_flow_action_set_ttl *)\n-\t\t\t actions->conf)->ttl_value;\n-\t}\n-\tp_parser->sel.nkeys = (++idx);\n-}\n-\n-/**\n- * Set pedit key of transport (TCP/UDP) port value\n- *\n- * @param[in] actions\n- *   pointer to action specification\n- * @param[in,out] p_parser\n- *   pointer to pedit_parser\n- * @param[in] item_flags\n- *   flags of all items presented\n- */\n-static void\n-flow_tcf_pedit_key_set_tp_port(const struct rte_flow_action *actions,\n-\t\t\t\tstruct pedit_parser *p_parser,\n-\t\t\t\tuint64_t item_flags)\n-{\n-\tint idx = p_parser->sel.nkeys;\n-\n-\tif (item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)\n-\t\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP;\n-\tif (item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP)\n-\t\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP;\n-\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\t/* offset of src/dst port is same for TCP and UDP */\n-\tp_parser->keys[idx].off =\n-\t\tactions->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?\n-\t\toffsetof(struct rte_tcp_hdr, src_port) :\n-\t\toffsetof(struct rte_tcp_hdr, dst_port);\n-\tp_parser->keys[idx].mask = 0xFFFF0000;\n-\tp_parser->keys[idx].val =\n-\t\t(__u32)((const struct rte_flow_action_set_tp *)\n-\t\t\t\tactions->conf)->port;\n-\tp_parser->sel.nkeys = (++idx);\n-}\n-\n-/**\n- * Set pedit key of ipv6 address\n- *\n- * @param[in] actions\n- *   pointer to action specification\n- * @param[in,out] p_parser\n- *   pointer to pedit_parser\n- */\n-static void\n-flow_tcf_pedit_key_set_ipv6_addr(const struct rte_flow_action *actions,\n-\t\t\t\t struct pedit_parser *p_parser)\n-{\n-\tint idx = p_parser->sel.nkeys;\n-\tint keys = NUM_OF_PEDIT_KEYS(IPV6_ADDR_LEN);\n-\tint off_base =\n-\t\tactions->type == RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?\n-\t\toffsetof(struct rte_ipv6_hdr, src_addr) :\n-\t\toffsetof(struct rte_ipv6_hdr, dst_addr);\n-\tconst struct rte_flow_action_set_ipv6 *conf =\n-\t\t(const struct rte_flow_action_set_ipv6 *)actions->conf;\n-\n-\tfor (int i = 0; i < keys; i++, idx++) {\n-\t\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6;\n-\t\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\t\tp_parser->keys[idx].off = off_base + i * SZ_PEDIT_KEY_VAL;\n-\t\tp_parser->keys[idx].mask = ~UINT32_MAX;\n-\t\tmemcpy(&p_parser->keys[idx].val,\n-\t\t\tconf->ipv6_addr + i *  SZ_PEDIT_KEY_VAL,\n-\t\t\tSZ_PEDIT_KEY_VAL);\n-\t}\n-\tp_parser->sel.nkeys += keys;\n-}\n-\n-/**\n- * Set pedit key of ipv4 address\n- *\n- * @param[in] actions\n- *   pointer to action specification\n- * @param[in,out] p_parser\n- *   pointer to pedit_parser\n- */\n-static void\n-flow_tcf_pedit_key_set_ipv4_addr(const struct rte_flow_action *actions,\n-\t\t\t\t struct pedit_parser *p_parser)\n-{\n-\tint idx = p_parser->sel.nkeys;\n-\n-\tp_parser->keys_ex[idx].htype = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4;\n-\tp_parser->keys_ex[idx].cmd = TCA_PEDIT_KEY_EX_CMD_SET;\n-\tp_parser->keys[idx].off =\n-\t\tactions->type == RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?\n-\t\toffsetof(struct rte_ipv4_hdr, src_addr) :\n-\t\toffsetof(struct rte_ipv4_hdr, dst_addr);\n-\tp_parser->keys[idx].mask = ~UINT32_MAX;\n-\tp_parser->keys[idx].val =\n-\t\t((const struct rte_flow_action_set_ipv4 *)\n-\t\t actions->conf)->ipv4_addr;\n-\tp_parser->sel.nkeys = (++idx);\n-}\n-\n-/**\n- * Create the pedit's na attribute in netlink message\n- * on pre-allocate message buffer\n- *\n- * @param[in,out] nl\n- *   pointer to pre-allocated netlink message buffer\n- * @param[in,out] actions\n- *   pointer to pointer of actions specification.\n- * @param[in,out] action_flags\n- *   pointer to actions flags\n- * @param[in] item_flags\n- *   flags of all item presented\n- */\n-static void\n-flow_tcf_create_pedit_mnl_msg(struct nlmsghdr *nl,\n-\t\t\t      const struct rte_flow_action **actions,\n-\t\t\t      uint64_t item_flags)\n-{\n-\tstruct pedit_parser p_parser;\n-\tstruct nlattr *na_act_options;\n-\tstruct nlattr *na_pedit_keys;\n-\n-\tmemset(&p_parser, 0, sizeof(p_parser));\n-\tmnl_attr_put_strz(nl, TCA_ACT_KIND, \"pedit\");\n-\tna_act_options = mnl_attr_nest_start(nl, TCA_ACT_OPTIONS);\n-\t/* all modify header actions should be in one tc-pedit action */\n-\tfor (; (*actions)->type != RTE_FLOW_ACTION_TYPE_END; (*actions)++) {\n-\t\tswitch ((*actions)->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n-\t\t\tflow_tcf_pedit_key_set_ipv4_addr(*actions, &p_parser);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n-\t\t\tflow_tcf_pedit_key_set_ipv6_addr(*actions, &p_parser);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n-\t\t\tflow_tcf_pedit_key_set_tp_port(*actions,\n-\t\t\t\t\t\t\t&p_parser, item_flags);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TTL:\n-\t\tcase RTE_FLOW_ACTION_TYPE_DEC_TTL:\n-\t\t\tflow_tcf_pedit_key_set_dec_ttl(*actions,\n-\t\t\t\t\t\t\t&p_parser, item_flags);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_DST:\n-\t\t\tflow_tcf_pedit_key_set_mac(*actions, &p_parser);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tgoto pedit_mnl_msg_done;\n-\t\t}\n-\t}\n-pedit_mnl_msg_done:\n-\tp_parser.sel.action = TC_ACT_PIPE;\n-\tmnl_attr_put(nl, TCA_PEDIT_PARMS_EX,\n-\t\t     sizeof(p_parser.sel) +\n-\t\t     p_parser.sel.nkeys * sizeof(struct tc_pedit_key),\n-\t\t     &p_parser);\n-\tna_pedit_keys =\n-\t\tmnl_attr_nest_start(nl, TCA_PEDIT_KEYS_EX | NLA_F_NESTED);\n-\tfor (int i = 0; i < p_parser.sel.nkeys; i++) {\n-\t\tstruct nlattr *na_pedit_key =\n-\t\t\tmnl_attr_nest_start(nl,\n-\t\t\t\t\t    TCA_PEDIT_KEY_EX | NLA_F_NESTED);\n-\t\tmnl_attr_put_u16(nl, TCA_PEDIT_KEY_EX_HTYPE,\n-\t\t\t\t p_parser.keys_ex[i].htype);\n-\t\tmnl_attr_put_u16(nl, TCA_PEDIT_KEY_EX_CMD,\n-\t\t\t\t p_parser.keys_ex[i].cmd);\n-\t\tmnl_attr_nest_end(nl, na_pedit_key);\n-\t}\n-\tmnl_attr_nest_end(nl, na_pedit_keys);\n-\tmnl_attr_nest_end(nl, na_act_options);\n-\t(*actions)--;\n-}\n-\n-/**\n- * Calculate max memory size of one TC-pedit actions.\n- * One TC-pedit action can contain set of keys each defining\n- * a rewrite element (rte_flow action)\n- *\n- * @param[in,out] actions\n- *   actions specification.\n- * @param[in,out] action_flags\n- *   actions flags\n- * @param[in,out] size\n- *   accumulated size\n- * @return\n- *   Max memory size of one TC-pedit action\n- */\n-static int\n-flow_tcf_get_pedit_actions_size(const struct rte_flow_action **actions,\n-\t\t\t\tuint64_t *action_flags)\n-{\n-\tint pedit_size = 0;\n-\tint keys = 0;\n-\tuint64_t flags = 0;\n-\n-\tpedit_size += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t      SZ_NLATTR_STRZ_OF(\"pedit\") +\n-\t\t      SZ_NLATTR_NEST; /* TCA_ACT_OPTIONS. */\n-\tfor (; (*actions)->type != RTE_FLOW_ACTION_TYPE_END; (*actions)++) {\n-\t\tswitch ((*actions)->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(IPV4_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_IPV4_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(IPV4_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_IPV4_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(IPV6_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_IPV6_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(IPV6_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_IPV6_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n-\t\t\t/* TCP is as same as UDP */\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(TP_PORT_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_TP_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n-\t\t\t/* TCP is as same as UDP */\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(TP_PORT_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_TP_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TTL:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(TTL_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_TTL;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_DEC_TTL:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(TTL_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_DEC_TTL;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(RTE_ETHER_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_MAC_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_DST:\n-\t\t\tkeys += NUM_OF_PEDIT_KEYS(RTE_ETHER_ADDR_LEN);\n-\t\t\tflags |= MLX5_FLOW_ACTION_SET_MAC_DST;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tgoto get_pedit_action_size_done;\n-\t\t}\n-\t}\n-get_pedit_action_size_done:\n-\t/* TCA_PEDIT_PARAMS_EX */\n-\tpedit_size +=\n-\t\tSZ_NLATTR_DATA_OF(sizeof(struct tc_pedit_sel) +\n-\t\t\t\t  keys * sizeof(struct tc_pedit_key));\n-\tpedit_size += SZ_NLATTR_NEST; /* TCA_PEDIT_KEYS */\n-\tpedit_size += keys *\n-\t\t      /* TCA_PEDIT_KEY_EX + HTYPE + CMD */\n-\t\t      (SZ_NLATTR_NEST + SZ_NLATTR_DATA_OF(2) +\n-\t\t       SZ_NLATTR_DATA_OF(2));\n-\t(*action_flags) |= flags;\n-\t(*actions)--;\n-\treturn pedit_size;\n-}\n-\n-/**\n- * Retrieve mask for pattern item.\n- *\n- * This function does basic sanity checks on a pattern item in order to\n- * return the most appropriate mask for it.\n- *\n- * @param[in] item\n- *   Item specification.\n- * @param[in] mask_default\n- *   Default mask for pattern item as specified by the flow API.\n- * @param[in] mask_supported\n- *   Mask fields supported by the implementation.\n- * @param[in] mask_empty\n- *   Empty mask to return when there is no specification.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   Either @p item->mask or one of the mask parameters on success, NULL\n- *   otherwise and rte_errno is set.\n- */\n-static const void *\n-flow_tcf_item_mask(const struct rte_flow_item *item, const void *mask_default,\n-\t\t   const void *mask_supported, const void *mask_empty,\n-\t\t   size_t mask_size, struct rte_flow_error *error)\n-{\n-\tconst uint8_t *mask;\n-\tsize_t i;\n-\n-\t/* item->last and item->mask cannot exist without item->spec. */\n-\tif (!item->spec && (item->mask || item->last)) {\n-\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t   \"\\\"mask\\\" or \\\"last\\\" field provided without\"\n-\t\t\t\t   \" a corresponding \\\"spec\\\"\");\n-\t\treturn NULL;\n-\t}\n-\t/* No spec, no mask, no problem. */\n-\tif (!item->spec)\n-\t\treturn mask_empty;\n-\tmask = item->mask ? item->mask : mask_default;\n-\tassert(mask);\n-\t/*\n-\t * Single-pass check to make sure that:\n-\t * - Mask is supported, no bits are set outside mask_supported.\n-\t * - Both item->spec and item->last are included in mask.\n-\t */\n-\tfor (i = 0; i != mask_size; ++i) {\n-\t\tif (!mask[i])\n-\t\t\tcontinue;\n-\t\tif ((mask[i] | ((const uint8_t *)mask_supported)[i]) !=\n-\t\t    ((const uint8_t *)mask_supported)[i]) {\n-\t\t\trte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t   \"unsupported field found\"\n-\t\t\t\t\t   \" in \\\"mask\\\"\");\n-\t\t\treturn NULL;\n-\t\t}\n-\t\tif (item->last &&\n-\t\t    (((const uint8_t *)item->spec)[i] & mask[i]) !=\n-\t\t    (((const uint8_t *)item->last)[i] & mask[i])) {\n-\t\t\trte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_ITEM_LAST,\n-\t\t\t\t\t   item->last,\n-\t\t\t\t\t   \"range between \\\"spec\\\" and \\\"last\\\"\"\n-\t\t\t\t\t   \" not comprised in \\\"mask\\\"\");\n-\t\t\treturn NULL;\n-\t\t}\n-\t}\n-\treturn mask;\n-}\n-\n-/**\n- * Build a conversion table between port ID and ifindex.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[out] ptoi\n- *   Pointer to ptoi table.\n- * @param[in] len\n- *   Size of ptoi table provided.\n- *\n- * @return\n- *   Size of ptoi table filled.\n- */\n-static unsigned int\n-flow_tcf_build_ptoi_table(struct rte_eth_dev *dev, struct flow_tcf_ptoi *ptoi,\n-\t\t\t  unsigned int len)\n-{\n-\tunsigned int n = mlx5_dev_to_port_id(dev->device, NULL, 0);\n-\tuint16_t port_id[n + 1];\n-\tunsigned int i;\n-\tunsigned int own = 0;\n-\n-\t/* At least one port is needed when no switch domain is present. */\n-\tif (!n) {\n-\t\tn = 1;\n-\t\tport_id[0] = dev->data->port_id;\n-\t} else {\n-\t\tn = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, n), n);\n-\t}\n-\tif (n > len)\n-\t\treturn 0;\n-\tfor (i = 0; i != n; ++i) {\n-\t\tstruct rte_eth_dev_info dev_info;\n-\n-\t\trte_eth_dev_info_get(port_id[i], &dev_info);\n-\t\tif (port_id[i] == dev->data->port_id)\n-\t\t\town = i;\n-\t\tptoi[i].port_id = port_id[i];\n-\t\tptoi[i].ifindex = dev_info.if_index;\n-\t}\n-\t/* Ensure first entry of ptoi[] is the current device. */\n-\tif (own) {\n-\t\tptoi[n] = ptoi[0];\n-\t\tptoi[0] = ptoi[own];\n-\t\tptoi[own] = ptoi[n];\n-\t}\n-\t/* An entry with zero ifindex terminates ptoi[]. */\n-\tptoi[n].port_id = 0;\n-\tptoi[n].ifindex = 0;\n-\treturn n;\n-}\n-\n-/**\n- * Verify the @p attr will be correctly understood by the E-switch.\n- *\n- * @param[in] attr\n- *   Pointer to flow attributes\n- * @param[out] error\n- *   Pointer to error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_validate_attributes(const struct rte_flow_attr *attr,\n-\t\t\t     struct rte_flow_error *error)\n-{\n-\t/*\n-\t * Supported attributes: groups, some priorities and ingress only.\n-\t * group is supported only if kernel supports chain. Don't care about\n-\t * transfer as it is the caller's problem.\n-\t */\n-\tif (attr->group > MLX5_TCF_GROUP_ID_MAX)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,\n-\t\t\t\t\t  \"group ID larger than \"\n-\t\t\t\t\t  RTE_STR(MLX5_TCF_GROUP_ID_MAX)\n-\t\t\t\t\t  \" isn't supported\");\n-\telse if (attr->priority > MLX5_TCF_GROUP_PRIORITY_MAX)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,\n-\t\t\t\t\t  attr,\n-\t\t\t\t\t  \"priority more than \"\n-\t\t\t\t\t  RTE_STR(MLX5_TCF_GROUP_PRIORITY_MAX)\n-\t\t\t\t\t  \" is not supported\");\n-\tif (!attr->ingress)\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,\n-\t\t\t\t\t  attr, \"only ingress is supported\");\n-\tif (attr->egress)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,\n-\t\t\t\t\t  attr, \"egress is not supported\");\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_ETH item for E-Switch.\n- * The routine checks the L2 fields to be used in encapsulation header.\n- *\n- * @param[in] item\n- *   Pointer to the item structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap_eth(const struct rte_flow_item *item,\n-\t\t\t\t  struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_eth *spec = item->spec;\n-\tconst struct rte_flow_item_eth *mask = item->mask;\n-\n-\tif (!spec) {\n-\t\t/*\n-\t\t * Specification for L2 addresses can be empty\n-\t\t * because these ones are optional and not\n-\t\t * required directly by tc rule. Kernel tries\n-\t\t * to resolve these ones on its own\n-\t\t */\n-\t\treturn 0;\n-\t}\n-\tif (!mask) {\n-\t\t/* If mask is not specified use the default one. */\n-\t\tmask = &rte_flow_item_eth_mask;\n-\t}\n-\tif (memcmp(&mask->dst,\n-\t\t   &flow_tcf_mask_empty.eth.dst,\n-\t\t   sizeof(flow_tcf_mask_empty.eth.dst))) {\n-\t\tif (memcmp(&mask->dst,\n-\t\t\t   &rte_flow_item_eth_mask.dst,\n-\t\t\t   sizeof(rte_flow_item_eth_mask.dst)))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t \" \\\"eth.dst\\\" field\");\n-\t}\n-\tif (memcmp(&mask->src,\n-\t\t   &flow_tcf_mask_empty.eth.src,\n-\t\t   sizeof(flow_tcf_mask_empty.eth.src))) {\n-\t\tif (memcmp(&mask->src,\n-\t\t\t   &rte_flow_item_eth_mask.src,\n-\t\t\t   sizeof(rte_flow_item_eth_mask.src)))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t \" \\\"eth.src\\\" field\");\n-\t}\n-\tif (mask->type != RTE_BE16(0x0000)) {\n-\t\tif (mask->type != RTE_BE16(0xffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t \" \\\"eth.type\\\" field\");\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"outer ethernet type field\"\n-\t\t\t\" cannot be forced for vxlan\"\n-\t\t\t\" encapsulation, parameter ignored\");\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_IPV4 item for E-Switch.\n- * The routine checks the IPv4 fields to be used in encapsulation header.\n- *\n- * @param[in] item\n- *   Pointer to the item structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap_ipv4(const struct rte_flow_item *item,\n-\t\t\t\t   struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_ipv4 *spec = item->spec;\n-\tconst struct rte_flow_item_ipv4 *mask = item->mask;\n-\n-\tif (!spec) {\n-\t\t/*\n-\t\t * Specification for IP addresses cannot be empty\n-\t\t * because it is required by tunnel_key parameter.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"NULL outer ipv4 address\"\n-\t\t\t\t\t  \" specification for vxlan\"\n-\t\t\t\t\t  \" encapsulation\");\n-\t}\n-\tif (!mask)\n-\t\tmask = &rte_flow_item_ipv4_mask;\n-\tif (mask->hdr.dst_addr != RTE_BE32(0x00000000)) {\n-\t\tif (mask->hdr.dst_addr != RTE_BE32(0xffffffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t \" \\\"ipv4.hdr.dst_addr\\\" field\"\n-\t\t\t\t \" for vxlan encapsulation\");\n-\t\t/* More IPv4 address validations can be put here. */\n-\t} else {\n-\t\t/*\n-\t\t * Kernel uses the destination IP address to determine\n-\t\t * the routing path and obtain the MAC destination\n-\t\t * address, so IP destination address must be\n-\t\t * specified in the tc rule.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer ipv4 destination address\"\n-\t\t\t\t\t  \" must be specified for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tif (mask->hdr.src_addr != RTE_BE32(0x00000000)) {\n-\t\tif (mask->hdr.src_addr != RTE_BE32(0xffffffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t \" \\\"ipv4.hdr.src_addr\\\" field\"\n-\t\t\t\t \" for vxlan encapsulation\");\n-\t\t/* More IPv4 address validations can be put here. */\n-\t} else {\n-\t\t/*\n-\t\t * Kernel uses the source IP address to select the\n-\t\t * interface for egress encapsulated traffic, so\n-\t\t * it must be specified in the tc rule.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer ipv4 source address\"\n-\t\t\t\t\t  \" must be specified for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tif (mask->hdr.type_of_service &&\n-\t    mask->hdr.type_of_service != 0xff)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t  \"no support for partial mask on\"\n-\t\t\t\t\t  \" \\\"ipv4.hdr.type_of_service\\\" field\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\tif (mask->hdr.time_to_live &&\n-\t    mask->hdr.time_to_live != 0xff)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t  \"no support for partial mask on\"\n-\t\t\t\t\t  \" \\\"ipv4.hdr.time_to_live\\\" field\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_IPV6 item for E-Switch.\n- * The routine checks the IPv6 fields to be used in encapsulation header.\n- *\n- * @param[in] item\n- *   Pointer to the item structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap_ipv6(const struct rte_flow_item *item,\n-\t\t\t\t   struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_ipv6 *spec = item->spec;\n-\tconst struct rte_flow_item_ipv6 *mask = item->mask;\n-\tuint8_t msk6;\n-\n-\tif (!spec) {\n-\t\t/*\n-\t\t * Specification for IP addresses cannot be empty\n-\t\t * because it is required by tunnel_key parameter.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"NULL outer ipv6 address\"\n-\t\t\t\t\t  \" specification for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tif (!mask)\n-\t\tmask = &rte_flow_item_ipv6_mask;\n-\tif (memcmp(&mask->hdr.dst_addr,\n-\t\t   &flow_tcf_mask_empty.ipv6.hdr.dst_addr,\n-\t\t   IPV6_ADDR_LEN)) {\n-\t\tif (memcmp(&mask->hdr.dst_addr,\n-\t\t\t   &rte_flow_item_ipv6_mask.hdr.dst_addr,\n-\t\t\t   IPV6_ADDR_LEN))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"ipv6.hdr.dst_addr\\\" field\"\n-\t\t\t\t\t \" for vxlan encapsulation\");\n-\t\t/* More IPv6 address validations can be put here. */\n-\t} else {\n-\t\t/*\n-\t\t * Kernel uses the destination IP address to determine\n-\t\t * the routing path and obtain the MAC destination\n-\t\t * address (heigh or gate), so IP destination address\n-\t\t * must be specified within the tc rule.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer ipv6 destination address\"\n-\t\t\t\t\t  \" must be specified for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tif (memcmp(&mask->hdr.src_addr,\n-\t\t   &flow_tcf_mask_empty.ipv6.hdr.src_addr,\n-\t\t   IPV6_ADDR_LEN)) {\n-\t\tif (memcmp(&mask->hdr.src_addr,\n-\t\t\t   &rte_flow_item_ipv6_mask.hdr.src_addr,\n-\t\t\t   IPV6_ADDR_LEN))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"ipv6.hdr.src_addr\\\" field\"\n-\t\t\t\t\t \" for vxlan encapsulation\");\n-\t\t/* More L3 address validation can be put here. */\n-\t} else {\n-\t\t/*\n-\t\t * Kernel uses the source IP address to select the\n-\t\t * interface for egress encapsulated traffic, so\n-\t\t * it must be specified in the tc rule.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer L3 source address\"\n-\t\t\t\t\t  \" must be specified for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tmsk6 = (rte_be_to_cpu_32(mask->hdr.vtc_flow) >>\n-\t\tRTE_IPV6_HDR_TC_SHIFT) & 0xff;\n-\tif (msk6 && msk6 != 0xff)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t  \"no support for partial mask on\"\n-\t\t\t\t\t  \" \\\"ipv6.hdr.vtc_flow.tos\\\" field\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\tif (mask->hdr.hop_limits && mask->hdr.hop_limits != 0xff)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t  \"no support for partial mask on\"\n-\t\t\t\t\t  \" \\\"ipv6.hdr.hop_limits\\\" field\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_UDP item for E-Switch.\n- * The routine checks the UDP fields to be used in encapsulation header.\n- *\n- * @param[in] item\n- *   Pointer to the item structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap_udp(const struct rte_flow_item *item,\n-\t\t\t\t  struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_udp *spec = item->spec;\n-\tconst struct rte_flow_item_udp *mask = item->mask;\n-\n-\tif (!spec) {\n-\t\t/*\n-\t\t * Specification for UDP ports cannot be empty\n-\t\t * because it is required by tunnel_key parameter.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"NULL UDP port specification \"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\t}\n-\tif (!mask)\n-\t\tmask = &rte_flow_item_udp_mask;\n-\tif (mask->hdr.dst_port != RTE_BE16(0x0000)) {\n-\t\tif (mask->hdr.dst_port != RTE_BE16(0xffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"udp.hdr.dst_port\\\" field\"\n-\t\t\t\t\t \" for vxlan encapsulation\");\n-\t\tif (!spec->hdr.dst_port)\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t \"outer UDP remote port cannot be\"\n-\t\t\t\t\t \" 0 for vxlan encapsulation\");\n-\t} else {\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer UDP remote port\"\n-\t\t\t\t\t  \" must be specified for\"\n-\t\t\t\t\t  \" vxlan encapsulation\");\n-\t}\n-\tif (mask->hdr.src_port != RTE_BE16(0x0000)) {\n-\t\tif (mask->hdr.src_port != RTE_BE16(0xffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"udp.hdr.src_port\\\" field\"\n-\t\t\t\t\t \" for vxlan encapsulation\");\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"outer UDP source port cannot be\"\n-\t\t\t\" forced for vxlan encapsulation,\"\n-\t\t\t\" parameter ignored\");\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action RTE_FLOW_ITEM_TYPE_VXLAN item for E-Switch.\n- * The routine checks the VNIP fields to be used in encapsulation header.\n- *\n- * @param[in] item\n- *   Pointer to the item structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap_vni(const struct rte_flow_item *item,\n-\t\t\t\t  struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_vxlan *spec = item->spec;\n-\tconst struct rte_flow_item_vxlan *mask = item->mask;\n-\n-\tif (!spec) {\n-\t\t/* Outer VNI is required by tunnel_key parameter. */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"NULL VNI specification\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\t}\n-\tif (!mask)\n-\t\tmask = &rte_flow_item_vxlan_mask;\n-\tif (!mask->vni[0] && !mask->vni[1] && !mask->vni[2])\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"outer VNI must be specified \"\n-\t\t\t\t\t  \"for vxlan encapsulation\");\n-\tif (mask->vni[0] != 0xff ||\n-\t    mask->vni[1] != 0xff ||\n-\t    mask->vni[2] != 0xff)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t  \"no support for partial mask on\"\n-\t\t\t\t\t  \" \\\"vxlan.vni\\\" field\");\n-\n-\tif (!spec->vni[0] && !spec->vni[1] && !spec->vni[2])\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, item,\n-\t\t\t\t\t  \"vxlan vni cannot be 0\");\n-\treturn 0;\n-}\n-\n-/**\n- * Validate VXLAN_ENCAP action item list for E-Switch.\n- * The routine checks items to be used in encapsulation header.\n- *\n- * @param[in] action\n- *   Pointer to the VXLAN_ENCAP action structure.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_encap(const struct rte_flow_action *action,\n-\t\t\t      struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item *items;\n-\tint ret;\n-\tuint32_t item_flags = 0;\n-\n-\tif (!action->conf)\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n-\t\t\t\t\t  \"Missing vxlan tunnel\"\n-\t\t\t\t\t  \" action configuration\");\n-\titems = ((const struct rte_flow_action_vxlan_encap *)\n-\t\t\t\t\taction->conf)->definition;\n-\tif (!items)\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n-\t\t\t\t\t  \"Missing vxlan tunnel\"\n-\t\t\t\t\t  \" encapsulation parameters\");\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tret = mlx5_flow_validate_item_eth(items, item_flags,\n-\t\t\t\t\t\t\t  error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tret = flow_tcf_validate_vxlan_encap_eth(items, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_L2;\n-\t\t\tbreak;\n-\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\tret = mlx5_flow_validate_item_ipv4\n-\t\t\t\t\t(items, item_flags,\n-\t\t\t\t\t &flow_tcf_mask_supported.ipv4, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tret = flow_tcf_validate_vxlan_encap_ipv4(items, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV4;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t\tret = mlx5_flow_validate_item_ipv6\n-\t\t\t\t\t(items, item_flags,\n-\t\t\t\t\t &flow_tcf_mask_supported.ipv6, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tret = flow_tcf_validate_vxlan_encap_ipv6(items, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_L3_IPV6;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\tret = mlx5_flow_validate_item_udp(items, item_flags,\n-\t\t\t\t\t\t\t   0xFF, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tret = flow_tcf_validate_vxlan_encap_udp(items, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_L4_UDP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tret = mlx5_flow_validate_item_vxlan(items,\n-\t\t\t\t\t\t\t    item_flags, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tret = flow_tcf_validate_vxlan_encap_vni(items, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_VXLAN;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, items,\n-\t\t\t\t\t \"vxlan encap item not supported\");\n-\t\t}\n-\t}\n-\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n-\t\t\t\t\t  \"no outer IP layer found\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n-\t\t\t\t\t  \"no outer UDP layer found\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\tif (!(item_flags & MLX5_FLOW_LAYER_VXLAN))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, action,\n-\t\t\t\t\t  \"no VXLAN VNI found\"\n-\t\t\t\t\t  \" for vxlan encapsulation\");\n-\treturn 0;\n-}\n-\n-/**\n- * Validate outer RTE_FLOW_ITEM_TYPE_UDP item if tunnel item\n- * RTE_FLOW_ITEM_TYPE_VXLAN is present in item list.\n- *\n- * @param[in] udp\n- *   Outer UDP layer item (if any, NULL otherwise).\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- **/\n-static int\n-flow_tcf_validate_vxlan_decap_udp(const struct rte_flow_item *udp,\n-\t\t\t\t  struct rte_flow_error *error)\n-{\n-\tconst struct rte_flow_item_udp *spec = udp->spec;\n-\tconst struct rte_flow_item_udp *mask = udp->mask;\n-\n-\tif (!spec)\n-\t\t/*\n-\t\t * Specification for UDP ports cannot be empty\n-\t\t * because it is required as decap parameter.\n-\t\t */\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, udp,\n-\t\t\t\t\t  \"NULL UDP port specification\"\n-\t\t\t\t\t  \" for VXLAN decapsulation\");\n-\tif (!mask)\n-\t\tmask = &rte_flow_item_udp_mask;\n-\tif (mask->hdr.dst_port != RTE_BE16(0x0000)) {\n-\t\tif (mask->hdr.dst_port != RTE_BE16(0xffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"udp.hdr.dst_port\\\" field\");\n-\t\tif (!spec->hdr.dst_port)\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, udp,\n-\t\t\t\t\t \"zero decap local UDP port\");\n-\t} else {\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM, udp,\n-\t\t\t\t\t  \"outer UDP destination port must be \"\n-\t\t\t\t\t  \"specified for vxlan decapsulation\");\n-\t}\n-\tif (mask->hdr.src_port != RTE_BE16(0x0000)) {\n-\t\tif (mask->hdr.src_port != RTE_BE16(0xffff))\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"udp.hdr.src_port\\\" field\");\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"outer UDP local port cannot be \"\n-\t\t\t\"forced for VXLAN encapsulation, \"\n-\t\t\t\"parameter ignored\");\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Validate flow for E-Switch.\n- *\n- * @param[in] priv\n- *   Pointer to the priv structure.\n- * @param[in] attr\n- *   Pointer to the flow attributes.\n- * @param[in] items\n- *   Pointer to the list of items.\n- * @param[in] actions\n- *   Pointer to the list of actions.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_validate(struct rte_eth_dev *dev,\n-\t\t  const struct rte_flow_attr *attr,\n-\t\t  const struct rte_flow_item items[],\n-\t\t  const struct rte_flow_action actions[],\n-\t\t  struct rte_flow_error *error)\n-{\n-\tunion {\n-\t\tconst struct rte_flow_item_port_id *port_id;\n-\t\tconst struct rte_flow_item_eth *eth;\n-\t\tconst struct rte_flow_item_vlan *vlan;\n-\t\tconst struct rte_flow_item_ipv4 *ipv4;\n-\t\tconst struct rte_flow_item_ipv6 *ipv6;\n-\t\tconst struct rte_flow_item_tcp *tcp;\n-\t\tconst struct rte_flow_item_udp *udp;\n-\t\tconst struct rte_flow_item_vxlan *vxlan;\n-\t} spec, mask;\n-\tunion {\n-\t\tconst struct rte_flow_action_port_id *port_id;\n-\t\tconst struct rte_flow_action_jump *jump;\n-\t\tconst struct rte_flow_action_of_push_vlan *of_push_vlan;\n-\t\tconst struct rte_flow_action_of_set_vlan_vid *\n-\t\t\tof_set_vlan_vid;\n-\t\tconst struct rte_flow_action_of_set_vlan_pcp *\n-\t\t\tof_set_vlan_pcp;\n-\t\tconst struct rte_flow_action_vxlan_encap *vxlan_encap;\n-\t\tconst struct rte_flow_action_set_ipv4 *set_ipv4;\n-\t\tconst struct rte_flow_action_set_ipv6 *set_ipv6;\n-\t} conf;\n-\tconst struct rte_flow_item *outer_udp = NULL;\n-\trte_be16_t inner_etype = RTE_BE16(ETH_P_ALL);\n-\trte_be16_t outer_etype = RTE_BE16(ETH_P_ALL);\n-\trte_be16_t vlan_etype = RTE_BE16(ETH_P_ALL);\n-\tuint64_t item_flags = 0;\n-\tuint64_t action_flags = 0;\n-\tuint8_t next_protocol = 0xff;\n-\tunsigned int tcm_ifindex = 0;\n-\tuint8_t pedit_validated = 0;\n-\tstruct flow_tcf_ptoi ptoi[PTOI_TABLE_SZ_MAX(dev)];\n-\tstruct rte_eth_dev *port_id_dev = NULL;\n-\tbool in_port_id_set;\n-\tint ret;\n-\n-\tclaim_nonzero(flow_tcf_build_ptoi_table(dev, ptoi,\n-\t\t\t\t\t\tPTOI_TABLE_SZ_MAX(dev)));\n-\tret = flow_tcf_validate_attributes(attr, error);\n-\tif (ret < 0)\n-\t\treturn ret;\n-\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n-\t\tunsigned int i;\n-\t\tuint64_t current_action_flag = 0;\n-\n-\t\tswitch (actions->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_PORT_ID:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_PORT_ID;\n-\t\t\tif (!actions->conf)\n-\t\t\t\tbreak;\n-\t\t\tconf.port_id = actions->conf;\n-\t\t\tif (conf.port_id->original)\n-\t\t\t\ti = 0;\n-\t\t\telse\n-\t\t\t\tfor (i = 0; ptoi[i].ifindex; ++i)\n-\t\t\t\t\tif (ptoi[i].port_id == conf.port_id->id)\n-\t\t\t\t\t\tbreak;\n-\t\t\tif (!ptoi[i].ifindex)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENODEV,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\t conf.port_id,\n-\t\t\t\t\t \"missing data to convert port ID to\"\n-\t\t\t\t\t \" ifindex\");\n-\t\t\tport_id_dev = &rte_eth_devices[conf.port_id->id];\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_JUMP;\n-\t\t\tif (!actions->conf)\n-\t\t\t\tbreak;\n-\t\t\tconf.jump = actions->conf;\n-\t\t\tif (attr->group >= conf.jump->group)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t actions,\n-\t\t\t\t\t \"can jump only to a group forward\");\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_DROP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_OF_POP_VLAN;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: {\n-\t\t\trte_be16_t ethertype;\n-\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_OF_PUSH_VLAN;\n-\t\t\tif (!actions->conf)\n-\t\t\t\tbreak;\n-\t\t\tconf.of_push_vlan = actions->conf;\n-\t\t\tethertype = conf.of_push_vlan->ethertype;\n-\t\t\tif (ethertype != RTE_BE16(ETH_P_8021Q) &&\n-\t\t\t    ethertype != RTE_BE16(ETH_P_8021AD))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t \"vlan push TPID must be \"\n-\t\t\t\t\t \"802.1Q or 802.1AD\");\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n-\t\t\tif (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t \"vlan modify is not supported,\"\n-\t\t\t\t\t \" set action must follow push action\");\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_OF_SET_VLAN_VID;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:\n-\t\t\tif (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t \"vlan modify is not supported,\"\n-\t\t\t\t\t \" set action must follow push action\");\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_VXLAN_DECAP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n-\t\t\tret = flow_tcf_validate_vxlan_encap(actions, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_VXLAN_ENCAP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_IPV4_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_IPV4_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_IPV6_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_IPV6_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_TP_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_TP_DST;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TTL:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_TTL;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_DEC_TTL:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_DEC_TTL;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_MAC_SRC;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_DST:\n-\t\t\tcurrent_action_flag = MLX5_FLOW_ACTION_SET_MAC_DST;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"action not supported\");\n-\t\t}\n-\t\tif (current_action_flag & MLX5_TCF_CONFIG_ACTIONS) {\n-\t\t\tif (!actions->conf)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ACTION_CONF,\n-\t\t\t\t\t actions,\n-\t\t\t\t\t \"action configuration not set\");\n-\t\t}\n-\t\tif ((current_action_flag & MLX5_TCF_PEDIT_ACTIONS) &&\n-\t\t    pedit_validated)\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"set actions should be \"\n-\t\t\t\t\t\t  \"listed successively\");\n-\t\tif ((current_action_flag & ~MLX5_TCF_PEDIT_ACTIONS) &&\n-\t\t    (action_flags & MLX5_TCF_PEDIT_ACTIONS))\n-\t\t\tpedit_validated = 1;\n-\t\tif ((current_action_flag & MLX5_TCF_FATE_ACTIONS) &&\n-\t\t    (action_flags & MLX5_TCF_FATE_ACTIONS))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"can't have multiple fate\"\n-\t\t\t\t\t\t  \" actions\");\n-\t\tif ((current_action_flag & MLX5_TCF_VXLAN_ACTIONS) &&\n-\t\t    (action_flags & MLX5_TCF_VXLAN_ACTIONS))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"can't have multiple vxlan\"\n-\t\t\t\t\t\t  \" actions\");\n-\t\tif ((current_action_flag & MLX5_TCF_VXLAN_ACTIONS) &&\n-\t\t    (action_flags & MLX5_TCF_VLAN_ACTIONS))\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"can't have vxlan and vlan\"\n-\t\t\t\t\t\t  \" actions in the same rule\");\n-\t\taction_flags |= current_action_flag;\n-\t}\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tunsigned int i;\n-\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_PORT_ID:\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, items,\n-\t\t\t\t\t \"inner tunnel port id\"\n-\t\t\t\t\t \" item is not supported\");\n-\t\t\tmask.port_id = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_port_id_mask,\n-\t\t\t\t &flow_tcf_mask_supported.port_id,\n-\t\t\t\t &flow_tcf_mask_empty.port_id,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.port_id),\n-\t\t\t\t error);\n-\t\t\tif (!mask.port_id)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif (mask.port_id == &flow_tcf_mask_empty.port_id) {\n-\t\t\t\tin_port_id_set = 1;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tspec.port_id = items->spec;\n-\t\t\tif (mask.port_id->id && mask.port_id->id != 0xffffffff)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.port_id,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"id\\\" field\");\n-\t\t\tif (!mask.port_id->id)\n-\t\t\t\ti = 0;\n-\t\t\telse\n-\t\t\t\tfor (i = 0; ptoi[i].ifindex; ++i)\n-\t\t\t\t\tif (ptoi[i].port_id == spec.port_id->id)\n-\t\t\t\t\t\tbreak;\n-\t\t\tif (!ptoi[i].ifindex)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENODEV,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_SPEC,\n-\t\t\t\t\t spec.port_id,\n-\t\t\t\t\t \"missing data to convert port ID to\"\n-\t\t\t\t\t \" ifindex\");\n-\t\t\tif (in_port_id_set && ptoi[i].ifindex != tcm_ifindex)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_SPEC,\n-\t\t\t\t\t spec.port_id,\n-\t\t\t\t\t \"cannot match traffic for\"\n-\t\t\t\t\t \" several port IDs through\"\n-\t\t\t\t\t \" a single flow rule\");\n-\t\t\ttcm_ifindex = ptoi[i].ifindex;\n-\t\t\tin_port_id_set = 1;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tret = mlx5_flow_validate_item_eth(items, item_flags,\n-\t\t\t\t\t\t\t  error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L2 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L2;\n-\t\t\t/* TODO:\n-\t\t\t * Redundant check due to different supported mask.\n-\t\t\t * Same for the rest of items.\n-\t\t\t */\n-\t\t\tmask.eth = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_eth_mask,\n-\t\t\t\t &flow_tcf_mask_supported.eth,\n-\t\t\t\t &flow_tcf_mask_empty.eth,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.eth),\n-\t\t\t\t error);\n-\t\t\tif (!mask.eth)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif (mask.eth->type && mask.eth->type !=\n-\t\t\t    RTE_BE16(0xffff))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.eth,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"type\\\" field\");\n-\t\t\tassert(items->spec);\n-\t\t\tspec.eth = items->spec;\n-\t\t\tif (mask.eth->type &&\n-\t\t\t    (item_flags & MLX5_FLOW_LAYER_TUNNEL) &&\n-\t\t\t    inner_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t    inner_etype != spec.eth->type)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t items,\n-\t\t\t\t\t \"inner eth_type conflict\");\n-\t\t\tif (mask.eth->type &&\n-\t\t\t    !(item_flags & MLX5_FLOW_LAYER_TUNNEL) &&\n-\t\t\t    outer_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t    outer_etype != spec.eth->type)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t items,\n-\t\t\t\t\t \"outer eth_type conflict\");\n-\t\t\tif (mask.eth->type) {\n-\t\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL)\n-\t\t\t\t\tinner_etype = spec.eth->type;\n-\t\t\t\telse\n-\t\t\t\t\touter_etype = spec.eth->type;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, items,\n-\t\t\t\t\t \"inner tunnel VLAN\"\n-\t\t\t\t\t \" is not supported\");\n-\t\t\tret = mlx5_flow_validate_item_vlan(items, item_flags,\n-\t\t\t\t\t\t\t   error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_VLAN;\n-\t\t\tmask.vlan = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_vlan_mask,\n-\t\t\t\t &flow_tcf_mask_supported.vlan,\n-\t\t\t\t &flow_tcf_mask_empty.vlan,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.vlan),\n-\t\t\t\t error);\n-\t\t\tif (!mask.vlan)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif ((mask.vlan->tci & RTE_BE16(0xe000) &&\n-\t\t\t     (mask.vlan->tci & RTE_BE16(0xe000)) !=\n-\t\t\t      RTE_BE16(0xe000)) ||\n-\t\t\t    (mask.vlan->tci & RTE_BE16(0x0fff) &&\n-\t\t\t     (mask.vlan->tci & RTE_BE16(0x0fff)) !=\n-\t\t\t      RTE_BE16(0x0fff)) ||\n-\t\t\t    (mask.vlan->inner_type &&\n-\t\t\t     mask.vlan->inner_type != RTE_BE16(0xffff)))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.vlan,\n-\t\t\t\t\t \"no support for partial masks on\"\n-\t\t\t\t\t \" \\\"tci\\\" (PCP and VID parts) and\"\n-\t\t\t\t\t \" \\\"inner_type\\\" fields\");\n-\t\t\tif (outer_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t    outer_etype != RTE_BE16(ETH_P_8021Q))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t items,\n-\t\t\t\t\t \"outer eth_type conflict,\"\n-\t\t\t\t\t \" must be 802.1Q\");\n-\t\t\touter_etype = RTE_BE16(ETH_P_8021Q);\n-\t\t\tassert(items->spec);\n-\t\t\tspec.vlan = items->spec;\n-\t\t\tif (mask.vlan->inner_type &&\n-\t\t\t    vlan_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t    vlan_etype != spec.vlan->inner_type)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t items,\n-\t\t\t\t\t \"vlan eth_type conflict\");\n-\t\t\tif (mask.vlan->inner_type)\n-\t\t\t\tvlan_etype = spec.vlan->inner_type;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\tret = mlx5_flow_validate_item_ipv4\n-\t\t\t\t\t(items, item_flags,\n-\t\t\t\t\t &flow_tcf_mask_supported.ipv4, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L3_IPV4 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV4;\n-\t\t\tmask.ipv4 = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_ipv4_mask,\n-\t\t\t\t &flow_tcf_mask_supported.ipv4,\n-\t\t\t\t &flow_tcf_mask_empty.ipv4,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.ipv4),\n-\t\t\t\t error);\n-\t\t\tif (!mask.ipv4)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif (mask.ipv4->hdr.next_proto_id &&\n-\t\t\t    mask.ipv4->hdr.next_proto_id != 0xff)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.ipv4,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"hdr.next_proto_id\\\" field\");\n-\t\t\telse if (mask.ipv4->hdr.next_proto_id)\n-\t\t\t\tnext_protocol =\n-\t\t\t\t\t((const struct rte_flow_item_ipv4 *)\n-\t\t\t\t\t (items->spec))->hdr.next_proto_id;\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL) {\n-\t\t\t\tif (inner_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    inner_etype != RTE_BE16(ETH_P_IP))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"inner eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv4 is required\");\n-\t\t\t\tinner_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t} else if (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN) {\n-\t\t\t\tif (vlan_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    vlan_etype != RTE_BE16(ETH_P_IP))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"vlan eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv4 is required\");\n-\t\t\t\tvlan_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t} else {\n-\t\t\t\tif (outer_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    outer_etype != RTE_BE16(ETH_P_IP))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv4 is required\");\n-\t\t\t\touter_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t\tret = mlx5_flow_validate_item_ipv6\n-\t\t\t\t\t(items, item_flags,\n-\t\t\t\t\t &flow_tcf_mask_supported.ipv6, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L3_IPV6 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV6;\n-\t\t\tmask.ipv6 = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_ipv6_mask,\n-\t\t\t\t &flow_tcf_mask_supported.ipv6,\n-\t\t\t\t &flow_tcf_mask_empty.ipv6,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.ipv6),\n-\t\t\t\t error);\n-\t\t\tif (!mask.ipv6)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif (mask.ipv6->hdr.proto &&\n-\t\t\t    mask.ipv6->hdr.proto != 0xff)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.ipv6,\n-\t\t\t\t\t \"no support for partial mask on\"\n-\t\t\t\t\t \" \\\"hdr.proto\\\" field\");\n-\t\t\telse if (mask.ipv6->hdr.proto)\n-\t\t\t\tnext_protocol =\n-\t\t\t\t\t((const struct rte_flow_item_ipv6 *)\n-\t\t\t\t\t (items->spec))->hdr.proto;\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL) {\n-\t\t\t\tif (inner_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    inner_etype != RTE_BE16(ETH_P_IPV6))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"inner eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv6 is required\");\n-\t\t\t\tinner_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t} else if (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN) {\n-\t\t\t\tif (vlan_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    vlan_etype != RTE_BE16(ETH_P_IPV6))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"vlan eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv6 is required\");\n-\t\t\t\tvlan_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t} else {\n-\t\t\t\tif (outer_etype != RTE_BE16(ETH_P_ALL) &&\n-\t\t\t\t    outer_etype != RTE_BE16(ETH_P_IPV6))\n-\t\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t(error, EINVAL,\n-\t\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t items,\n-\t\t\t\t\t\t \"eth_type conflict,\"\n-\t\t\t\t\t\t \" IPv6 is required\");\n-\t\t\t\touter_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\tret = mlx5_flow_validate_item_udp(items, item_flags,\n-\t\t\t\t\t\t\t  next_protocol, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L4_UDP :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L4_UDP;\n-\t\t\tmask.udp = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_udp_mask,\n-\t\t\t\t &flow_tcf_mask_supported.udp,\n-\t\t\t\t &flow_tcf_mask_empty.udp,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.udp),\n-\t\t\t\t error);\n-\t\t\tif (!mask.udp)\n-\t\t\t\treturn -rte_errno;\n-\t\t\t/*\n-\t\t\t * Save the presumed outer UDP item for extra check\n-\t\t\t * if the tunnel item will be found later in the list.\n-\t\t\t */\n-\t\t\tif (!(item_flags & MLX5_FLOW_LAYER_TUNNEL))\n-\t\t\t\touter_udp = items;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t\t\tret = mlx5_flow_validate_item_tcp\n-\t\t\t\t\t     (items, item_flags,\n-\t\t\t\t\t      next_protocol,\n-\t\t\t\t\t      &flow_tcf_mask_supported.tcp,\n-\t\t\t\t\t      error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L4_TCP :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L4_TCP;\n-\t\t\tmask.tcp = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_tcp_mask,\n-\t\t\t\t &flow_tcf_mask_supported.tcp,\n-\t\t\t\t &flow_tcf_mask_empty.tcp,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.tcp),\n-\t\t\t\t error);\n-\t\t\tif (!mask.tcp)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM, items,\n-\t\t\t\t\t \"vxlan tunnel over vlan\"\n-\t\t\t\t\t \" is not supported\");\n-\t\t\tret = mlx5_flow_validate_item_vxlan(items,\n-\t\t\t\t\t\t\t    item_flags, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_VXLAN;\n-\t\t\tmask.vxlan = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_vxlan_mask,\n-\t\t\t\t &flow_tcf_mask_supported.vxlan,\n-\t\t\t\t &flow_tcf_mask_empty.vxlan,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.vxlan), error);\n-\t\t\tif (!mask.vxlan)\n-\t\t\t\treturn -rte_errno;\n-\t\t\tif (mask.vxlan->vni[0] != 0xff ||\n-\t\t\t    mask.vxlan->vni[1] != 0xff ||\n-\t\t\t    mask.vxlan->vni[2] != 0xff)\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t(error, ENOTSUP,\n-\t\t\t\t\t RTE_FLOW_ERROR_TYPE_ITEM_MASK,\n-\t\t\t\t\t mask.vxlan,\n-\t\t\t\t\t \"no support for partial or \"\n-\t\t\t\t\t \"empty mask on \\\"vxlan.vni\\\" field\");\n-\t\t\t/*\n-\t\t\t * The VNI item assumes the VXLAN tunnel, it requires\n-\t\t\t * at least the outer destination UDP port must be\n-\t\t\t * specified without wildcards to allow kernel select\n-\t\t\t * the virtual VXLAN device by port. Also outer IPv4\n-\t\t\t * or IPv6 item must be specified (wilcards or even\n-\t\t\t * zero mask are allowed) to let driver know the tunnel\n-\t\t\t * IP version and process UDP traffic correctly.\n-\t\t\t */\n-\t\t\tif (!(item_flags &\n-\t\t\t     (MLX5_FLOW_LAYER_OUTER_L3_IPV4 |\n-\t\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV6)))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t (error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  NULL,\n-\t\t\t\t\t\t  \"no outer IP pattern found\"\n-\t\t\t\t\t\t  \" for vxlan tunnel\");\n-\t\t\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP))\n-\t\t\t\treturn rte_flow_error_set\n-\t\t\t\t\t\t (error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  NULL,\n-\t\t\t\t\t\t  \"no outer UDP pattern found\"\n-\t\t\t\t\t\t  \" for vxlan tunnel\");\n-\t\t\t/*\n-\t\t\t * All items preceding the tunnel item become outer\n-\t\t\t * ones and we should do extra validation for them\n-\t\t\t * due to tc limitations for tunnel outer parameters.\n-\t\t\t * Currently only outer UDP item requres extra check,\n-\t\t\t * use the saved pointer instead of item list rescan.\n-\t\t\t */\n-\t\t\tassert(outer_udp);\n-\t\t\tret = flow_tcf_validate_vxlan_decap_udp\n-\t\t\t\t\t\t(outer_udp, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\t/* Reset L4 protocol for inner parameters. */\n-\t\t\tnext_protocol = 0xff;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t  items, \"item not supported\");\n-\t\t}\n-\t}\n-\tif ((action_flags & MLX5_TCF_PEDIT_ACTIONS) &&\n-\t    (action_flags & MLX5_FLOW_ACTION_DROP))\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t  actions,\n-\t\t\t\t\t  \"set action is not compatible with \"\n-\t\t\t\t\t  \"drop action\");\n-\tif ((action_flags & MLX5_TCF_PEDIT_ACTIONS) &&\n-\t    !(action_flags & MLX5_FLOW_ACTION_PORT_ID))\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t  actions,\n-\t\t\t\t\t  \"set action must be followed by \"\n-\t\t\t\t\t  \"port_id action\");\n-\tif (action_flags &\n-\t   (MLX5_FLOW_ACTION_SET_IPV4_SRC | MLX5_FLOW_ACTION_SET_IPV4_DST)) {\n-\t\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"no ipv4 item found in\"\n-\t\t\t\t\t\t  \" pattern\");\n-\t}\n-\tif (action_flags &\n-\t   (MLX5_FLOW_ACTION_SET_IPV6_SRC | MLX5_FLOW_ACTION_SET_IPV6_DST)) {\n-\t\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV6))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"no ipv6 item found in\"\n-\t\t\t\t\t\t  \" pattern\");\n-\t}\n-\tif (action_flags &\n-\t   (MLX5_FLOW_ACTION_SET_TP_SRC | MLX5_FLOW_ACTION_SET_TP_DST)) {\n-\t\tif (!(item_flags &\n-\t\t     (MLX5_FLOW_LAYER_OUTER_L4_UDP |\n-\t\t      MLX5_FLOW_LAYER_OUTER_L4_TCP)))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"no TCP/UDP item found in\"\n-\t\t\t\t\t\t  \" pattern\");\n-\t}\n-\t/*\n-\t * FW syndrome (0xA9C090):\n-\t *     set_flow_table_entry: push vlan action fte in fdb can ONLY be\n-\t *     forward to the uplink.\n-\t */\n-\tif ((action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) &&\n-\t    (action_flags & MLX5_FLOW_ACTION_PORT_ID) &&\n-\t    ((struct mlx5_priv *)port_id_dev->data->dev_private)->representor)\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t  \"vlan push can only be applied\"\n-\t\t\t\t\t  \" when forwarding to uplink port\");\n-\t/*\n-\t * FW syndrome (0x294609):\n-\t *     set_flow_table_entry: modify/pop/push actions in fdb flow table\n-\t *     are supported only while forwarding to vport.\n-\t */\n-\tif ((action_flags & MLX5_TCF_VLAN_ACTIONS) &&\n-\t    !(action_flags & MLX5_FLOW_ACTION_PORT_ID))\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t  \"vlan actions are supported\"\n-\t\t\t\t\t  \" only with port_id action\");\n-\tif ((action_flags & MLX5_TCF_VXLAN_ACTIONS) &&\n-\t    !(action_flags & MLX5_FLOW_ACTION_PORT_ID))\n-\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, NULL,\n-\t\t\t\t\t  \"vxlan actions are supported\"\n-\t\t\t\t\t  \" only with port_id action\");\n-\tif (!(action_flags & MLX5_TCF_FATE_ACTIONS))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION, actions,\n-\t\t\t\t\t  \"no fate action is found\");\n-\tif (action_flags &\n-\t   (MLX5_FLOW_ACTION_SET_TTL | MLX5_FLOW_ACTION_DEC_TTL)) {\n-\t\tif (!(item_flags &\n-\t\t     (MLX5_FLOW_LAYER_OUTER_L3_IPV4 |\n-\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV6)))\n-\t\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"no IP found in pattern\");\n-\t}\n-\tif (action_flags &\n-\t    (MLX5_FLOW_ACTION_SET_MAC_SRC | MLX5_FLOW_ACTION_SET_MAC_DST)) {\n-\t\tif (!(item_flags & MLX5_FLOW_LAYER_OUTER_L2))\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"no ethernet found in\"\n-\t\t\t\t\t\t  \" pattern\");\n-\t}\n-\tif ((action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP) &&\n-\t    !(item_flags & MLX5_FLOW_LAYER_VXLAN))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t  NULL,\n-\t\t\t\t\t  \"no VNI pattern found\"\n-\t\t\t\t\t  \" for vxlan decap action\");\n-\tif ((action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP) &&\n-\t    (item_flags & MLX5_FLOW_LAYER_TUNNEL))\n-\t\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t  NULL,\n-\t\t\t\t\t  \"vxlan encap not supported\"\n-\t\t\t\t\t  \" for tunneled traffic\");\n-\treturn 0;\n-}\n-\n-/**\n- * Calculate maximum size of memory for flow items of Linux TC flower.\n- *\n- * @param[in] attr\n- *   Pointer to the flow attributes.\n- * @param[in] items\n- *   Pointer to the list of items.\n- * @param[out] action_flags\n- *   Pointer to the detected actions.\n- *\n- * @return\n- *   Maximum size of memory for items.\n- */\n-static int\n-flow_tcf_get_items_size(const struct rte_flow_attr *attr,\n-\t\t\tconst struct rte_flow_item items[],\n-\t\t\tuint64_t *action_flags)\n-{\n-\tint size = 0;\n-\n-\tsize += SZ_NLATTR_STRZ_OF(\"flower\") +\n-\t\tSZ_NLATTR_TYPE_OF(uint16_t) + /* Outer ether type. */\n-\t\tSZ_NLATTR_NEST + /* TCA_OPTIONS. */\n-\t\tSZ_NLATTR_TYPE_OF(uint32_t); /* TCA_CLS_FLAGS_SKIP_SW. */\n-\tif (attr->group > 0)\n-\t\tsize += SZ_NLATTR_TYPE_OF(uint32_t); /* TCA_CHAIN. */\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_PORT_ID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tsize += SZ_NLATTR_DATA_OF(RTE_ETHER_ADDR_LEN) * 4;\n-\t\t\t\t/* dst/src MAC addr and mask. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t\tsize +=\tSZ_NLATTR_TYPE_OF(uint16_t) +\n-\t\t\t\t/* VLAN Ether type. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint8_t) + /* VLAN prio. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint16_t); /* VLAN ID. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4: {\n-\t\t\tconst struct rte_flow_item_ipv4 *ipv4 = items->mask;\n-\n-\t\t\tsize +=\tSZ_NLATTR_TYPE_OF(uint8_t) + /* IP proto. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint32_t) * 4;\n-\t\t\t\t/* dst/src IP addr and mask. */\n-\t\t\tif (ipv4 && ipv4->hdr.time_to_live)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tif (ipv4 && ipv4->hdr.type_of_service)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6: {\n-\t\t\tconst struct rte_flow_item_ipv6 *ipv6 = items->mask;\n-\n-\t\t\tsize +=\tSZ_NLATTR_TYPE_OF(uint8_t) + /* IP proto. */\n-\t\t\t\tSZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) * 4;\n-\t\t\t\t/* dst/src IP addr and mask. */\n-\t\t\tif (ipv6 && ipv6->hdr.hop_limits)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tif (ipv6 && (rte_be_to_cpu_32(ipv6->hdr.vtc_flow) &\n-\t\t\t\t     (0xfful << RTE_IPV6_HDR_TC_SHIFT)))\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) + /* IP proto. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint16_t) * 4;\n-\t\t\t\t/* dst/src port and mask. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) + /* IP proto. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint16_t) * 4;\n-\t\t\t\t/* dst/src port and mask. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tsize += SZ_NLATTR_TYPE_OF(uint32_t);\n-\t\t\t/*\n-\t\t\t * There might be no VXLAN decap action in the action\n-\t\t\t * list, nonetheless the VXLAN tunnel flow requires\n-\t\t\t * the decap structure to be correctly applied to\n-\t\t\t * VXLAN device, set the flag to create the structure.\n-\t\t\t * Translation routine will not put the decap action\n-\t\t\t * in tne Netlink message if there is no actual action\n-\t\t\t * in the list.\n-\t\t\t */\n-\t\t\t*action_flags |= MLX5_FLOW_ACTION_VXLAN_DECAP;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\"unsupported item %p type %d,\"\n-\t\t\t\t\" items must be validated before flow creation\",\n-\t\t\t\t(const void *)items, items->type);\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\treturn size;\n-}\n-\n-/**\n- * Calculate size of memory to store the VXLAN encapsultion\n- * related items in the Netlink message buffer. Items list\n- * is specified by RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action.\n- * The item list should be validated.\n- *\n- * @param[in] action\n- *   RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action object.\n- *   List of pattern items to scan data from.\n- *\n- * @return\n- *   The size the part of Netlink message buffer to store the\n- *   VXLAN encapsulation item attributes.\n- */\n-static int\n-flow_tcf_vxlan_encap_size(const struct rte_flow_action *action)\n-{\n-\tconst struct rte_flow_item *items;\n-\tint size = 0;\n-\n-\tassert(action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP);\n-\tassert(action->conf);\n-\n-\titems = ((const struct rte_flow_action_vxlan_encap *)\n-\t\t\t\t\taction->conf)->definition;\n-\tassert(items);\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\t/* This item does not require message buffer. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4: {\n-\t\t\tconst struct rte_flow_item_ipv4 *ipv4 = items->mask;\n-\n-\t\t\tsize += SZ_NLATTR_DATA_OF(IPV4_ADDR_LEN) * 2;\n-\t\t\tif (ipv4 && ipv4->hdr.time_to_live)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tif (ipv4 && ipv4->hdr.type_of_service)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6: {\n-\t\t\tconst struct rte_flow_item_ipv6 *ipv6 = items->mask;\n-\n-\t\t\tsize += SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN) * 2;\n-\t\t\tif (ipv6 && ipv6->hdr.hop_limits)\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tif (ipv6 && (rte_be_to_cpu_32(ipv6->hdr.vtc_flow) &\n-\t\t\t\t     (0xfful << RTE_IPV6_HDR_TC_SHIFT)))\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint8_t) * 2;\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP: {\n-\t\t\tconst struct rte_flow_item_udp *udp = items->mask;\n-\n-\t\t\tsize += SZ_NLATTR_TYPE_OF(uint16_t);\n-\t\t\tif (!udp || udp->hdr.src_port != RTE_BE16(0x0000))\n-\t\t\t\tsize += SZ_NLATTR_TYPE_OF(uint16_t);\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tsize +=\tSZ_NLATTR_TYPE_OF(uint32_t);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tassert(false);\n-\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\"unsupported item %p type %d,\"\n-\t\t\t\t\" items must be validated\"\n-\t\t\t\t\" before flow creation\",\n-\t\t\t\t(const void *)items, items->type);\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n-\treturn size;\n-}\n-\n-/**\n- * Calculate maximum size of memory for flow actions of Linux TC flower and\n- * extract specified actions.\n- *\n- * @param[in] actions\n- *   Pointer to the list of actions.\n- * @param[out] action_flags\n- *   Pointer to the detected actions.\n- *\n- * @return\n- *   Maximum size of memory for actions.\n- */\n-static int\n-flow_tcf_get_actions_and_size(const struct rte_flow_action actions[],\n-\t\t\t      uint64_t *action_flags)\n-{\n-\tint size = 0;\n-\tuint64_t flags = *action_flags;\n-\n-\tsize += SZ_NLATTR_NEST; /* TCA_FLOWER_ACT. */\n-\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n-\t\tswitch (actions->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_PORT_ID:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"mirred\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(struct tc_mirred);\n-\t\t\tflags |= MLX5_FLOW_ACTION_PORT_ID;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"gact\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(struct tc_gact);\n-\t\t\tflags |= MLX5_FLOW_ACTION_JUMP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"gact\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(struct tc_gact);\n-\t\t\tflags |= MLX5_FLOW_ACTION_DROP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n-\t\t\tflags |= MLX5_FLOW_ACTION_OF_POP_VLAN;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n-\t\t\tflags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n-\t\t\tflags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:\n-\t\t\tflags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;\n-\t\t\tgoto action_of_vlan;\n-action_of_vlan:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"vlan\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(struct tc_vlan) +\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint16_t) +\n-\t\t\t\t/* VLAN protocol. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint16_t) + /* VLAN ID. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint8_t); /* VLAN prio. */\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"tunnel_key\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint8_t);\n-\t\t\tsize += SZ_NLATTR_TYPE_OF(struct tc_tunnel_key);\n-\t\t\tsize +=\tflow_tcf_vxlan_encap_size(actions) +\n-\t\t\t\tRTE_ALIGN_CEIL /* preceding encap params. */\n-\t\t\t\t(sizeof(struct flow_tcf_vxlan_encap),\n-\t\t\t\tMNL_ALIGNTO);\n-\t\t\tflags |= MLX5_FLOW_ACTION_VXLAN_ENCAP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n-\t\t\tsize += SZ_NLATTR_NEST + /* na_act_index. */\n-\t\t\t\tSZ_NLATTR_STRZ_OF(\"tunnel_key\") +\n-\t\t\t\tSZ_NLATTR_NEST + /* TCA_ACT_OPTIONS. */\n-\t\t\t\tSZ_NLATTR_TYPE_OF(uint8_t);\n-\t\t\tsize +=\tSZ_NLATTR_TYPE_OF(struct tc_tunnel_key);\n-\t\t\tsize +=\tRTE_ALIGN_CEIL /* preceding decap params. */\n-\t\t\t\t(sizeof(struct flow_tcf_vxlan_decap),\n-\t\t\t\tMNL_ALIGNTO);\n-\t\t\tflags |= MLX5_FLOW_ACTION_VXLAN_DECAP;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TTL:\n-\t\tcase RTE_FLOW_ACTION_TYPE_DEC_TTL:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_DST:\n-\t\t\tsize += flow_tcf_get_pedit_actions_size(&actions,\n-\t\t\t\t\t\t\t\t&flags);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\"unsupported action %p type %d,\"\n-\t\t\t\t\" items must be validated before flow creation\",\n-\t\t\t\t(const void *)actions, actions->type);\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\t*action_flags = flags;\n-\treturn size;\n-}\n-\n-/**\n- * Prepare a flow object for Linux TC flower. It calculates the maximum size of\n- * memory required, allocates the memory, initializes Netlink message headers\n- * and set unique TC message handle.\n- *\n- * @param[in] attr\n- *   Pointer to the flow attributes.\n- * @param[in] items\n- *   Pointer to the list of items.\n- * @param[in] actions\n- *   Pointer to the list of actions.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   Pointer to mlx5_flow object on success,\n- *   otherwise NULL and rte_errno is set.\n- */\n-static struct mlx5_flow *\n-flow_tcf_prepare(const struct rte_flow_attr *attr,\n-\t\t const struct rte_flow_item items[],\n-\t\t const struct rte_flow_action actions[],\n-\t\t struct rte_flow_error *error)\n-{\n-\tsize_t size = RTE_ALIGN_CEIL\n-\t\t\t(sizeof(struct mlx5_flow),\n-\t\t\t alignof(struct flow_tcf_tunnel_hdr)) +\n-\t\t      MNL_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t      MNL_ALIGN(sizeof(struct tcmsg));\n-\tstruct mlx5_flow *dev_flow;\n-\tuint64_t action_flags = 0;\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\tuint8_t *sp, *tun = NULL;\n-\n-\tsize += flow_tcf_get_items_size(attr, items, &action_flags);\n-\tsize += flow_tcf_get_actions_and_size(actions, &action_flags);\n-\tdev_flow = rte_zmalloc(__func__, size, MNL_ALIGNTO);\n-\tif (!dev_flow) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"not enough memory to create E-Switch flow\");\n-\t\treturn NULL;\n-\t}\n-\tsp = (uint8_t *)(dev_flow + 1);\n-\tif (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP) {\n-\t\tsp = RTE_PTR_ALIGN\n-\t\t\t(sp, alignof(struct flow_tcf_tunnel_hdr));\n-\t\ttun = sp;\n-\t\tsp += RTE_ALIGN_CEIL\n-\t\t\t(sizeof(struct flow_tcf_vxlan_encap),\n-\t\t\tMNL_ALIGNTO);\n-#ifndef NDEBUG\n-\t\tsize -= RTE_ALIGN_CEIL\n-\t\t\t(sizeof(struct flow_tcf_vxlan_encap),\n-\t\t\tMNL_ALIGNTO);\n-#endif\n-\t} else if (action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP) {\n-\t\tsp = RTE_PTR_ALIGN\n-\t\t\t(sp, alignof(struct flow_tcf_tunnel_hdr));\n-\t\ttun = sp;\n-\t\tsp += RTE_ALIGN_CEIL\n-\t\t\t(sizeof(struct flow_tcf_vxlan_decap),\n-\t\t\tMNL_ALIGNTO);\n-#ifndef NDEBUG\n-\t\tsize -= RTE_ALIGN_CEIL\n-\t\t\t(sizeof(struct flow_tcf_vxlan_decap),\n-\t\t\tMNL_ALIGNTO);\n-#endif\n-\t} else {\n-\t\tsp = RTE_PTR_ALIGN(sp, MNL_ALIGNTO);\n-\t}\n-\tnlh = mnl_nlmsg_put_header(sp);\n-\ttcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm));\n-\t*dev_flow = (struct mlx5_flow){\n-\t\t.tcf = (struct mlx5_flow_tcf){\n-#ifndef NDEBUG\n-\t\t\t.nlsize = size - RTE_ALIGN_CEIL\n-\t\t\t\t(sizeof(struct mlx5_flow),\n-\t\t\t\t alignof(struct flow_tcf_tunnel_hdr)),\n-#endif\n-\t\t\t.tunnel = (struct flow_tcf_tunnel_hdr *)tun,\n-\t\t\t.nlh = nlh,\n-\t\t\t.tcm = tcm,\n-\t\t},\n-\t};\n-\tif (action_flags & MLX5_FLOW_ACTION_VXLAN_DECAP)\n-\t\tdev_flow->tcf.tunnel->type = FLOW_TCF_TUNACT_VXLAN_DECAP;\n-\telse if (action_flags & MLX5_FLOW_ACTION_VXLAN_ENCAP)\n-\t\tdev_flow->tcf.tunnel->type = FLOW_TCF_TUNACT_VXLAN_ENCAP;\n-\treturn dev_flow;\n-}\n-\n-/**\n- * Make adjustments for supporting count actions.\n- *\n- * @param[in] dev\n- *   Pointer to the Ethernet device structure.\n- * @param[in] dev_flow\n- *   Pointer to mlx5_flow.\n- * @param[out] error\n- *   Pointer to error structure.\n- *\n- * @return\n- *   0 On success else a negative errno value is returned and rte_errno is set.\n- */\n-static int\n-flow_tcf_translate_action_count(struct rte_eth_dev *dev __rte_unused,\n-\t\t\t\t  struct mlx5_flow *dev_flow,\n-\t\t\t\t  struct rte_flow_error *error)\n-{\n-\tstruct rte_flow *flow = dev_flow->flow;\n-\n-\tif (!flow->counter) {\n-\t\tflow->counter = flow_tcf_counter_new();\n-\t\tif (!flow->counter)\n-\t\t\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  NULL,\n-\t\t\t\t\t\t  \"cannot get counter\"\n-\t\t\t\t\t\t  \" context.\");\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Convert VXLAN VNI to 32-bit integer.\n- *\n- * @param[in] vni\n- *   VXLAN VNI in 24-bit wire format.\n- *\n- * @return\n- *   VXLAN VNI as a 32-bit integer value in network endianness.\n- */\n-static inline rte_be32_t\n-vxlan_vni_as_be32(const uint8_t vni[3])\n-{\n-\tunion {\n-\t\tuint8_t vni[4];\n-\t\trte_be32_t dword;\n-\t} ret = {\n-\t\t.vni = { 0, vni[0], vni[1], vni[2] },\n-\t};\n-\treturn ret.dword;\n-}\n-\n-/**\n- * Helper function to process RTE_FLOW_ITEM_TYPE_ETH entry in configuration\n- * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the MAC address fields\n- * in the encapsulation parameters structure. The item must be prevalidated,\n- * no any validation checks performed by function.\n- *\n- * @param[in] spec\n- *   RTE_FLOW_ITEM_TYPE_ETH entry specification.\n- * @param[in] mask\n- *   RTE_FLOW_ITEM_TYPE_ETH entry mask.\n- * @param[out] encap\n- *   Structure to fill the gathered MAC address data.\n- */\n-static void\n-flow_tcf_parse_vxlan_encap_eth(const struct rte_flow_item_eth *spec,\n-\t\t\t       const struct rte_flow_item_eth *mask,\n-\t\t\t       struct flow_tcf_vxlan_encap *encap)\n-{\n-\t/* Item must be validated before. No redundant checks. */\n-\tassert(spec);\n-\tif (!mask || !memcmp(&mask->dst,\n-\t\t\t     &rte_flow_item_eth_mask.dst,\n-\t\t\t     sizeof(rte_flow_item_eth_mask.dst))) {\n-\t\t/*\n-\t\t * Ethernet addresses are not supported by\n-\t\t * tc as tunnel_key parameters. Destination\n-\t\t * address is needed to form encap packet\n-\t\t * header and retrieved by kernel from\n-\t\t * implicit sources (ARP table, etc),\n-\t\t * address masks are not supported at all.\n-\t\t */\n-\t\tencap->eth.dst = spec->dst;\n-\t\tencap->mask |= FLOW_TCF_ENCAP_ETH_DST;\n-\t}\n-\tif (!mask || !memcmp(&mask->src,\n-\t\t\t     &rte_flow_item_eth_mask.src,\n-\t\t\t     sizeof(rte_flow_item_eth_mask.src))) {\n-\t\t/*\n-\t\t * Ethernet addresses are not supported by\n-\t\t * tc as tunnel_key parameters. Source ethernet\n-\t\t * address is ignored anyway.\n-\t\t */\n-\t\tencap->eth.src = spec->src;\n-\t\tencap->mask |= FLOW_TCF_ENCAP_ETH_SRC;\n-\t}\n-}\n-\n-/**\n- * Helper function to process RTE_FLOW_ITEM_TYPE_IPV4 entry in configuration\n- * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the IPV4 address fields\n- * in the encapsulation parameters structure. The item must be prevalidated,\n- * no any validation checks performed by function.\n- *\n- * @param[in] spec\n- *   RTE_FLOW_ITEM_TYPE_IPV4 entry specification.\n- * @param[in] mask\n- *  RTE_FLOW_ITEM_TYPE_IPV4 entry mask.\n- * @param[out] encap\n- *   Structure to fill the gathered IPV4 address data.\n- */\n-static void\n-flow_tcf_parse_vxlan_encap_ipv4(const struct rte_flow_item_ipv4 *spec,\n-\t\t\t\tconst struct rte_flow_item_ipv4 *mask,\n-\t\t\t\tstruct flow_tcf_vxlan_encap *encap)\n-{\n-\t/* Item must be validated before. No redundant checks. */\n-\tassert(spec);\n-\tencap->ipv4.dst = spec->hdr.dst_addr;\n-\tencap->ipv4.src = spec->hdr.src_addr;\n-\tencap->mask |= FLOW_TCF_ENCAP_IPV4_SRC |\n-\t\t       FLOW_TCF_ENCAP_IPV4_DST;\n-\tif (mask && mask->hdr.type_of_service) {\n-\t\tencap->mask |= FLOW_TCF_ENCAP_IP_TOS;\n-\t\tencap->ip_tos = spec->hdr.type_of_service;\n-\t}\n-\tif (mask && mask->hdr.time_to_live) {\n-\t\tencap->mask |= FLOW_TCF_ENCAP_IP_TTL;\n-\t\tencap->ip_ttl_hop = spec->hdr.time_to_live;\n-\t}\n-}\n-\n-/**\n- * Helper function to process RTE_FLOW_ITEM_TYPE_IPV6 entry in configuration\n- * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the IPV6 address fields\n- * in the encapsulation parameters structure. The item must be prevalidated,\n- * no any validation checks performed by function.\n- *\n- * @param[in] spec\n- *   RTE_FLOW_ITEM_TYPE_IPV6 entry specification.\n- * @param[in] mask\n- *  RTE_FLOW_ITEM_TYPE_IPV6 entry mask.\n- * @param[out] encap\n- *   Structure to fill the gathered IPV6 address data.\n- */\n-static void\n-flow_tcf_parse_vxlan_encap_ipv6(const struct rte_flow_item_ipv6 *spec,\n-\t\t\t\tconst struct rte_flow_item_ipv6 *mask,\n-\t\t\t\tstruct flow_tcf_vxlan_encap *encap)\n-{\n-\t/* Item must be validated before. No redundant checks. */\n-\tassert(spec);\n-\tmemcpy(encap->ipv6.dst, spec->hdr.dst_addr, IPV6_ADDR_LEN);\n-\tmemcpy(encap->ipv6.src, spec->hdr.src_addr, IPV6_ADDR_LEN);\n-\tencap->mask |= FLOW_TCF_ENCAP_IPV6_SRC |\n-\t\t       FLOW_TCF_ENCAP_IPV6_DST;\n-\tif (mask) {\n-\t\tif ((rte_be_to_cpu_32(mask->hdr.vtc_flow) >>\n-\t\t    RTE_IPV6_HDR_TC_SHIFT) & 0xff) {\n-\t\t\tencap->mask |= FLOW_TCF_ENCAP_IP_TOS;\n-\t\t\tencap->ip_tos = (rte_be_to_cpu_32\n-\t\t\t\t\t\t(spec->hdr.vtc_flow) >>\n-\t\t\t\t\t\t RTE_IPV6_HDR_TC_SHIFT) & 0xff;\n-\t\t}\n-\t\tif (mask->hdr.hop_limits) {\n-\t\t\tencap->mask |= FLOW_TCF_ENCAP_IP_TTL;\n-\t\t\tencap->ip_ttl_hop = spec->hdr.hop_limits;\n-\t\t}\n-\t}\n-}\n-\n-/**\n- * Helper function to process RTE_FLOW_ITEM_TYPE_UDP entry in configuration\n- * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the UDP port fields\n- * in the encapsulation parameters structure. The item must be prevalidated,\n- * no any validation checks performed by function.\n- *\n- * @param[in] spec\n- *   RTE_FLOW_ITEM_TYPE_UDP entry specification.\n- * @param[in] mask\n- *   RTE_FLOW_ITEM_TYPE_UDP entry mask.\n- * @param[out] encap\n- *   Structure to fill the gathered UDP port data.\n- */\n-static void\n-flow_tcf_parse_vxlan_encap_udp(const struct rte_flow_item_udp *spec,\n-\t\t\t       const struct rte_flow_item_udp *mask,\n-\t\t\t       struct flow_tcf_vxlan_encap *encap)\n-{\n-\tassert(spec);\n-\tencap->udp.dst = spec->hdr.dst_port;\n-\tencap->mask |= FLOW_TCF_ENCAP_UDP_DST;\n-\tif (!mask || mask->hdr.src_port != RTE_BE16(0x0000)) {\n-\t\tencap->udp.src = spec->hdr.src_port;\n-\t\tencap->mask |= FLOW_TCF_ENCAP_IPV4_SRC;\n-\t}\n-}\n-\n-/**\n- * Helper function to process RTE_FLOW_ITEM_TYPE_VXLAN entry in configuration\n- * of action RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. Fills the VNI fields\n- * in the encapsulation parameters structure. The item must be prevalidated,\n- * no any validation checks performed by function.\n- *\n- * @param[in] spec\n- *   RTE_FLOW_ITEM_TYPE_VXLAN entry specification.\n- * @param[out] encap\n- *   Structure to fill the gathered VNI address data.\n- */\n-static void\n-flow_tcf_parse_vxlan_encap_vni(const struct rte_flow_item_vxlan *spec,\n-\t\t\t       struct flow_tcf_vxlan_encap *encap)\n-{\n-\t/* Item must be validated before. Do not redundant checks. */\n-\tassert(spec);\n-\tmemcpy(encap->vxlan.vni, spec->vni, sizeof(encap->vxlan.vni));\n-\tencap->mask |= FLOW_TCF_ENCAP_VXLAN_VNI;\n-}\n-\n-/**\n- * Populate consolidated encapsulation object from list of pattern items.\n- *\n- * Helper function to process configuration of action such as\n- * RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP. The item list should be\n- * validated, there is no way to return an meaningful error.\n- *\n- * @param[in] action\n- *   RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP action object.\n- *   List of pattern items to gather data from.\n- * @param[out] src\n- *   Structure to fill gathered data.\n- */\n-static void\n-flow_tcf_vxlan_encap_parse(const struct rte_flow_action *action,\n-\t\t\t   struct flow_tcf_vxlan_encap *encap)\n-{\n-\tunion {\n-\t\tconst struct rte_flow_item_eth *eth;\n-\t\tconst struct rte_flow_item_ipv4 *ipv4;\n-\t\tconst struct rte_flow_item_ipv6 *ipv6;\n-\t\tconst struct rte_flow_item_udp *udp;\n-\t\tconst struct rte_flow_item_vxlan *vxlan;\n-\t} spec, mask;\n-\tconst struct rte_flow_item *items;\n-\n-\tassert(action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP);\n-\tassert(action->conf);\n-\n-\titems = ((const struct rte_flow_action_vxlan_encap *)\n-\t\t\t\t\taction->conf)->definition;\n-\tassert(items);\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\tmask.eth = items->mask;\n-\t\t\tspec.eth = items->spec;\n-\t\t\tflow_tcf_parse_vxlan_encap_eth(spec.eth, mask.eth,\n-\t\t\t\t\t\t       encap);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\tspec.ipv4 = items->spec;\n-\t\t\tmask.ipv4 = items->mask;\n-\t\t\tflow_tcf_parse_vxlan_encap_ipv4(spec.ipv4, mask.ipv4,\n-\t\t\t\t\t\t\tencap);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6:\n-\t\t\tspec.ipv6 = items->spec;\n-\t\t\tmask.ipv6 = items->mask;\n-\t\t\tflow_tcf_parse_vxlan_encap_ipv6(spec.ipv6, mask.ipv6,\n-\t\t\t\t\t\t\tencap);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\tmask.udp = items->mask;\n-\t\t\tspec.udp = items->spec;\n-\t\t\tflow_tcf_parse_vxlan_encap_udp(spec.udp, mask.udp,\n-\t\t\t\t\t\t       encap);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tspec.vxlan = items->spec;\n-\t\t\tflow_tcf_parse_vxlan_encap_vni(spec.vxlan, encap);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tassert(false);\n-\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\"unsupported item %p type %d,\"\n-\t\t\t\t\" items must be validated\"\n-\t\t\t\t\" before flow creation\",\n-\t\t\t\t(const void *)items, items->type);\n-\t\t\tencap->mask = 0;\n-\t\t\treturn;\n-\t\t}\n-\t}\n-}\n-\n-/**\n- * Translate flow for Linux TC flower and construct Netlink message.\n- *\n- * @param[in] priv\n- *   Pointer to the priv structure.\n- * @param[in, out] flow\n- *   Pointer to the sub flow.\n- * @param[in] attr\n- *   Pointer to the flow attributes.\n- * @param[in] items\n- *   Pointer to the list of items.\n- * @param[in] actions\n- *   Pointer to the list of actions.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_translate(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow,\n-\t\t   const struct rte_flow_attr *attr,\n-\t\t   const struct rte_flow_item items[],\n-\t\t   const struct rte_flow_action actions[],\n-\t\t   struct rte_flow_error *error)\n-{\n-\tunion {\n-\t\tconst struct rte_flow_item_port_id *port_id;\n-\t\tconst struct rte_flow_item_eth *eth;\n-\t\tconst struct rte_flow_item_vlan *vlan;\n-\t\tconst struct rte_flow_item_ipv4 *ipv4;\n-\t\tconst struct rte_flow_item_ipv6 *ipv6;\n-\t\tconst struct rte_flow_item_tcp *tcp;\n-\t\tconst struct rte_flow_item_udp *udp;\n-\t\tconst struct rte_flow_item_vxlan *vxlan;\n-\t} spec, mask;\n-\tunion {\n-\t\tconst struct rte_flow_action_port_id *port_id;\n-\t\tconst struct rte_flow_action_jump *jump;\n-\t\tconst struct rte_flow_action_of_push_vlan *of_push_vlan;\n-\t\tconst struct rte_flow_action_of_set_vlan_vid *\n-\t\t\tof_set_vlan_vid;\n-\t\tconst struct rte_flow_action_of_set_vlan_pcp *\n-\t\t\tof_set_vlan_pcp;\n-\t} conf;\n-\tunion {\n-\t\tstruct flow_tcf_tunnel_hdr *hdr;\n-\t\tstruct flow_tcf_vxlan_decap *vxlan;\n-\t} decap = {\n-\t\t.hdr = NULL,\n-\t};\n-\tunion {\n-\t\tstruct flow_tcf_tunnel_hdr *hdr;\n-\t\tstruct flow_tcf_vxlan_encap *vxlan;\n-\t} encap = {\n-\t\t.hdr = NULL,\n-\t};\n-\tstruct flow_tcf_ptoi ptoi[PTOI_TABLE_SZ_MAX(dev)];\n-\tstruct nlmsghdr *nlh = dev_flow->tcf.nlh;\n-\tstruct tcmsg *tcm = dev_flow->tcf.tcm;\n-\tuint32_t na_act_index_cur;\n-\trte_be16_t inner_etype = RTE_BE16(ETH_P_ALL);\n-\trte_be16_t outer_etype = RTE_BE16(ETH_P_ALL);\n-\trte_be16_t vlan_etype = RTE_BE16(ETH_P_ALL);\n-\tbool ip_proto_set = 0;\n-\tbool tunnel_outer = 0;\n-\tstruct nlattr *na_flower;\n-\tstruct nlattr *na_flower_act;\n-\tstruct nlattr *na_vlan_id = NULL;\n-\tstruct nlattr *na_vlan_priority = NULL;\n-\tuint64_t item_flags = 0;\n-\tint ret;\n-\n-\tclaim_nonzero(flow_tcf_build_ptoi_table(dev, ptoi,\n-\t\t\t\t\t\tPTOI_TABLE_SZ_MAX(dev)));\n-\tif (dev_flow->tcf.tunnel) {\n-\t\tswitch (dev_flow->tcf.tunnel->type) {\n-\t\tcase FLOW_TCF_TUNACT_VXLAN_DECAP:\n-\t\t\tdecap.vxlan = dev_flow->tcf.vxlan_decap;\n-\t\t\ttunnel_outer = 1;\n-\t\t\tbreak;\n-\t\tcase FLOW_TCF_TUNACT_VXLAN_ENCAP:\n-\t\t\tencap.vxlan = dev_flow->tcf.vxlan_encap;\n-\t\t\tbreak;\n-\t\t/* New tunnel actions can be added here. */\n-\t\tdefault:\n-\t\t\tassert(false);\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\tnlh = dev_flow->tcf.nlh;\n-\ttcm = dev_flow->tcf.tcm;\n-\t/* Prepare API must have been called beforehand. */\n-\tassert(nlh != NULL && tcm != NULL);\n-\ttcm->tcm_family = AF_UNSPEC;\n-\ttcm->tcm_ifindex = ptoi[0].ifindex;\n-\ttcm->tcm_parent = TC_H_MAKE(TC_H_INGRESS, TC_H_MIN_INGRESS);\n-\t/*\n-\t * Priority cannot be zero to prevent the kernel from picking one\n-\t * automatically.\n-\t */\n-\ttcm->tcm_info = TC_H_MAKE((attr->priority + 1) << 16, outer_etype);\n-\tif (attr->group > 0)\n-\t\tmnl_attr_put_u32(nlh, TCA_CHAIN, attr->group);\n-\tmnl_attr_put_strz(nlh, TCA_KIND, \"flower\");\n-\tna_flower = mnl_attr_nest_start(nlh, TCA_OPTIONS);\n-\tfor (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {\n-\t\tunsigned int i;\n-\n-\t\tswitch (items->type) {\n-\t\tcase RTE_FLOW_ITEM_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_PORT_ID:\n-\t\t\tmask.port_id = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_port_id_mask,\n-\t\t\t\t &flow_tcf_mask_supported.port_id,\n-\t\t\t\t &flow_tcf_mask_empty.port_id,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.port_id),\n-\t\t\t\t error);\n-\t\t\tassert(mask.port_id);\n-\t\t\tif (mask.port_id == &flow_tcf_mask_empty.port_id)\n-\t\t\t\tbreak;\n-\t\t\tspec.port_id = items->spec;\n-\t\t\tif (!mask.port_id->id)\n-\t\t\t\ti = 0;\n-\t\t\telse\n-\t\t\t\tfor (i = 0; ptoi[i].ifindex; ++i)\n-\t\t\t\t\tif (ptoi[i].port_id == spec.port_id->id)\n-\t\t\t\t\t\tbreak;\n-\t\t\tassert(ptoi[i].ifindex);\n-\t\t\ttcm->tcm_ifindex = ptoi[i].ifindex;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_ETH:\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L2 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L2;\n-\t\t\tmask.eth = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_eth_mask,\n-\t\t\t\t &flow_tcf_mask_supported.eth,\n-\t\t\t\t &flow_tcf_mask_empty.eth,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.eth),\n-\t\t\t\t error);\n-\t\t\tassert(mask.eth);\n-\t\t\tif (mask.eth == &flow_tcf_mask_empty.eth)\n-\t\t\t\tbreak;\n-\t\t\tspec.eth = items->spec;\n-\t\t\tif (mask.eth->type) {\n-\t\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL)\n-\t\t\t\t\tinner_etype = spec.eth->type;\n-\t\t\t\telse\n-\t\t\t\t\touter_etype = spec.eth->type;\n-\t\t\t}\n-\t\t\tif (tunnel_outer) {\n-\t\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\t\"outer L2 addresses cannot be\"\n-\t\t\t\t\t\" forced is outer ones for tunnel,\"\n-\t\t\t\t\t\" parameter is ignored\");\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (!rte_is_zero_ether_addr(&mask.eth->dst)) {\n-\t\t\t\tmnl_attr_put(nlh, TCA_FLOWER_KEY_ETH_DST,\n-\t\t\t\t\t     RTE_ETHER_ADDR_LEN,\n-\t\t\t\t\t     spec.eth->dst.addr_bytes);\n-\t\t\t\tmnl_attr_put(nlh, TCA_FLOWER_KEY_ETH_DST_MASK,\n-\t\t\t\t\t     RTE_ETHER_ADDR_LEN,\n-\t\t\t\t\t     mask.eth->dst.addr_bytes);\n-\t\t\t}\n-\t\t\tif (!rte_is_zero_ether_addr(&mask.eth->src)) {\n-\t\t\t\tmnl_attr_put(nlh, TCA_FLOWER_KEY_ETH_SRC,\n-\t\t\t\t\t     RTE_ETHER_ADDR_LEN,\n-\t\t\t\t\t     spec.eth->src.addr_bytes);\n-\t\t\t\tmnl_attr_put(nlh, TCA_FLOWER_KEY_ETH_SRC_MASK,\n-\t\t\t\t\t     RTE_ETHER_ADDR_LEN,\n-\t\t\t\t\t     mask.eth->src.addr_bytes);\n-\t\t\t}\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VLAN:\n-\t\t\tassert(!encap.hdr);\n-\t\t\tassert(!decap.hdr);\n-\t\t\tassert(!tunnel_outer);\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_OUTER_VLAN;\n-\t\t\tmask.vlan = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_vlan_mask,\n-\t\t\t\t &flow_tcf_mask_supported.vlan,\n-\t\t\t\t &flow_tcf_mask_empty.vlan,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.vlan),\n-\t\t\t\t error);\n-\t\t\tassert(mask.vlan);\n-\t\t\tif (mask.vlan == &flow_tcf_mask_empty.vlan)\n-\t\t\t\tbreak;\n-\t\t\tspec.vlan = items->spec;\n-\t\t\tassert(outer_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t       outer_etype == RTE_BE16(ETH_P_8021Q));\n-\t\t\touter_etype = RTE_BE16(ETH_P_8021Q);\n-\t\t\tif (mask.vlan->inner_type)\n-\t\t\t\tvlan_etype = spec.vlan->inner_type;\n-\t\t\tif (mask.vlan->tci & RTE_BE16(0xe000))\n-\t\t\t\tmnl_attr_put_u8(nlh, TCA_FLOWER_KEY_VLAN_PRIO,\n-\t\t\t\t\t\t(rte_be_to_cpu_16\n-\t\t\t\t\t\t (spec.vlan->tci) >> 13) & 0x7);\n-\t\t\tif (mask.vlan->tci & RTE_BE16(0x0fff))\n-\t\t\t\tmnl_attr_put_u16(nlh, TCA_FLOWER_KEY_VLAN_ID,\n-\t\t\t\t\t\t rte_be_to_cpu_16\n-\t\t\t\t\t\t (spec.vlan->tci &\n-\t\t\t\t\t\t  RTE_BE16(0x0fff)));\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV4:\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L3_IPV4 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV4;\n-\t\t\tmask.ipv4 = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_ipv4_mask,\n-\t\t\t\t &flow_tcf_mask_supported.ipv4,\n-\t\t\t\t &flow_tcf_mask_empty.ipv4,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.ipv4),\n-\t\t\t\t error);\n-\t\t\tassert(mask.ipv4);\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL) {\n-\t\t\t\tassert(inner_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       inner_etype == RTE_BE16(ETH_P_IP));\n-\t\t\t\tinner_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t} else if (outer_etype == RTE_BE16(ETH_P_8021Q)) {\n-\t\t\t\tassert(vlan_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       vlan_etype == RTE_BE16(ETH_P_IP));\n-\t\t\t\tvlan_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t} else {\n-\t\t\t\tassert(outer_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       outer_etype == RTE_BE16(ETH_P_IP));\n-\t\t\t\touter_etype = RTE_BE16(ETH_P_IP);\n-\t\t\t}\n-\t\t\tspec.ipv4 = items->spec;\n-\t\t\tif (!tunnel_outer && mask.ipv4->hdr.next_proto_id) {\n-\t\t\t\t/*\n-\t\t\t\t * No way to set IP protocol for outer tunnel\n-\t\t\t\t * layers. Usually it is fixed, for example,\n-\t\t\t\t * to UDP for VXLAN/GPE.\n-\t\t\t\t */\n-\t\t\t\tassert(spec.ipv4); /* Mask is not empty. */\n-\t\t\t\tmnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,\n-\t\t\t\t\t\tspec.ipv4->hdr.next_proto_id);\n-\t\t\t\tip_proto_set = 1;\n-\t\t\t}\n-\t\t\tif (mask.ipv4 == &flow_tcf_mask_empty.ipv4 ||\n-\t\t\t     (!mask.ipv4->hdr.src_addr &&\n-\t\t\t      !mask.ipv4->hdr.dst_addr)) {\n-\t\t\t\tif (!tunnel_outer)\n-\t\t\t\t\tbreak;\n-\t\t\t\t/*\n-\t\t\t\t * For tunnel outer we must set outer IP key\n-\t\t\t\t * anyway, even if the specification/mask is\n-\t\t\t\t * empty. There is no another way to tell\n-\t\t\t\t * kernel about he outer layer protocol.\n-\t\t\t\t */\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, TCA_FLOWER_KEY_ENC_IPV4_SRC,\n-\t\t\t\t\t mask.ipv4->hdr.src_addr);\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,\n-\t\t\t\t\t mask.ipv4->hdr.src_addr);\n-\t\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (mask.ipv4->hdr.src_addr) {\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IPV4_SRC :\n-\t\t\t\t\t TCA_FLOWER_KEY_IPV4_SRC,\n-\t\t\t\t\t spec.ipv4->hdr.src_addr);\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IPV4_SRC_MASK,\n-\t\t\t\t\t mask.ipv4->hdr.src_addr);\n-\t\t\t}\n-\t\t\tif (mask.ipv4->hdr.dst_addr) {\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IPV4_DST :\n-\t\t\t\t\t TCA_FLOWER_KEY_IPV4_DST,\n-\t\t\t\t\t spec.ipv4->hdr.dst_addr);\n-\t\t\t\tmnl_attr_put_u32\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IPV4_DST_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IPV4_DST_MASK,\n-\t\t\t\t\t mask.ipv4->hdr.dst_addr);\n-\t\t\t}\n-\t\t\tif (mask.ipv4->hdr.time_to_live) {\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TTL :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TTL,\n-\t\t\t\t\t spec.ipv4->hdr.time_to_live);\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TTL_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TTL_MASK,\n-\t\t\t\t\t mask.ipv4->hdr.time_to_live);\n-\t\t\t}\n-\t\t\tif (mask.ipv4->hdr.type_of_service) {\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TOS :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TOS,\n-\t\t\t\t\t spec.ipv4->hdr.type_of_service);\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TOS_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TOS_MASK,\n-\t\t\t\t\t mask.ipv4->hdr.type_of_service);\n-\t\t\t}\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_IPV6: {\n-\t\t\tbool ipv6_src, ipv6_dst;\n-\t\t\tuint8_t msk6, tos6;\n-\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L3_IPV6 :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L3_IPV6;\n-\t\t\tmask.ipv6 = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_ipv6_mask,\n-\t\t\t\t &flow_tcf_mask_supported.ipv6,\n-\t\t\t\t &flow_tcf_mask_empty.ipv6,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.ipv6),\n-\t\t\t\t error);\n-\t\t\tassert(mask.ipv6);\n-\t\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL) {\n-\t\t\t\tassert(inner_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       inner_etype == RTE_BE16(ETH_P_IPV6));\n-\t\t\t\tinner_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t} else if (outer_etype == RTE_BE16(ETH_P_8021Q)) {\n-\t\t\t\tassert(vlan_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       vlan_etype == RTE_BE16(ETH_P_IPV6));\n-\t\t\t\tvlan_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t} else {\n-\t\t\t\tassert(outer_etype == RTE_BE16(ETH_P_ALL) ||\n-\t\t\t\t       outer_etype == RTE_BE16(ETH_P_IPV6));\n-\t\t\t\touter_etype = RTE_BE16(ETH_P_IPV6);\n-\t\t\t}\n-\t\t\tspec.ipv6 = items->spec;\n-\t\t\tif (!tunnel_outer && mask.ipv6->hdr.proto) {\n-\t\t\t\t/*\n-\t\t\t\t * No way to set IP protocol for outer tunnel\n-\t\t\t\t * layers. Usually it is fixed, for example,\n-\t\t\t\t * to UDP for VXLAN/GPE.\n-\t\t\t\t */\n-\t\t\t\tassert(spec.ipv6); /* Mask is not empty. */\n-\t\t\t\tmnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,\n-\t\t\t\t\t\tspec.ipv6->hdr.proto);\n-\t\t\t\tip_proto_set = 1;\n-\t\t\t}\n-\t\t\tipv6_dst = !IN6_IS_ADDR_UNSPECIFIED\n-\t\t\t\t\t\t(mask.ipv6->hdr.dst_addr);\n-\t\t\tipv6_src = !IN6_IS_ADDR_UNSPECIFIED\n-\t\t\t\t\t\t(mask.ipv6->hdr.src_addr);\n-\t\t\tif (mask.ipv6 == &flow_tcf_mask_empty.ipv6 ||\n-\t\t\t     (!ipv6_dst && !ipv6_src)) {\n-\t\t\t\tif (!tunnel_outer)\n-\t\t\t\t\tbreak;\n-\t\t\t\t/*\n-\t\t\t\t * For tunnel outer we must set outer IP key\n-\t\t\t\t * anyway, even if the specification/mask is\n-\t\t\t\t * empty. There is no another way to tell\n-\t\t\t\t * kernel about he outer layer protocol.\n-\t\t\t\t */\n-\t\t\t\tmnl_attr_put(nlh,\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_SRC,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     mask.ipv6->hdr.src_addr);\n-\t\t\t\tmnl_attr_put(nlh,\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     mask.ipv6->hdr.src_addr);\n-\t\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (ipv6_src) {\n-\t\t\t\tmnl_attr_put(nlh, tunnel_outer ?\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_SRC :\n-\t\t\t\t\t     TCA_FLOWER_KEY_IPV6_SRC,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     spec.ipv6->hdr.src_addr);\n-\t\t\t\tmnl_attr_put(nlh, tunnel_outer ?\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK :\n-\t\t\t\t\t     TCA_FLOWER_KEY_IPV6_SRC_MASK,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     mask.ipv6->hdr.src_addr);\n-\t\t\t}\n-\t\t\tif (ipv6_dst) {\n-\t\t\t\tmnl_attr_put(nlh, tunnel_outer ?\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_DST :\n-\t\t\t\t\t     TCA_FLOWER_KEY_IPV6_DST,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     spec.ipv6->hdr.dst_addr);\n-\t\t\t\tmnl_attr_put(nlh, tunnel_outer ?\n-\t\t\t\t\t     TCA_FLOWER_KEY_ENC_IPV6_DST_MASK :\n-\t\t\t\t\t     TCA_FLOWER_KEY_IPV6_DST_MASK,\n-\t\t\t\t\t     IPV6_ADDR_LEN,\n-\t\t\t\t\t     mask.ipv6->hdr.dst_addr);\n-\t\t\t}\n-\t\t\tif (mask.ipv6->hdr.hop_limits) {\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TTL :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TTL,\n-\t\t\t\t\t spec.ipv6->hdr.hop_limits);\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TTL_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TTL_MASK,\n-\t\t\t\t\t mask.ipv6->hdr.hop_limits);\n-\t\t\t}\n-\t\t\tmsk6 = (rte_be_to_cpu_32(mask.ipv6->hdr.vtc_flow) >>\n-\t\t\t\tRTE_IPV6_HDR_TC_SHIFT) & 0xff;\n-\t\t\tif (msk6) {\n-\t\t\t\ttos6 = (rte_be_to_cpu_32\n-\t\t\t\t\t(spec.ipv6->hdr.vtc_flow) >>\n-\t\t\t\t\t\tRTE_IPV6_HDR_TC_SHIFT) & 0xff;\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TOS :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TOS, tos6);\n-\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_IP_TOS_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_IP_TOS_MASK, msk6);\n-\t\t\t}\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\t}\n-\t\tcase RTE_FLOW_ITEM_TYPE_UDP:\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L4_UDP :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L4_UDP;\n-\t\t\tmask.udp = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_udp_mask,\n-\t\t\t\t &flow_tcf_mask_supported.udp,\n-\t\t\t\t &flow_tcf_mask_empty.udp,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.udp),\n-\t\t\t\t error);\n-\t\t\tassert(mask.udp);\n-\t\t\tspec.udp = items->spec;\n-\t\t\tif (!tunnel_outer) {\n-\t\t\t\tif (!ip_proto_set)\n-\t\t\t\t\tmnl_attr_put_u8\n-\t\t\t\t\t\t(nlh, TCA_FLOWER_KEY_IP_PROTO,\n-\t\t\t\t\t\tIPPROTO_UDP);\n-\t\t\t\tif (mask.udp == &flow_tcf_mask_empty.udp)\n-\t\t\t\t\tbreak;\n-\t\t\t} else {\n-\t\t\t\tassert(mask.udp != &flow_tcf_mask_empty.udp);\n-\t\t\t\tdecap.vxlan->udp_port =\n-\t\t\t\t\trte_be_to_cpu_16\n-\t\t\t\t\t\t(spec.udp->hdr.dst_port);\n-\t\t\t}\n-\t\t\tif (mask.udp->hdr.src_port) {\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_UDP_SRC_PORT :\n-\t\t\t\t\t TCA_FLOWER_KEY_UDP_SRC,\n-\t\t\t\t\t spec.udp->hdr.src_port);\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_UDP_SRC_MASK,\n-\t\t\t\t\t mask.udp->hdr.src_port);\n-\t\t\t}\n-\t\t\tif (mask.udp->hdr.dst_port) {\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_UDP_DST_PORT :\n-\t\t\t\t\t TCA_FLOWER_KEY_UDP_DST,\n-\t\t\t\t\t spec.udp->hdr.dst_port);\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh, tunnel_outer ?\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK :\n-\t\t\t\t\t TCA_FLOWER_KEY_UDP_DST_MASK,\n-\t\t\t\t\t mask.udp->hdr.dst_port);\n-\t\t\t}\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_TCP:\n-\t\t\titem_flags |= (item_flags & MLX5_FLOW_LAYER_TUNNEL) ?\n-\t\t\t\t      MLX5_FLOW_LAYER_INNER_L4_TCP :\n-\t\t\t\t      MLX5_FLOW_LAYER_OUTER_L4_TCP;\n-\t\t\tmask.tcp = flow_tcf_item_mask\n-\t\t\t\t(items, &rte_flow_item_tcp_mask,\n-\t\t\t\t &flow_tcf_mask_supported.tcp,\n-\t\t\t\t &flow_tcf_mask_empty.tcp,\n-\t\t\t\t sizeof(flow_tcf_mask_supported.tcp),\n-\t\t\t\t error);\n-\t\t\tassert(mask.tcp);\n-\t\t\tif (!ip_proto_set)\n-\t\t\t\tmnl_attr_put_u8(nlh, TCA_FLOWER_KEY_IP_PROTO,\n-\t\t\t\t\t\tIPPROTO_TCP);\n-\t\t\tif (mask.tcp == &flow_tcf_mask_empty.tcp)\n-\t\t\t\tbreak;\n-\t\t\tspec.tcp = items->spec;\n-\t\t\tif (mask.tcp->hdr.src_port) {\n-\t\t\t\tmnl_attr_put_u16(nlh, TCA_FLOWER_KEY_TCP_SRC,\n-\t\t\t\t\t\t spec.tcp->hdr.src_port);\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t\t TCA_FLOWER_KEY_TCP_SRC_MASK,\n-\t\t\t\t\t\t mask.tcp->hdr.src_port);\n-\t\t\t}\n-\t\t\tif (mask.tcp->hdr.dst_port) {\n-\t\t\t\tmnl_attr_put_u16(nlh, TCA_FLOWER_KEY_TCP_DST,\n-\t\t\t\t\t\t spec.tcp->hdr.dst_port);\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t\t TCA_FLOWER_KEY_TCP_DST_MASK,\n-\t\t\t\t\t\t mask.tcp->hdr.dst_port);\n-\t\t\t}\n-\t\t\tif (mask.tcp->hdr.tcp_flags) {\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh,\n-\t\t\t\t\t TCA_FLOWER_KEY_TCP_FLAGS,\n-\t\t\t\t\t rte_cpu_to_be_16\n-\t\t\t\t\t\t(spec.tcp->hdr.tcp_flags));\n-\t\t\t\tmnl_attr_put_u16\n-\t\t\t\t\t(nlh,\n-\t\t\t\t\t TCA_FLOWER_KEY_TCP_FLAGS_MASK,\n-\t\t\t\t\t rte_cpu_to_be_16\n-\t\t\t\t\t\t(mask.tcp->hdr.tcp_flags));\n-\t\t\t}\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ITEM_TYPE_VXLAN:\n-\t\t\tassert(decap.vxlan);\n-\t\t\ttunnel_outer = 0;\n-\t\t\titem_flags |= MLX5_FLOW_LAYER_VXLAN;\n-\t\t\tspec.vxlan = items->spec;\n-\t\t\tmnl_attr_put_u32(nlh,\n-\t\t\t\t\t TCA_FLOWER_KEY_ENC_KEY_ID,\n-\t\t\t\t\t vxlan_vni_as_be32(spec.vxlan->vni));\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ITEM,\n-\t\t\t\t\t\t  NULL, \"item not supported\");\n-\t\t}\n-\t}\n-\t/*\n-\t * Set the ether_type flower key and tc rule protocol:\n-\t * - if there is nor VLAN neither VXLAN the key is taken from\n-\t *   eth item directly or deduced from L3 items.\n-\t * - if there is vlan item then key is fixed to 802.1q.\n-\t * - if there is vxlan item then key is set to inner tunnel type.\n-\t * - simultaneous vlan and vxlan items are prohibited.\n-\t */\n-\tif (outer_etype != RTE_BE16(ETH_P_ALL)) {\n-\t\ttcm->tcm_info = TC_H_MAKE((attr->priority + 1) << 16,\n-\t\t\t\t\t   outer_etype);\n-\t\tif (item_flags & MLX5_FLOW_LAYER_TUNNEL) {\n-\t\t\tif (inner_etype != RTE_BE16(ETH_P_ALL))\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t\t TCA_FLOWER_KEY_ETH_TYPE,\n-\t\t\t\t\t\t inner_etype);\n-\t\t} else {\n-\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t TCA_FLOWER_KEY_ETH_TYPE,\n-\t\t\t\t\t outer_etype);\n-\t\t\tif (outer_etype == RTE_BE16(ETH_P_8021Q) &&\n-\t\t\t    vlan_etype != RTE_BE16(ETH_P_ALL))\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t\t TCA_FLOWER_KEY_VLAN_ETH_TYPE,\n-\t\t\t\t\t\t vlan_etype);\n-\t\t}\n-\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t}\n-\tna_flower_act = mnl_attr_nest_start(nlh, TCA_FLOWER_ACT);\n-\tna_act_index_cur = 1;\n-\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n-\t\tstruct nlattr *na_act_index;\n-\t\tstruct nlattr *na_act;\n-\t\tunsigned int vlan_act;\n-\t\tunsigned int i;\n-\n-\t\tswitch (actions->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_PORT_ID:\n-\t\t\tconf.port_id = actions->conf;\n-\t\t\tif (conf.port_id->original)\n-\t\t\t\ti = 0;\n-\t\t\telse\n-\t\t\t\tfor (i = 0; ptoi[i].ifindex; ++i)\n-\t\t\t\t\tif (ptoi[i].port_id == conf.port_id->id)\n-\t\t\t\t\t\tbreak;\n-\t\t\tassert(ptoi[i].ifindex);\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"mirred\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tif (encap.hdr) {\n-\t\t\t\tassert(dev_flow->tcf.tunnel);\n-\t\t\t\tdev_flow->tcf.tunnel->ifindex_ptr =\n-\t\t\t\t\t&((struct tc_mirred *)\n-\t\t\t\t\tmnl_attr_get_payload\n-\t\t\t\t\t(mnl_nlmsg_get_payload_tail\n-\t\t\t\t\t\t(nlh)))->ifindex;\n-\t\t\t} else if (decap.hdr) {\n-\t\t\t\tassert(dev_flow->tcf.tunnel);\n-\t\t\t\tdev_flow->tcf.tunnel->ifindex_ptr =\n-\t\t\t\t\t(unsigned int *)&tcm->tcm_ifindex;\n-\t\t\t}\n-\t\t\tmnl_attr_put(nlh, TCA_MIRRED_PARMS,\n-\t\t\t\t     sizeof(struct tc_mirred),\n-\t\t\t\t     &(struct tc_mirred){\n-\t\t\t\t\t.action = TC_ACT_STOLEN,\n-\t\t\t\t\t.eaction = TCA_EGRESS_REDIR,\n-\t\t\t\t\t.ifindex = ptoi[i].ifindex,\n-\t\t\t\t     });\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_JUMP:\n-\t\t\tconf.jump = actions->conf;\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"gact\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tmnl_attr_put(nlh, TCA_GACT_PARMS,\n-\t\t\t\t     sizeof(struct tc_gact),\n-\t\t\t\t     &(struct tc_gact){\n-\t\t\t\t\t.action = TC_ACT_GOTO_CHAIN |\n-\t\t\t\t\t\t  conf.jump->group,\n-\t\t\t\t     });\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_DROP:\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"gact\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tmnl_attr_put(nlh, TCA_GACT_PARMS,\n-\t\t\t\t     sizeof(struct tc_gact),\n-\t\t\t\t     &(struct tc_gact){\n-\t\t\t\t\t.action = TC_ACT_SHOT,\n-\t\t\t\t     });\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n-\t\t\t/*\n-\t\t\t * Driver adds the count action implicitly for\n-\t\t\t * each rule it creates.\n-\t\t\t */\n-\t\t\tret = flow_tcf_translate_action_count(dev,\n-\t\t\t\t\t\t\t      dev_flow, error);\n-\t\t\tif (ret < 0)\n-\t\t\t\treturn ret;\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:\n-\t\t\tconf.of_push_vlan = NULL;\n-\t\t\tvlan_act = TCA_VLAN_ACT_POP;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:\n-\t\t\tconf.of_push_vlan = actions->conf;\n-\t\t\tvlan_act = TCA_VLAN_ACT_PUSH;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:\n-\t\t\tconf.of_set_vlan_vid = actions->conf;\n-\t\t\tif (na_vlan_id)\n-\t\t\t\tgoto override_na_vlan_id;\n-\t\t\tvlan_act = TCA_VLAN_ACT_MODIFY;\n-\t\t\tgoto action_of_vlan;\n-\t\tcase RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:\n-\t\t\tconf.of_set_vlan_pcp = actions->conf;\n-\t\t\tif (na_vlan_priority)\n-\t\t\t\tgoto override_na_vlan_priority;\n-\t\t\tvlan_act = TCA_VLAN_ACT_MODIFY;\n-\t\t\tgoto action_of_vlan;\n-action_of_vlan:\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"vlan\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tmnl_attr_put(nlh, TCA_VLAN_PARMS,\n-\t\t\t\t     sizeof(struct tc_vlan),\n-\t\t\t\t     &(struct tc_vlan){\n-\t\t\t\t\t.action = TC_ACT_PIPE,\n-\t\t\t\t\t.v_action = vlan_act,\n-\t\t\t\t     });\n-\t\t\tif (vlan_act == TCA_VLAN_ACT_POP) {\n-\t\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (vlan_act == TCA_VLAN_ACT_PUSH)\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t\t TCA_VLAN_PUSH_VLAN_PROTOCOL,\n-\t\t\t\t\t\t conf.of_push_vlan->ethertype);\n-\t\t\tna_vlan_id = mnl_nlmsg_get_payload_tail(nlh);\n-\t\t\tmnl_attr_put_u16(nlh, TCA_VLAN_PAD, 0);\n-\t\t\tna_vlan_priority = mnl_nlmsg_get_payload_tail(nlh);\n-\t\t\tmnl_attr_put_u8(nlh, TCA_VLAN_PAD, 0);\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tif (actions->type ==\n-\t\t\t    RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) {\n-override_na_vlan_id:\n-\t\t\t\tna_vlan_id->nla_type = TCA_VLAN_PUSH_VLAN_ID;\n-\t\t\t\t*(uint16_t *)mnl_attr_get_payload(na_vlan_id) =\n-\t\t\t\t\trte_be_to_cpu_16\n-\t\t\t\t\t(conf.of_set_vlan_vid->vlan_vid);\n-\t\t\t} else if (actions->type ==\n-\t\t\t\t   RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) {\n-override_na_vlan_priority:\n-\t\t\t\tna_vlan_priority->nla_type =\n-\t\t\t\t\tTCA_VLAN_PUSH_VLAN_PRIORITY;\n-\t\t\t\t*(uint8_t *)mnl_attr_get_payload\n-\t\t\t\t\t(na_vlan_priority) =\n-\t\t\t\t\tconf.of_set_vlan_pcp->vlan_pcp;\n-\t\t\t}\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:\n-\t\t\tassert(decap.vxlan);\n-\t\t\tassert(dev_flow->tcf.tunnel);\n-\t\t\tdev_flow->tcf.tunnel->ifindex_ptr =\n-\t\t\t\t(unsigned int *)&tcm->tcm_ifindex;\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"tunnel_key\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tmnl_attr_put(nlh, TCA_TUNNEL_KEY_PARMS,\n-\t\t\t\tsizeof(struct tc_tunnel_key),\n-\t\t\t\t&(struct tc_tunnel_key){\n-\t\t\t\t\t.action = TC_ACT_PIPE,\n-\t\t\t\t\t.t_action = TCA_TUNNEL_KEY_ACT_RELEASE,\n-\t\t\t\t\t});\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:\n-\t\t\tassert(encap.vxlan);\n-\t\t\tflow_tcf_vxlan_encap_parse(actions, encap.vxlan);\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tassert(na_act_index);\n-\t\t\tmnl_attr_put_strz(nlh, TCA_ACT_KIND, \"tunnel_key\");\n-\t\t\tna_act = mnl_attr_nest_start(nlh, TCA_ACT_OPTIONS);\n-\t\t\tassert(na_act);\n-\t\t\tmnl_attr_put(nlh, TCA_TUNNEL_KEY_PARMS,\n-\t\t\t\tsizeof(struct tc_tunnel_key),\n-\t\t\t\t&(struct tc_tunnel_key){\n-\t\t\t\t\t.action = TC_ACT_PIPE,\n-\t\t\t\t\t.t_action = TCA_TUNNEL_KEY_ACT_SET,\n-\t\t\t\t\t});\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_UDP_DST)\n-\t\t\t\tmnl_attr_put_u16(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_DST_PORT,\n-\t\t\t\t\t encap.vxlan->udp.dst);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV4_SRC)\n-\t\t\t\tmnl_attr_put_u32(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_IPV4_SRC,\n-\t\t\t\t\t encap.vxlan->ipv4.src);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV4_DST)\n-\t\t\t\tmnl_attr_put_u32(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_IPV4_DST,\n-\t\t\t\t\t encap.vxlan->ipv4.dst);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV6_SRC)\n-\t\t\t\tmnl_attr_put(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_IPV6_SRC,\n-\t\t\t\t\t sizeof(encap.vxlan->ipv6.src),\n-\t\t\t\t\t &encap.vxlan->ipv6.src);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IPV6_DST)\n-\t\t\t\tmnl_attr_put(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_IPV6_DST,\n-\t\t\t\t\t sizeof(encap.vxlan->ipv6.dst),\n-\t\t\t\t\t &encap.vxlan->ipv6.dst);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IP_TTL)\n-\t\t\t\tmnl_attr_put_u8(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_TTL,\n-\t\t\t\t\t encap.vxlan->ip_ttl_hop);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_IP_TOS)\n-\t\t\t\tmnl_attr_put_u8(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_TOS,\n-\t\t\t\t\t encap.vxlan->ip_tos);\n-\t\t\tif (encap.vxlan->mask & FLOW_TCF_ENCAP_VXLAN_VNI)\n-\t\t\t\tmnl_attr_put_u32(nlh,\n-\t\t\t\t\t TCA_TUNNEL_KEY_ENC_KEY_ID,\n-\t\t\t\t\t vxlan_vni_as_be32\n-\t\t\t\t\t\t(encap.vxlan->vxlan.vni));\n-\t\t\tmnl_attr_put_u8(nlh, TCA_TUNNEL_KEY_NO_CSUM, 0);\n-\t\t\tmnl_attr_nest_end(nlh, na_act);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TP_DST:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_TTL:\n-\t\tcase RTE_FLOW_ACTION_TYPE_DEC_TTL:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:\n-\t\tcase RTE_FLOW_ACTION_TYPE_SET_MAC_DST:\n-\t\t\tna_act_index =\n-\t\t\t\tmnl_attr_nest_start(nlh, na_act_index_cur++);\n-\t\t\tflow_tcf_create_pedit_mnl_msg(nlh,\n-\t\t\t\t\t\t      &actions, item_flags);\n-\t\t\tmnl_attr_nest_end(nlh, na_act_index);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"action not supported\");\n-\t\t}\n-\t}\n-\tassert(na_flower);\n-\tassert(na_flower_act);\n-\tmnl_attr_nest_end(nlh, na_flower_act);\n-\tdev_flow->tcf.ptc_flags = mnl_attr_get_payload\n-\t\t\t\t\t(mnl_nlmsg_get_payload_tail(nlh));\n-\tmnl_attr_put_u32(nlh, TCA_FLOWER_FLAGS,\tdecap.vxlan ?\n-\t\t\t\t\t\t0 : TCA_CLS_FLAGS_SKIP_SW);\n-\tmnl_attr_nest_end(nlh, na_flower);\n-\tif (dev_flow->tcf.tunnel && dev_flow->tcf.tunnel->ifindex_ptr)\n-\t\tdev_flow->tcf.tunnel->ifindex_org =\n-\t\t\t*dev_flow->tcf.tunnel->ifindex_ptr;\n-\tassert(dev_flow->tcf.nlsize >= nlh->nlmsg_len);\n-\treturn 0;\n-}\n-\n-/**\n- * Send Netlink message with acknowledgment.\n- *\n- * @param tcf\n- *   Flow context to use.\n- * @param nlh\n- *   Message to send. This function always raises the NLM_F_ACK flag before\n- *   sending.\n- * @param[in] cb\n- *   Callback handler for received message.\n- * @param[in] arg\n- *   Context pointer for callback handler.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_nl_ack(struct mlx5_flow_tcf_context *tcf,\n-\t\tstruct nlmsghdr *nlh,\n-\t\tmnl_cb_t cb, void *arg)\n-{\n-\tunsigned int portid = mnl_socket_get_portid(tcf->nl);\n-\tuint32_t seq = tcf->seq++;\n-\tint ret, err = 0;\n-\n-\tassert(tcf->nl);\n-\tassert(tcf->buf);\n-\tif (!seq) {\n-\t\t/* seq 0 is reserved for kernel event-driven notifications. */\n-\t\tseq = tcf->seq++;\n-\t}\n-\tnlh->nlmsg_seq = seq;\n-\tnlh->nlmsg_flags |= NLM_F_ACK;\n-\tret = mnl_socket_sendto(tcf->nl, nlh, nlh->nlmsg_len);\n-\tif (ret <= 0) {\n-\t\t/* Message send error occurred. */\n-\t\trte_errno = errno;\n-\t\treturn -rte_errno;\n-\t}\n-\tnlh = (struct nlmsghdr *)(tcf->buf);\n-\t/*\n-\t * The following loop postpones non-fatal errors until multipart\n-\t * messages are complete.\n-\t */\n-\twhile (true) {\n-\t\tret = mnl_socket_recvfrom(tcf->nl, tcf->buf, tcf->buf_size);\n-\t\tif (ret < 0) {\n-\t\t\terr = errno;\n-\t\t\t/*\n-\t\t\t * In case of overflow Will receive till\n-\t\t\t * end of multipart message. We may lost part\n-\t\t\t * of reply messages but mark and return an error.\n-\t\t\t */\n-\t\t\tif (err != ENOSPC ||\n-\t\t\t    !(nlh->nlmsg_flags & NLM_F_MULTI) ||\n-\t\t\t    nlh->nlmsg_type == NLMSG_DONE)\n-\t\t\t\tbreak;\n-\t\t} else {\n-\t\t\tret = mnl_cb_run(nlh, ret, seq, portid, cb, arg);\n-\t\t\tif (!ret) {\n-\t\t\t\t/*\n-\t\t\t\t * libmnl returns 0 if DONE or\n-\t\t\t\t * success ACK message found.\n-\t\t\t\t */\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (ret < 0) {\n-\t\t\t\t/*\n-\t\t\t\t * ACK message with error found\n-\t\t\t\t * or some error occurred.\n-\t\t\t\t */\n-\t\t\t\terr = errno;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\t/* We should continue receiving. */\n-\t\t}\n-\t}\n-\tif (!err)\n-\t\treturn 0;\n-\trte_errno = err;\n-\treturn -err;\n-}\n-\n-#define MNL_BUF_EXTRA_SPACE 16\n-#define MNL_REQUEST_SIZE_MIN 256\n-#define MNL_REQUEST_SIZE_MAX 2048\n-#define MNL_REQUEST_SIZE RTE_MIN(RTE_MAX(sysconf(_SC_PAGESIZE), \\\n-\t\t\t\t MNL_REQUEST_SIZE_MIN), MNL_REQUEST_SIZE_MAX)\n-\n-/* Data structures used by flow_tcf_xxx_cb() routines. */\n-struct tcf_nlcb_buf {\n-\tLIST_ENTRY(tcf_nlcb_buf) next;\n-\tuint32_t size;\n-\talignas(struct nlmsghdr)\n-\tuint8_t msg[]; /**< Netlink message data. */\n-};\n-\n-struct tcf_nlcb_context {\n-\tunsigned int ifindex; /**< Base interface index. */\n-\tuint32_t bufsize;\n-\tLIST_HEAD(, tcf_nlcb_buf) nlbuf;\n-};\n-\n-/**\n- * Allocate space for netlink command in buffer list\n- *\n- * @param[in, out] ctx\n- *   Pointer to callback context with command buffers list.\n- * @param[in] size\n- *   Required size of data buffer to be allocated.\n- *\n- * @return\n- *   Pointer to allocated memory, aligned as message header.\n- *   NULL if some error occurred.\n- */\n-static struct nlmsghdr *\n-flow_tcf_alloc_nlcmd(struct tcf_nlcb_context *ctx, uint32_t size)\n-{\n-\tstruct tcf_nlcb_buf *buf;\n-\tstruct nlmsghdr *nlh;\n-\n-\tsize = NLMSG_ALIGN(size);\n-\tbuf = LIST_FIRST(&ctx->nlbuf);\n-\tif (buf && (buf->size + size) <= ctx->bufsize) {\n-\t\tnlh = (struct nlmsghdr *)&buf->msg[buf->size];\n-\t\tbuf->size += size;\n-\t\treturn nlh;\n-\t}\n-\tif (size > ctx->bufsize) {\n-\t\tDRV_LOG(WARNING, \"netlink: too long command buffer requested\");\n-\t\treturn NULL;\n-\t}\n-\tbuf = rte_malloc(__func__,\n-\t\t\tctx->bufsize + sizeof(struct tcf_nlcb_buf),\n-\t\t\talignof(struct tcf_nlcb_buf));\n-\tif (!buf) {\n-\t\tDRV_LOG(WARNING, \"netlink: no memory for command buffer\");\n-\t\treturn NULL;\n-\t}\n-\tLIST_INSERT_HEAD(&ctx->nlbuf, buf, next);\n-\tbuf->size = size;\n-\tnlh = (struct nlmsghdr *)&buf->msg[0];\n-\treturn nlh;\n-}\n-\n-/**\n- * Send the buffers with prepared netlink commands. Scans the list and\n- * sends all found buffers. Buffers are sent and freed anyway in order\n- * to prevent memory leakage if some every message in received packet.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in, out] ctx\n- *   Pointer to callback context with command buffers list.\n- *\n- * @return\n- *   Zero value on success, negative errno value otherwise\n- *   and rte_errno is set.\n- */\n-static int\n-flow_tcf_send_nlcmd(struct mlx5_flow_tcf_context *tcf,\n-\t\t    struct tcf_nlcb_context *ctx)\n-{\n-\tstruct tcf_nlcb_buf *bc = LIST_FIRST(&ctx->nlbuf);\n-\tint ret = 0;\n-\n-\twhile (bc) {\n-\t\tstruct tcf_nlcb_buf *bn = LIST_NEXT(bc, next);\n-\t\tstruct nlmsghdr *nlh;\n-\t\tuint32_t msg = 0;\n-\t\tint rc;\n-\n-\t\twhile (msg < bc->size) {\n-\t\t\t/*\n-\t\t\t * Send Netlink commands from buffer in one by one\n-\t\t\t * fashion. If we send multiple rule deletion commands\n-\t\t\t * in one Netlink message and some error occurs it may\n-\t\t\t * cause multiple ACK error messages and break sequence\n-\t\t\t * numbers of Netlink communication, because we expect\n-\t\t\t * the only one ACK reply.\n-\t\t\t */\n-\t\t\tassert((bc->size - msg) >= sizeof(struct nlmsghdr));\n-\t\t\tnlh = (struct nlmsghdr *)&bc->msg[msg];\n-\t\t\tassert((bc->size - msg) >= nlh->nlmsg_len);\n-\t\t\tmsg += nlh->nlmsg_len;\n-\t\t\trc = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);\n-\t\t\tif (rc) {\n-\t\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\t\"netlink: cleanup error %d\", rc);\n-\t\t\t\tif (!ret)\n-\t\t\t\t\tret = rc;\n-\t\t\t}\n-\t\t}\n-\t\trte_free(bc);\n-\t\tbc = bn;\n-\t}\n-\tLIST_INIT(&ctx->nlbuf);\n-\treturn ret;\n-}\n-\n-/**\n- * Collect local IP address rules with scope link attribute  on specified\n- * network device. This is callback routine called by libmnl mnl_cb_run()\n- * in loop for every message in received packet.\n- *\n- * @param[in] nlh\n- *   Pointer to reply header.\n- * @param[in, out] arg\n- *   Opaque data pointer for this callback.\n- *\n- * @return\n- *   A positive, nonzero value on success, negative errno value otherwise\n- *   and rte_errno is set.\n- */\n-static int\n-flow_tcf_collect_local_cb(const struct nlmsghdr *nlh, void *arg)\n-{\n-\tstruct tcf_nlcb_context *ctx = arg;\n-\tstruct nlmsghdr *cmd;\n-\tstruct ifaddrmsg *ifa;\n-\tstruct nlattr *na;\n-\tstruct nlattr *na_local = NULL;\n-\tstruct nlattr *na_peer = NULL;\n-\tunsigned char family;\n-\tuint32_t size;\n-\n-\tif (nlh->nlmsg_type != RTM_NEWADDR) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n-\t}\n-\tifa = mnl_nlmsg_get_payload(nlh);\n-\tfamily = ifa->ifa_family;\n-\tif (ifa->ifa_index != ctx->ifindex ||\n-\t    ifa->ifa_scope != RT_SCOPE_LINK ||\n-\t    !(ifa->ifa_flags & IFA_F_PERMANENT) ||\n-\t    (family != AF_INET && family != AF_INET6))\n-\t\treturn 1;\n-\tmnl_attr_for_each(na, nlh, sizeof(*ifa)) {\n-\t\tswitch (mnl_attr_get_type(na)) {\n-\t\tcase IFA_LOCAL:\n-\t\t\tna_local = na;\n-\t\t\tbreak;\n-\t\tcase IFA_ADDRESS:\n-\t\t\tna_peer = na;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (na_local && na_peer)\n-\t\t\tbreak;\n-\t}\n-\tif (!na_local || !na_peer)\n-\t\treturn 1;\n-\t/* Local rule found with scope link, permanent and assigned peer. */\n-\tsize = MNL_ALIGN(sizeof(struct nlmsghdr)) +\n-\t       MNL_ALIGN(sizeof(struct ifaddrmsg)) +\n-\t       (family == AF_INET6 ? 2 * SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN)\n-\t\t\t\t   : 2 * SZ_NLATTR_TYPE_OF(uint32_t));\n-\tcmd = flow_tcf_alloc_nlcmd(ctx, size);\n-\tif (!cmd) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn -rte_errno;\n-\t}\n-\tcmd = mnl_nlmsg_put_header(cmd);\n-\tcmd->nlmsg_type = RTM_DELADDR;\n-\tcmd->nlmsg_flags = NLM_F_REQUEST;\n-\tifa = mnl_nlmsg_put_extra_header(cmd, sizeof(*ifa));\n-\tifa->ifa_flags = IFA_F_PERMANENT;\n-\tifa->ifa_scope = RT_SCOPE_LINK;\n-\tifa->ifa_index = ctx->ifindex;\n-\tif (family == AF_INET) {\n-\t\tifa->ifa_family = AF_INET;\n-\t\tifa->ifa_prefixlen = 32;\n-\t\tmnl_attr_put_u32(cmd, IFA_LOCAL, mnl_attr_get_u32(na_local));\n-\t\tmnl_attr_put_u32(cmd, IFA_ADDRESS, mnl_attr_get_u32(na_peer));\n-\t} else {\n-\t\tifa->ifa_family = AF_INET6;\n-\t\tifa->ifa_prefixlen = 128;\n-\t\tmnl_attr_put(cmd, IFA_LOCAL, IPV6_ADDR_LEN,\n-\t\t\tmnl_attr_get_payload(na_local));\n-\t\tmnl_attr_put(cmd, IFA_ADDRESS, IPV6_ADDR_LEN,\n-\t\t\tmnl_attr_get_payload(na_peer));\n-\t}\n-\tassert(size == cmd->nlmsg_len);\n-\treturn 1;\n-}\n-\n-/**\n- * Cleanup the local IP addresses on outer interface.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifindex\n- *   Network interface index to perform cleanup.\n- */\n-static void\n-flow_tcf_encap_local_cleanup(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t    unsigned int ifindex)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifaddrmsg *ifa;\n-\tstruct tcf_nlcb_context ctx = {\n-\t\t.ifindex = ifindex,\n-\t\t.bufsize = MNL_REQUEST_SIZE,\n-\t\t.nlbuf = LIST_HEAD_INITIALIZER(),\n-\t};\n-\tint ret;\n-\n-\tassert(ifindex);\n-\t/*\n-\t * Seek and destroy leftovers of local IP addresses with\n-\t * matching properties \"scope link\".\n-\t */\n-\tnlh = mnl_nlmsg_put_header(tcf->buf);\n-\tnlh->nlmsg_type = RTM_GETADDR;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;\n-\tifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa));\n-\tifa->ifa_family = AF_UNSPEC;\n-\tifa->ifa_index = ifindex;\n-\tifa->ifa_scope = RT_SCOPE_LINK;\n-\tret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_local_cb, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: query device list error %d\", ret);\n-\tret = flow_tcf_send_nlcmd(tcf, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: device delete error %d\", ret);\n-}\n-\n-/**\n- * Collect neigh permanent rules on specified network device.\n- * This is callback routine called by libmnl mnl_cb_run() in loop for\n- * every message in received packet.\n- *\n- * @param[in] nlh\n- *   Pointer to reply header.\n- * @param[in, out] arg\n- *   Opaque data pointer for this callback.\n- *\n- * @return\n- *   A positive, nonzero value on success, negative errno value otherwise\n- *   and rte_errno is set.\n- */\n-static int\n-flow_tcf_collect_neigh_cb(const struct nlmsghdr *nlh, void *arg)\n-{\n-\tstruct tcf_nlcb_context *ctx = arg;\n-\tstruct nlmsghdr *cmd;\n-\tstruct ndmsg *ndm;\n-\tstruct nlattr *na;\n-\tstruct nlattr *na_ip = NULL;\n-\tstruct nlattr *na_mac = NULL;\n-\tunsigned char family;\n-\tuint32_t size;\n-\n-\tif (nlh->nlmsg_type != RTM_NEWNEIGH) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n-\t}\n-\tndm = mnl_nlmsg_get_payload(nlh);\n-\tfamily = ndm->ndm_family;\n-\tif (ndm->ndm_ifindex != (int)ctx->ifindex ||\n-\t   !(ndm->ndm_state & NUD_PERMANENT) ||\n-\t   (family != AF_INET && family != AF_INET6))\n-\t\treturn 1;\n-\tmnl_attr_for_each(na, nlh, sizeof(*ndm)) {\n-\t\tswitch (mnl_attr_get_type(na)) {\n-\t\tcase NDA_DST:\n-\t\t\tna_ip = na;\n-\t\t\tbreak;\n-\t\tcase NDA_LLADDR:\n-\t\t\tna_mac = na;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (na_mac && na_ip)\n-\t\t\tbreak;\n-\t}\n-\tif (!na_mac || !na_ip)\n-\t\treturn 1;\n-\t/* Neigh rule with permanent attribute found. */\n-\tsize = MNL_ALIGN(sizeof(struct nlmsghdr)) +\n-\t       MNL_ALIGN(sizeof(struct ndmsg)) +\n-\t       SZ_NLATTR_DATA_OF(RTE_ETHER_ADDR_LEN) +\n-\t       (family == AF_INET6 ? SZ_NLATTR_DATA_OF(IPV6_ADDR_LEN)\n-\t\t\t\t   : SZ_NLATTR_TYPE_OF(uint32_t));\n-\tcmd = flow_tcf_alloc_nlcmd(ctx, size);\n-\tif (!cmd) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn -rte_errno;\n-\t}\n-\tcmd = mnl_nlmsg_put_header(cmd);\n-\tcmd->nlmsg_type = RTM_DELNEIGH;\n-\tcmd->nlmsg_flags = NLM_F_REQUEST;\n-\tndm = mnl_nlmsg_put_extra_header(cmd, sizeof(*ndm));\n-\tndm->ndm_ifindex = ctx->ifindex;\n-\tndm->ndm_state = NUD_PERMANENT;\n-\tndm->ndm_flags = 0;\n-\tndm->ndm_type = 0;\n-\tif (family == AF_INET) {\n-\t\tndm->ndm_family = AF_INET;\n-\t\tmnl_attr_put_u32(cmd, NDA_DST, mnl_attr_get_u32(na_ip));\n-\t} else {\n-\t\tndm->ndm_family = AF_INET6;\n-\t\tmnl_attr_put(cmd, NDA_DST, IPV6_ADDR_LEN,\n-\t\t\t     mnl_attr_get_payload(na_ip));\n-\t}\n-\tmnl_attr_put(cmd, NDA_LLADDR, RTE_ETHER_ADDR_LEN,\n-\t\t     mnl_attr_get_payload(na_mac));\n-\tassert(size == cmd->nlmsg_len);\n-\treturn 1;\n-}\n-\n-/**\n- * Cleanup the neigh rules on outer interface.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifindex\n- *   Network interface index to perform cleanup.\n- */\n-static void\n-flow_tcf_encap_neigh_cleanup(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t    unsigned int ifindex)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ndmsg *ndm;\n-\tstruct tcf_nlcb_context ctx = {\n-\t\t.ifindex = ifindex,\n-\t\t.bufsize = MNL_REQUEST_SIZE,\n-\t\t.nlbuf = LIST_HEAD_INITIALIZER(),\n-\t};\n-\tint ret;\n-\n-\tassert(ifindex);\n-\t/* Seek and destroy leftovers of neigh rules. */\n-\tnlh = mnl_nlmsg_put_header(tcf->buf);\n-\tnlh->nlmsg_type = RTM_GETNEIGH;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;\n-\tndm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ndm));\n-\tndm->ndm_family = AF_UNSPEC;\n-\tndm->ndm_ifindex = ifindex;\n-\tndm->ndm_state = NUD_PERMANENT;\n-\tret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_neigh_cb, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: query device list error %d\", ret);\n-\tret = flow_tcf_send_nlcmd(tcf, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: device delete error %d\", ret);\n-}\n-\n-/**\n- * Collect indices of VXLAN encap/decap interfaces associated with device.\n- * This is callback routine called by libmnl mnl_cb_run() in loop for\n- * every message in received packet.\n- *\n- * @param[in] nlh\n- *   Pointer to reply header.\n- * @param[in, out] arg\n- *   Opaque data pointer for this callback.\n- *\n- * @return\n- *   A positive, nonzero value on success, negative errno value otherwise\n- *   and rte_errno is set.\n- */\n-static int\n-flow_tcf_collect_vxlan_cb(const struct nlmsghdr *nlh, void *arg)\n-{\n-\tstruct tcf_nlcb_context *ctx = arg;\n-\tstruct nlmsghdr *cmd;\n-\tstruct ifinfomsg *ifm;\n-\tstruct nlattr *na;\n-\tstruct nlattr *na_info = NULL;\n-\tstruct nlattr *na_vxlan = NULL;\n-\tbool found = false;\n-\tunsigned int vxindex;\n-\tuint32_t size;\n-\n-\tif (nlh->nlmsg_type != RTM_NEWLINK) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n-\t}\n-\tifm = mnl_nlmsg_get_payload(nlh);\n-\tif (!ifm->ifi_index) {\n-\t\trte_errno = EINVAL;\n-\t\treturn -rte_errno;\n-\t}\n-\tmnl_attr_for_each(na, nlh, sizeof(*ifm))\n-\t\tif (mnl_attr_get_type(na) == IFLA_LINKINFO) {\n-\t\t\tna_info = na;\n-\t\t\tbreak;\n-\t\t}\n-\tif (!na_info)\n-\t\treturn 1;\n-\tmnl_attr_for_each_nested(na, na_info) {\n-\t\tswitch (mnl_attr_get_type(na)) {\n-\t\tcase IFLA_INFO_KIND:\n-\t\t\tif (!strncmp(\"vxlan\", mnl_attr_get_str(na),\n-\t\t\t\t     mnl_attr_get_len(na)))\n-\t\t\t\tfound = true;\n-\t\t\tbreak;\n-\t\tcase IFLA_INFO_DATA:\n-\t\t\tna_vxlan = na;\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (found && na_vxlan)\n-\t\t\tbreak;\n-\t}\n-\tif (!found || !na_vxlan)\n-\t\treturn 1;\n-\tfound = false;\n-\tmnl_attr_for_each_nested(na, na_vxlan) {\n-\t\tif (mnl_attr_get_type(na) == IFLA_VXLAN_LINK &&\n-\t\t    mnl_attr_get_u32(na) == ctx->ifindex) {\n-\t\t\tfound = true;\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\tif (!found)\n-\t\treturn 1;\n-\t/* Attached VXLAN device found, store the command to delete. */\n-\tvxindex = ifm->ifi_index;\n-\tsize = MNL_ALIGN(sizeof(struct nlmsghdr)) +\n-\t       MNL_ALIGN(sizeof(struct ifinfomsg));\n-\tcmd = flow_tcf_alloc_nlcmd(ctx, size);\n-\tif (!cmd) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn -rte_errno;\n-\t}\n-\tcmd = mnl_nlmsg_put_header(cmd);\n-\tcmd->nlmsg_type = RTM_DELLINK;\n-\tcmd->nlmsg_flags = NLM_F_REQUEST;\n-\tifm = mnl_nlmsg_put_extra_header(cmd, sizeof(*ifm));\n-\tifm->ifi_family = AF_UNSPEC;\n-\tifm->ifi_index = vxindex;\n-\tassert(size == cmd->nlmsg_len);\n-\treturn 1;\n-}\n-\n-/**\n- * Cleanup the outer interface. Removes all found vxlan devices\n- * attached to specified index, flushes the neigh and local IP\n- * database.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifindex\n- *   Network inferface index to perform cleanup.\n- */\n-static void\n-flow_tcf_encap_iface_cleanup(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t    unsigned int ifindex)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifinfomsg *ifm;\n-\tstruct tcf_nlcb_context ctx = {\n-\t\t.ifindex = ifindex,\n-\t\t.bufsize = MNL_REQUEST_SIZE,\n-\t\t.nlbuf = LIST_HEAD_INITIALIZER(),\n-\t};\n-\tint ret;\n-\n-\tassert(ifindex);\n-\t/*\n-\t * Seek and destroy leftover VXLAN encap/decap interfaces with\n-\t * matching properties.\n-\t */\n-\tnlh = mnl_nlmsg_put_header(tcf->buf);\n-\tnlh->nlmsg_type = RTM_GETLINK;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;\n-\tifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));\n-\tifm->ifi_family = AF_UNSPEC;\n-\tret = flow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_vxlan_cb, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: query device list error %d\", ret);\n-\tret = flow_tcf_send_nlcmd(tcf, &ctx);\n-\tif (ret)\n-\t\tDRV_LOG(WARNING, \"netlink: device delete error %d\", ret);\n-}\n-\n-/**\n- * Emit Netlink message to add/remove local address to the outer device.\n- * The address being added is visible within the link only (scope link).\n- *\n- * Note that an implicit route is maintained by the kernel due to the\n- * presence of a peer address (IFA_ADDRESS).\n- *\n- * These rules are used for encapsulation only and allow to assign\n- * the outer tunnel source IP address.\n- *\n- * @param[in] tcf\n- *   Libmnl socket context object.\n- * @param[in] encap\n- *   Encapsulation properties (source address and its peer).\n- * @param[in] ifindex\n- *   Network interface to apply rule.\n- * @param[in] enable\n- *   Toggle between add and remove.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_rule_local(struct mlx5_flow_tcf_context *tcf,\n-\t\t    const struct flow_tcf_vxlan_encap *encap,\n-\t\t    unsigned int ifindex,\n-\t\t    bool enable,\n-\t\t    struct rte_flow_error *error)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifaddrmsg *ifa;\n-\talignas(struct nlmsghdr)\n-\tuint8_t buf[mnl_nlmsg_size(sizeof(*ifa) + 128)];\n-\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = enable ? RTM_NEWADDR : RTM_DELADDR;\n-\tnlh->nlmsg_flags =\n-\t\tNLM_F_REQUEST | (enable ? NLM_F_CREATE | NLM_F_REPLACE : 0);\n-\tnlh->nlmsg_seq = 0;\n-\tifa = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifa));\n-\tifa->ifa_flags = IFA_F_PERMANENT;\n-\tifa->ifa_scope = RT_SCOPE_LINK;\n-\tifa->ifa_index = ifindex;\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_SRC) {\n-\t\tifa->ifa_family = AF_INET;\n-\t\tifa->ifa_prefixlen = 32;\n-\t\tmnl_attr_put_u32(nlh, IFA_LOCAL, encap->ipv4.src);\n-\t\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_DST)\n-\t\t\tmnl_attr_put_u32(nlh, IFA_ADDRESS,\n-\t\t\t\t\t      encap->ipv4.dst);\n-\t} else {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_SRC);\n-\t\tifa->ifa_family = AF_INET6;\n-\t\tifa->ifa_prefixlen = 128;\n-\t\tmnl_attr_put(nlh, IFA_LOCAL,\n-\t\t\t\t  sizeof(encap->ipv6.src),\n-\t\t\t\t  &encap->ipv6.src);\n-\t\tif (encap->mask & FLOW_TCF_ENCAP_IPV6_DST)\n-\t\t\tmnl_attr_put(nlh, IFA_ADDRESS,\n-\t\t\t\t\t  sizeof(encap->ipv6.dst),\n-\t\t\t\t\t  &encap->ipv6.dst);\n-\t}\n-\tif (!flow_tcf_nl_ack(tcf, nlh, NULL, NULL))\n-\t\treturn 0;\n-\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t  \"netlink: cannot complete IFA request\"\n-\t\t\t\t  \" (ip addr add)\");\n-}\n-\n-/**\n- * Emit Netlink message to add/remove neighbor.\n- *\n- * @param[in] tcf\n- *   Libmnl socket context object.\n- * @param[in] encap\n- *   Encapsulation properties (destination address).\n- * @param[in] ifindex\n- *   Network interface.\n- * @param[in] enable\n- *   Toggle between add and remove.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_rule_neigh(struct mlx5_flow_tcf_context *tcf,\n-\t\t     const struct flow_tcf_vxlan_encap *encap,\n-\t\t     unsigned int ifindex,\n-\t\t     bool enable,\n-\t\t     struct rte_flow_error *error)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ndmsg *ndm;\n-\talignas(struct nlmsghdr)\n-\tuint8_t buf[mnl_nlmsg_size(sizeof(*ndm) + 128)];\n-\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = enable ? RTM_NEWNEIGH : RTM_DELNEIGH;\n-\tnlh->nlmsg_flags =\n-\t\tNLM_F_REQUEST | (enable ? NLM_F_CREATE | NLM_F_REPLACE : 0);\n-\tnlh->nlmsg_seq = 0;\n-\tndm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ndm));\n-\tndm->ndm_ifindex = ifindex;\n-\tndm->ndm_state = NUD_PERMANENT;\n-\tndm->ndm_flags = 0;\n-\tndm->ndm_type = 0;\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_DST) {\n-\t\tndm->ndm_family = AF_INET;\n-\t\tmnl_attr_put_u32(nlh, NDA_DST, encap->ipv4.dst);\n-\t} else {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_DST);\n-\t\tndm->ndm_family = AF_INET6;\n-\t\tmnl_attr_put(nlh, NDA_DST, sizeof(encap->ipv6.dst),\n-\t\t\t\t\t\t &encap->ipv6.dst);\n-\t}\n-\tif (encap->mask & FLOW_TCF_ENCAP_ETH_SRC && enable)\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"outer ethernet source address cannot be \"\n-\t\t\t\"forced for VXLAN encapsulation\");\n-\tif (encap->mask & FLOW_TCF_ENCAP_ETH_DST)\n-\t\tmnl_attr_put(nlh, NDA_LLADDR, sizeof(encap->eth.dst),\n-\t\t\t\t\t\t    &encap->eth.dst);\n-\tif (!flow_tcf_nl_ack(tcf, nlh, NULL, NULL))\n-\t\treturn 0;\n-\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t  \"netlink: cannot complete ND request\"\n-\t\t\t\t  \" (ip neigh)\");\n-}\n-\n-/**\n- * Manage the local IP addresses and their peers IP addresses on the\n- * outer interface for encapsulation purposes. The kernel searches the\n- * appropriate device for tunnel egress traffic using the outer source\n- * IP, this IP should be assigned to the outer network device, otherwise\n- * kernel rejects the rule.\n- *\n- * Adds or removes the addresses using the Netlink command like this:\n- *   ip addr add <src_ip> peer <dst_ip> scope link dev <ifouter>\n- *\n- * The addresses are local to the netdev (\"scope link\"), this reduces\n- * the risk of conflicts. Note that an implicit route is maintained by\n- * the kernel due to the presence of a peer address (IFA_ADDRESS).\n- *\n- * @param[in] tcf\n- *   Libmnl socket context object.\n- * @param[in] iface\n- *   Object, contains rule database and ifouter index.\n- * @param[in] dev_flow\n- *   Flow object, contains the tunnel parameters (for encap only).\n- * @param[in] enable\n- *   Toggle between add and remove.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_encap_local(struct mlx5_flow_tcf_context *tcf,\n-\t\t     struct tcf_irule *iface,\n-\t\t     struct mlx5_flow *dev_flow,\n-\t\t     bool enable,\n-\t\t     struct rte_flow_error *error)\n-{\n-\tconst struct flow_tcf_vxlan_encap *encap = dev_flow->tcf.vxlan_encap;\n-\tstruct tcf_local_rule *rule = NULL;\n-\tint ret;\n-\n-\tassert(encap);\n-\tassert(encap->hdr.type == FLOW_TCF_TUNACT_VXLAN_ENCAP);\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_SRC) {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV4_DST);\n-\t\tLIST_FOREACH(rule, &iface->local, next) {\n-\t\t\tif (rule->mask & FLOW_TCF_ENCAP_IPV4_SRC &&\n-\t\t\t    encap->ipv4.src == rule->ipv4.src &&\n-\t\t\t    encap->ipv4.dst == rule->ipv4.dst) {\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t} else {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_SRC);\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_DST);\n-\t\tLIST_FOREACH(rule, &iface->local, next) {\n-\t\t\tif (rule->mask & FLOW_TCF_ENCAP_IPV6_SRC &&\n-\t\t\t    !memcmp(&encap->ipv6.src, &rule->ipv6.src,\n-\t\t\t\t\t    sizeof(encap->ipv6.src)) &&\n-\t\t\t    !memcmp(&encap->ipv6.dst, &rule->ipv6.dst,\n-\t\t\t\t\t    sizeof(encap->ipv6.dst))) {\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t}\n-\tif (rule) {\n-\t\tif (enable) {\n-\t\t\trule->refcnt++;\n-\t\t\treturn 0;\n-\t\t}\n-\t\tif (!rule->refcnt || !--rule->refcnt) {\n-\t\t\tLIST_REMOVE(rule, next);\n-\t\t\treturn flow_tcf_rule_local(tcf, encap,\n-\t\t\t\t\tiface->ifouter, false, error);\n-\t\t}\n-\t\treturn 0;\n-\t}\n-\tif (!enable) {\n-\t\tDRV_LOG(WARNING, \"disabling not existing local rule\");\n-\t\trte_flow_error_set(error, ENOENT,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"disabling not existing local rule\");\n-\t\treturn -ENOENT;\n-\t}\n-\trule = rte_zmalloc(__func__, sizeof(struct tcf_local_rule),\n-\t\t\t\talignof(struct tcf_local_rule));\n-\tif (!rule) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unable to allocate memory for local rule\");\n-\t\treturn -rte_errno;\n-\t}\n-\t*rule = (struct tcf_local_rule){.refcnt = 0,\n-\t\t\t\t\t.mask = 0,\n-\t\t\t\t\t};\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_SRC) {\n-\t\trule->mask = FLOW_TCF_ENCAP_IPV4_SRC\n-\t\t\t   | FLOW_TCF_ENCAP_IPV4_DST;\n-\t\trule->ipv4.src = encap->ipv4.src;\n-\t\trule->ipv4.dst = encap->ipv4.dst;\n-\t} else {\n-\t\trule->mask = FLOW_TCF_ENCAP_IPV6_SRC\n-\t\t\t   | FLOW_TCF_ENCAP_IPV6_DST;\n-\t\tmemcpy(&rule->ipv6.src, &encap->ipv6.src, IPV6_ADDR_LEN);\n-\t\tmemcpy(&rule->ipv6.dst, &encap->ipv6.dst, IPV6_ADDR_LEN);\n-\t}\n-\tret = flow_tcf_rule_local(tcf, encap, iface->ifouter, true, error);\n-\tif (ret) {\n-\t\trte_free(rule);\n-\t\treturn ret;\n-\t}\n-\trule->refcnt++;\n-\tLIST_INSERT_HEAD(&iface->local, rule, next);\n-\treturn 0;\n-}\n-\n-/**\n- * Manage the destination MAC/IP addresses neigh database, kernel uses\n- * this one to determine the destination MAC address within encapsulation\n- * header. Adds or removes the entries using the Netlink command like this:\n- *   ip neigh add dev <ifouter> lladdr <dst_mac> to <dst_ip> nud permanent\n- *\n- * @param[in] tcf\n- *   Libmnl socket context object.\n- * @param[in] iface\n- *   Object, contains rule database and ifouter index.\n- * @param[in] dev_flow\n- *   Flow object, contains the tunnel parameters (for encap only).\n- * @param[in] enable\n- *   Toggle between add and remove.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_encap_neigh(struct mlx5_flow_tcf_context *tcf,\n-\t\t     struct tcf_irule *iface,\n-\t\t     struct mlx5_flow *dev_flow,\n-\t\t     bool enable,\n-\t\t     struct rte_flow_error *error)\n-{\n-\tconst struct flow_tcf_vxlan_encap *encap = dev_flow->tcf.vxlan_encap;\n-\tstruct tcf_neigh_rule *rule = NULL;\n-\tint ret;\n-\n-\tassert(encap);\n-\tassert(encap->hdr.type == FLOW_TCF_TUNACT_VXLAN_ENCAP);\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_DST) {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV4_SRC);\n-\t\tLIST_FOREACH(rule, &iface->neigh, next) {\n-\t\t\tif (rule->mask & FLOW_TCF_ENCAP_IPV4_DST &&\n-\t\t\t    encap->ipv4.dst == rule->ipv4.dst) {\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t} else {\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_SRC);\n-\t\tassert(encap->mask & FLOW_TCF_ENCAP_IPV6_DST);\n-\t\tLIST_FOREACH(rule, &iface->neigh, next) {\n-\t\t\tif (rule->mask & FLOW_TCF_ENCAP_IPV6_DST &&\n-\t\t\t    !memcmp(&encap->ipv6.dst, &rule->ipv6.dst,\n-\t\t\t\t\t\tsizeof(encap->ipv6.dst))) {\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t}\n-\tif (rule) {\n-\t\tif (memcmp(&encap->eth.dst, &rule->eth,\n-\t\t\t   sizeof(encap->eth.dst))) {\n-\t\t\tDRV_LOG(WARNING, \"Destination MAC differs\"\n-\t\t\t\t\t \" in neigh rule\");\n-\t\t\trte_flow_error_set(error, EEXIST,\n-\t\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t\t   NULL, \"Different MAC address\"\n-\t\t\t\t\t   \" neigh rule for the same\"\n-\t\t\t\t\t   \" destination IP\");\n-\t\t\t\t\treturn -EEXIST;\n-\t\t}\n-\t\tif (enable) {\n-\t\t\trule->refcnt++;\n-\t\t\treturn 0;\n-\t\t}\n-\t\tif (!rule->refcnt || !--rule->refcnt) {\n-\t\t\tLIST_REMOVE(rule, next);\n-\t\t\treturn flow_tcf_rule_neigh(tcf, encap,\n-\t\t\t\t\t\t   iface->ifouter,\n-\t\t\t\t\t\t   false, error);\n-\t\t}\n-\t\treturn 0;\n-\t}\n-\tif (!enable) {\n-\t\tDRV_LOG(WARNING, \"Disabling not existing neigh rule\");\n-\t\trte_flow_error_set(error, ENOENT,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unable to allocate memory for neigh rule\");\n-\t\treturn -ENOENT;\n-\t}\n-\trule = rte_zmalloc(__func__, sizeof(struct tcf_neigh_rule),\n-\t\t\t\talignof(struct tcf_neigh_rule));\n-\tif (!rule) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unable to allocate memory for neigh rule\");\n-\t\treturn -rte_errno;\n-\t}\n-\t*rule = (struct tcf_neigh_rule){.refcnt = 0,\n-\t\t\t\t\t.mask = 0,\n-\t\t\t\t\t};\n-\tif (encap->mask & FLOW_TCF_ENCAP_IPV4_DST) {\n-\t\trule->mask = FLOW_TCF_ENCAP_IPV4_DST;\n-\t\trule->ipv4.dst = encap->ipv4.dst;\n-\t} else {\n-\t\trule->mask = FLOW_TCF_ENCAP_IPV6_DST;\n-\t\tmemcpy(&rule->ipv6.dst, &encap->ipv6.dst, IPV6_ADDR_LEN);\n-\t}\n-\tmemcpy(&rule->eth, &encap->eth.dst, sizeof(rule->eth));\n-\tret = flow_tcf_rule_neigh(tcf, encap, iface->ifouter, true, error);\n-\tif (ret) {\n-\t\trte_free(rule);\n-\t\treturn ret;\n-\t}\n-\trule->refcnt++;\n-\tLIST_INSERT_HEAD(&iface->neigh, rule, next);\n-\treturn 0;\n-}\n-\n-/* VXLAN encap rule database for outer interfaces. */\n-static  LIST_HEAD(, tcf_irule) iface_list_vxlan = LIST_HEAD_INITIALIZER();\n-\n-/* VTEP device list is shared between PMD port instances. */\n-static LIST_HEAD(, tcf_vtep) vtep_list_vxlan = LIST_HEAD_INITIALIZER();\n-static pthread_mutex_t vtep_list_mutex = PTHREAD_MUTEX_INITIALIZER;\n-\n-/**\n- * Acquire the VXLAN encap rules container for specified interface.\n- * First looks for the container in the existing ones list, creates\n- * and initializes the new container if existing not found.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifouter\n- *   Network interface index to create VXLAN encap rules on.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- * @return\n- *   Rule container pointer on success,\n- *   NULL otherwise and rte_errno is set.\n- */\n-static struct tcf_irule*\n-flow_tcf_encap_irule_acquire(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t     unsigned int ifouter,\n-\t\t\t     struct rte_flow_error *error)\n-{\n-\tstruct tcf_irule *iface;\n-\n-\t/* Look whether the container for encap rules is created. */\n-\tassert(ifouter);\n-\tLIST_FOREACH(iface, &iface_list_vxlan, next) {\n-\t\tif (iface->ifouter == ifouter)\n-\t\t\tbreak;\n-\t}\n-\tif (iface) {\n-\t\t/* Container already exists, just increment the reference. */\n-\t\tiface->refcnt++;\n-\t\treturn iface;\n-\t}\n-\t/* Not found, we should create the new container. */\n-\tiface = rte_zmalloc(__func__, sizeof(*iface),\n-\t\t\t    alignof(struct tcf_irule));\n-\tif (!iface) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unable to allocate memory for container\");\n-\t\treturn NULL;\n-\t}\n-\t*iface = (struct tcf_irule){\n-\t\t\t.local = LIST_HEAD_INITIALIZER(),\n-\t\t\t.neigh = LIST_HEAD_INITIALIZER(),\n-\t\t\t.ifouter = ifouter,\n-\t\t\t.refcnt = 1,\n-\t};\n-\t/* Interface cleanup for new container created. */\n-\tflow_tcf_encap_iface_cleanup(tcf, ifouter);\n-\tflow_tcf_encap_local_cleanup(tcf, ifouter);\n-\tflow_tcf_encap_neigh_cleanup(tcf, ifouter);\n-\tLIST_INSERT_HEAD(&iface_list_vxlan, iface, next);\n-\treturn iface;\n-}\n-\n-/**\n- * Releases VXLAN encap rules container by pointer. Decrements the\n- * reference counter and deletes the container if counter is zero.\n- *\n- * @param[in] irule\n- *   VXLAN rule container pointer to release.\n- */\n-static void\n-flow_tcf_encap_irule_release(struct tcf_irule *iface)\n-{\n-\tassert(iface->refcnt);\n-\tif (--iface->refcnt == 0) {\n-\t\t/* Reference counter is zero, delete the container. */\n-\t\tassert(LIST_EMPTY(&iface->local));\n-\t\tassert(LIST_EMPTY(&iface->neigh));\n-\t\tLIST_REMOVE(iface, next);\n-\t\trte_free(iface);\n-\t}\n-}\n-\n-/**\n- * Deletes VTEP network device.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] vtep\n- *   Object representing the network device to delete. Memory\n- *   allocated for this object is freed by routine.\n- */\n-static void\n-flow_tcf_vtep_delete(struct mlx5_flow_tcf_context *tcf,\n-\t\t     struct tcf_vtep *vtep)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifinfomsg *ifm;\n-\talignas(struct nlmsghdr)\n-\tuint8_t buf[mnl_nlmsg_size(MNL_ALIGN(sizeof(*ifm))) +\n-\t\t    MNL_BUF_EXTRA_SPACE];\n-\tint ret;\n-\n-\tassert(!vtep->refcnt);\n-\t/* Delete only ifaces those we actually created. */\n-\tif (vtep->created && vtep->ifindex) {\n-\t\tDRV_LOG(INFO, \"VTEP delete (%d)\", vtep->ifindex);\n-\t\tnlh = mnl_nlmsg_put_header(buf);\n-\t\tnlh->nlmsg_type = RTM_DELLINK;\n-\t\tnlh->nlmsg_flags = NLM_F_REQUEST;\n-\t\tifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));\n-\t\tifm->ifi_family = AF_UNSPEC;\n-\t\tifm->ifi_index = vtep->ifindex;\n-\t\tassert(sizeof(buf) >= nlh->nlmsg_len);\n-\t\tret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);\n-\t\tif (ret)\n-\t\t\tDRV_LOG(WARNING, \"netlink: error deleting vxlan\"\n-\t\t\t\t\t \" encap/decap ifindex %u\",\n-\t\t\t\t\t ifm->ifi_index);\n-\t}\n-\trte_free(vtep);\n-}\n-\n-/**\n- * Creates VTEP network device.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] port\n- *   UDP port of created VTEP device.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- * Pointer to created device structure on success,\n- * NULL otherwise and rte_errno is set.\n- */\n-static struct tcf_vtep*\n-flow_tcf_vtep_create(struct mlx5_flow_tcf_context *tcf,\n-\t\t     uint16_t port, struct rte_flow_error *error)\n-{\n-\tstruct tcf_vtep *vtep;\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifinfomsg *ifm;\n-\tchar name[sizeof(MLX5_VXLAN_DEVICE_PFX) + 24];\n-\talignas(struct nlmsghdr)\n-\tuint8_t buf[mnl_nlmsg_size(sizeof(*ifm)) +\n-\t\t    SZ_NLATTR_DATA_OF(sizeof(name)) +\n-\t\t    SZ_NLATTR_NEST * 2 +\n-\t\t    SZ_NLATTR_STRZ_OF(\"vxlan\") +\n-\t\t    SZ_NLATTR_DATA_OF(sizeof(uint32_t)) +\n-\t\t    SZ_NLATTR_DATA_OF(sizeof(uint16_t)) +\n-\t\t    SZ_NLATTR_DATA_OF(sizeof(uint8_t)) * 3 +\n-\t\t    MNL_BUF_EXTRA_SPACE];\n-\tstruct nlattr *na_info;\n-\tstruct nlattr *na_vxlan;\n-\trte_be16_t vxlan_port = rte_cpu_to_be_16(port);\n-\tint ret;\n-\n-\tvtep = rte_zmalloc(__func__, sizeof(*vtep), alignof(struct tcf_vtep));\n-\tif (!vtep) {\n-\t\trte_flow_error_set(error, ENOMEM,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unable to allocate memory for VTEP\");\n-\t\treturn NULL;\n-\t}\n-\t*vtep = (struct tcf_vtep){\n-\t\t\t.port = port,\n-\t};\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = RTM_NEWLINK;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE  | NLM_F_EXCL;\n-\tifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));\n-\tifm->ifi_family = AF_UNSPEC;\n-\tifm->ifi_type = 0;\n-\tifm->ifi_index = 0;\n-\tifm->ifi_flags = IFF_UP;\n-\tifm->ifi_change = 0xffffffff;\n-\tsnprintf(name, sizeof(name), \"%s%u\", MLX5_VXLAN_DEVICE_PFX, port);\n-\tmnl_attr_put_strz(nlh, IFLA_IFNAME, name);\n-\tna_info = mnl_attr_nest_start(nlh, IFLA_LINKINFO);\n-\tassert(na_info);\n-\tmnl_attr_put_strz(nlh, IFLA_INFO_KIND, \"vxlan\");\n-\tna_vxlan = mnl_attr_nest_start(nlh, IFLA_INFO_DATA);\n-\tassert(na_vxlan);\n-#ifdef HAVE_IFLA_VXLAN_COLLECT_METADATA\n-\t/*\n-\t * RH 7.2 does not support metadata for tunnel device.\n-\t * It does not matter because we are going to use the\n-\t * hardware offload by mlx5 driver.\n-\t */\n-\tmnl_attr_put_u8(nlh, IFLA_VXLAN_COLLECT_METADATA, 1);\n-#endif\n-\tmnl_attr_put_u8(nlh, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 1);\n-\tmnl_attr_put_u8(nlh, IFLA_VXLAN_LEARNING, 0);\n-\tmnl_attr_put_u16(nlh, IFLA_VXLAN_PORT, vxlan_port);\n-#ifndef HAVE_IFLA_VXLAN_COLLECT_METADATA\n-\t/*\n-\t *  We must specify VNI explicitly if metadata not supported.\n-\t *  Note, VNI is transferred with native endianness format.\n-\t */\n-\tmnl_attr_put_u16(nlh, IFLA_VXLAN_ID, MLX5_VXLAN_DEFAULT_VNI);\n-#endif\n-\tmnl_attr_nest_end(nlh, na_vxlan);\n-\tmnl_attr_nest_end(nlh, na_info);\n-\tassert(sizeof(buf) >= nlh->nlmsg_len);\n-\tret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);\n-\tif (ret) {\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"netlink: VTEP %s create failure (%d)\",\n-\t\t\tname, rte_errno);\n-\t\tif (rte_errno != EEXIST)\n-\t\t\t/*\n-\t\t\t * Some unhandled error occurred or device is\n-\t\t\t * for encapsulation and cannot be shared.\n-\t\t\t */\n-\t\t\tgoto error;\n-\t} else {\n-\t\t/*\n-\t\t * Mark device we actually created.\n-\t\t * We should explicitly delete\n-\t\t * when we do not need it anymore.\n-\t\t */\n-\t\tvtep->created = 1;\n-\t\tvtep->waitreg = 1;\n-\t}\n-\t/* Try to get ifindex of created of pre-existing device. */\n-\tret = if_nametoindex(name);\n-\tif (!ret) {\n-\t\tDRV_LOG(WARNING,\n-\t\t\t\"VTEP %s failed to get index (%d)\", name, errno);\n-\t\trte_flow_error_set\n-\t\t\t(error, -errno,\n-\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t \"netlink: failed to retrieve VTEP ifindex\");\n-\t\tgoto error;\n-\t}\n-\tvtep->ifindex = ret;\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = RTM_NEWLINK;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST;\n-\tifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));\n-\tifm->ifi_family = AF_UNSPEC;\n-\tifm->ifi_type = 0;\n-\tifm->ifi_index = vtep->ifindex;\n-\tifm->ifi_flags = IFF_UP;\n-\tifm->ifi_change = IFF_UP;\n-\tret = flow_tcf_nl_ack(tcf, nlh, NULL, NULL);\n-\tif (ret) {\n-\t\trte_flow_error_set(error, -errno,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"netlink: failed to set VTEP link up\");\n-\t\tDRV_LOG(WARNING, \"netlink: VTEP %s set link up failure (%d)\",\n-\t\t\tname, rte_errno);\n-\t\tgoto clean;\n-\t}\n-\tret = mlx5_flow_tcf_init(tcf, vtep->ifindex, error);\n-\tif (ret) {\n-\t\tDRV_LOG(WARNING, \"VTEP %s init failure (%d)\", name, rte_errno);\n-\t\tgoto clean;\n-\t}\n-\tDRV_LOG(INFO, \"VTEP create (%d, %d)\", vtep->port, vtep->ifindex);\n-\tvtep->refcnt = 1;\n-\treturn vtep;\n-clean:\n-\tflow_tcf_vtep_delete(tcf, vtep);\n-\treturn NULL;\n-error:\n-\trte_free(vtep);\n-\treturn NULL;\n-}\n-\n-/**\n- * Acquire target interface index for VXLAN tunneling decapsulation.\n- * In order to share the UDP port within the other interfaces the\n- * VXLAN device created as not attached to any interface (if created).\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] dev_flow\n- *   Flow tcf object with tunnel structure pointer set.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- * @return\n- *   Interface descriptor pointer on success,\n- *   NULL otherwise and rte_errno is set.\n- */\n-static struct tcf_vtep*\n-flow_tcf_decap_vtep_acquire(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t    struct mlx5_flow *dev_flow,\n-\t\t\t    struct rte_flow_error *error)\n-{\n-\tstruct tcf_vtep *vtep;\n-\tuint16_t port = dev_flow->tcf.vxlan_decap->udp_port;\n-\n-\tLIST_FOREACH(vtep, &vtep_list_vxlan, next) {\n-\t\tif (vtep->port == port)\n-\t\t\tbreak;\n-\t}\n-\tif (vtep) {\n-\t\t/* Device exists, just increment the reference counter. */\n-\t\tvtep->refcnt++;\n-\t\tassert(vtep->ifindex);\n-\t\treturn vtep;\n-\t}\n-\t/* No decapsulation device exists, try to create the new one. */\n-\tvtep = flow_tcf_vtep_create(tcf, port, error);\n-\tif (vtep)\n-\t\tLIST_INSERT_HEAD(&vtep_list_vxlan, vtep, next);\n-\treturn vtep;\n-}\n-\n-/**\n- * Acquire target interface index for VXLAN tunneling encapsulation.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifouter\n- *   Network interface index to attach VXLAN encap device to.\n- * @param[in] dev_flow\n- *   Flow tcf object with tunnel structure pointer set.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- * @return\n- *   Interface descriptor pointer on success,\n- *   NULL otherwise and rte_errno is set.\n- */\n-static struct tcf_vtep*\n-flow_tcf_encap_vtep_acquire(struct mlx5_flow_tcf_context *tcf,\n-\t\t\t    unsigned int ifouter,\n-\t\t\t    struct mlx5_flow *dev_flow,\n-\t\t\t    struct rte_flow_error *error)\n-{\n-\tstatic uint16_t port;\n-\tstruct tcf_vtep *vtep;\n-\tstruct tcf_irule *iface;\n-\tint ret;\n-\n-\tassert(ifouter);\n-\t/* Look whether the VTEP for specified port is created. */\n-\tport = rte_be_to_cpu_16(dev_flow->tcf.vxlan_encap->udp.dst);\n-\tLIST_FOREACH(vtep, &vtep_list_vxlan, next) {\n-\t\tif (vtep->port == port)\n-\t\t\tbreak;\n-\t}\n-\tif (vtep) {\n-\t\t/* VTEP already exists, just increment the reference. */\n-\t\tvtep->refcnt++;\n-\t} else {\n-\t\t/* Not found, we should create the new VTEP. */\n-\t\tvtep = flow_tcf_vtep_create(tcf, port, error);\n-\t\tif (!vtep)\n-\t\t\treturn NULL;\n-\t\tLIST_INSERT_HEAD(&vtep_list_vxlan, vtep, next);\n-\t}\n-\tassert(vtep->ifindex);\n-\tiface = flow_tcf_encap_irule_acquire(tcf, ifouter, error);\n-\tif (!iface) {\n-\t\tif (--vtep->refcnt == 0)\n-\t\t\tflow_tcf_vtep_delete(tcf, vtep);\n-\t\treturn NULL;\n-\t}\n-\tdev_flow->tcf.vxlan_encap->iface = iface;\n-\t/* Create local ipaddr with peer to specify the outer IPs. */\n-\tret = flow_tcf_encap_local(tcf, iface, dev_flow, true, error);\n-\tif (!ret) {\n-\t\t/* Create neigh rule to specify outer destination MAC. */\n-\t\tret = flow_tcf_encap_neigh(tcf, iface, dev_flow, true, error);\n-\t\tif (ret)\n-\t\t\tflow_tcf_encap_local(tcf, iface,\n-\t\t\t\t\t     dev_flow, false, error);\n-\t}\n-\tif (ret) {\n-\t\tdev_flow->tcf.vxlan_encap->iface = NULL;\n-\t\tflow_tcf_encap_irule_release(iface);\n-\t\tif (--vtep->refcnt == 0)\n-\t\t\tflow_tcf_vtep_delete(tcf, vtep);\n-\t\treturn NULL;\n-\t}\n-\treturn vtep;\n-}\n-\n-/**\n- * Acquires target interface index for tunneling of any type.\n- * Creates the new VTEP if needed.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] ifouter\n- *   Network interface index to create VXLAN encap rules on.\n- * @param[in] dev_flow\n- *   Flow tcf object with tunnel structure pointer set.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- * @return\n- *   Interface descriptor pointer on success,\n- *   NULL otherwise and rte_errno is set.\n- */\n-static struct tcf_vtep*\n-flow_tcf_vtep_acquire(struct mlx5_flow_tcf_context *tcf,\n-\t\t      unsigned int ifouter,\n-\t\t      struct mlx5_flow *dev_flow,\n-\t\t      struct rte_flow_error *error)\n-{\n-\tstruct tcf_vtep *vtep = NULL;\n-\n-\tassert(dev_flow->tcf.tunnel);\n-\tpthread_mutex_lock(&vtep_list_mutex);\n-\tswitch (dev_flow->tcf.tunnel->type) {\n-\tcase FLOW_TCF_TUNACT_VXLAN_ENCAP:\n-\t\tvtep = flow_tcf_encap_vtep_acquire(tcf, ifouter,\n-\t\t\t\t\t\t  dev_flow, error);\n-\t\tbreak;\n-\tcase FLOW_TCF_TUNACT_VXLAN_DECAP:\n-\t\tvtep = flow_tcf_decap_vtep_acquire(tcf, dev_flow, error);\n-\t\tbreak;\n-\tdefault:\n-\t\trte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t   \"unsupported tunnel type\");\n-\t\tbreak;\n-\t}\n-\tpthread_mutex_unlock(&vtep_list_mutex);\n-\treturn vtep;\n-}\n-\n-/**\n- * Release tunneling interface by ifindex. Decrements reference\n- * counter and actually removes the device if counter is zero.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] vtep\n- *   VTEP device descriptor structure.\n- * @param[in] dev_flow\n- *   Flow tcf object with tunnel structure pointer set.\n- */\n-static void\n-flow_tcf_vtep_release(struct mlx5_flow_tcf_context *tcf,\n-\t\t      struct tcf_vtep *vtep,\n-\t\t      struct mlx5_flow *dev_flow)\n-{\n-\tassert(dev_flow->tcf.tunnel);\n-\tpthread_mutex_lock(&vtep_list_mutex);\n-\tswitch (dev_flow->tcf.tunnel->type) {\n-\tcase FLOW_TCF_TUNACT_VXLAN_DECAP:\n-\t\tbreak;\n-\tcase FLOW_TCF_TUNACT_VXLAN_ENCAP: {\n-\t\tstruct tcf_irule *iface;\n-\n-\t\t/* Remove the encap ancillary rules first. */\n-\t\tiface = dev_flow->tcf.vxlan_encap->iface;\n-\t\tassert(iface);\n-\t\tflow_tcf_encap_neigh(tcf, iface, dev_flow, false, NULL);\n-\t\tflow_tcf_encap_local(tcf, iface, dev_flow, false, NULL);\n-\t\tflow_tcf_encap_irule_release(iface);\n-\t\tdev_flow->tcf.vxlan_encap->iface = NULL;\n-\t\tbreak;\n-\t}\n-\tdefault:\n-\t\tassert(false);\n-\t\tDRV_LOG(WARNING, \"Unsupported tunnel type\");\n-\t\tbreak;\n-\t}\n-\tassert(vtep->refcnt);\n-\tif (--vtep->refcnt == 0) {\n-\t\tLIST_REMOVE(vtep, next);\n-\t\tflow_tcf_vtep_delete(tcf, vtep);\n-\t}\n-\tpthread_mutex_unlock(&vtep_list_mutex);\n-}\n-\n-struct tcf_nlcb_query {\n-\tuint32_t handle;\n-\tuint32_t tc_flags;\n-\tuint32_t flags_valid:1;\n-};\n-\n-/**\n- * Collect queried rule attributes. This is callback routine called by\n- * libmnl mnl_cb_run() in loop for every message in received packet.\n- * Current implementation collects the flower flags only.\n- *\n- * @param[in] nlh\n- *   Pointer to reply header.\n- * @param[in, out] arg\n- *   Context pointer for this callback.\n- *\n- * @return\n- *   A positive, nonzero value on success (required by libmnl\n- *   to continue messages processing).\n- */\n-static int\n-flow_tcf_collect_query_cb(const struct nlmsghdr *nlh, void *arg)\n-{\n-\tstruct tcf_nlcb_query *query = arg;\n-\tstruct tcmsg *tcm = mnl_nlmsg_get_payload(nlh);\n-\tstruct nlattr *na, *na_opt;\n-\tbool flower = false;\n-\n-\tif (nlh->nlmsg_type != RTM_NEWTFILTER ||\n-\t    tcm->tcm_handle != query->handle)\n-\t\treturn 1;\n-\tmnl_attr_for_each(na, nlh, sizeof(*tcm)) {\n-\t\tswitch (mnl_attr_get_type(na)) {\n-\t\tcase TCA_KIND:\n-\t\t\tif (strcmp(mnl_attr_get_payload(na), \"flower\")) {\n-\t\t\t\t/* Not flower filter, drop entire message. */\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\tflower = true;\n-\t\t\tbreak;\n-\t\tcase TCA_OPTIONS:\n-\t\t\tif (!flower) {\n-\t\t\t\t/* Not flower options, drop entire message. */\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\t/* Check nested flower options. */\n-\t\t\tmnl_attr_for_each_nested(na_opt, na) {\n-\t\t\t\tswitch (mnl_attr_get_type(na_opt)) {\n-\t\t\t\tcase TCA_FLOWER_FLAGS:\n-\t\t\t\t\tquery->flags_valid = 1;\n-\t\t\t\t\tquery->tc_flags =\n-\t\t\t\t\t\tmnl_attr_get_u32(na_opt);\n-\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\treturn 1;\n-}\n-\n-/**\n- * Query a TC flower rule flags via netlink.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] dev_flow\n- *   Pointer to the flow.\n- * @param[out] pflags\n- *   pointer to the data retrieved by the query.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise.\n- */\n-static int\n-flow_tcf_query_flags(struct mlx5_flow_tcf_context *tcf,\n-\t\t     struct mlx5_flow *dev_flow,\n-\t\t     uint32_t *pflags)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\tstruct tcf_nlcb_query query = {\n-\t\t.handle = dev_flow->tcf.tcm->tcm_handle,\n-\t};\n-\n-\tnlh = mnl_nlmsg_put_header(tcf->buf);\n-\tnlh->nlmsg_type = RTM_GETTFILTER;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST;\n-\ttcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm));\n-\tmemcpy(tcm, dev_flow->tcf.tcm, sizeof(*tcm));\n-\t/*\n-\t * Ignore Netlink error for filter query operations.\n-\t * The reply length is sent by kernel as errno.\n-\t * Just check we got the flags option.\n-\t */\n-\tflow_tcf_nl_ack(tcf, nlh, flow_tcf_collect_query_cb, &query);\n-\tif (!query.flags_valid) {\n-\t\t*pflags = 0;\n-\t\treturn -ENOENT;\n-\t}\n-\t*pflags = query.tc_flags;\n-\treturn 0;\n-}\n-\n-/**\n- * Query and check the in_hw set for specified rule.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_flow_tcf_context_create().\n- * @param[in] dev_flow\n- *   Pointer to the flow to check.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise.\n- */\n-static int\n-flow_tcf_check_inhw(struct mlx5_flow_tcf_context *tcf,\n-\t\t    struct mlx5_flow *dev_flow)\n-{\n-\tuint32_t flags;\n-\tint ret;\n-\n-\tret = flow_tcf_query_flags(tcf, dev_flow, &flags);\n-\tif (ret)\n-\t\treturn ret;\n-\treturn  (flags & TCA_CLS_FLAGS_IN_HW) ? 0 : -ENOENT;\n-}\n-\n-/**\n- * Remove flow from E-Switch by sending Netlink message.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in, out] flow\n- *   Pointer to the sub flow.\n- */\n-static void\n-flow_tcf_remove(struct rte_eth_dev *dev, struct rte_flow *flow)\n-{\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_tcf_context *ctx = priv->tcf_context;\n-\tstruct mlx5_flow *dev_flow;\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\n-\tif (!flow)\n-\t\treturn;\n-\tdev_flow = LIST_FIRST(&flow->dev_flows);\n-\tif (!dev_flow)\n-\t\treturn;\n-\t/* E-Switch flow can't be expanded. */\n-\tassert(!LIST_NEXT(dev_flow, next));\n-\tif (dev_flow->tcf.applied) {\n-\t\tnlh = dev_flow->tcf.nlh;\n-\t\tnlh->nlmsg_type = RTM_DELTFILTER;\n-\t\tnlh->nlmsg_flags = NLM_F_REQUEST;\n-\t\tflow_tcf_nl_ack(ctx, nlh, NULL, NULL);\n-\t\tif (dev_flow->tcf.tunnel) {\n-\t\t\tassert(dev_flow->tcf.tunnel->vtep);\n-\t\t\tflow_tcf_vtep_release(ctx,\n-\t\t\t\tdev_flow->tcf.tunnel->vtep,\n-\t\t\t\tdev_flow);\n-\t\t\tdev_flow->tcf.tunnel->vtep = NULL;\n-\t\t}\n-\t\t/* Cleanup the rule handle value. */\n-\t\ttcm = mnl_nlmsg_get_payload(nlh);\n-\t\ttcm->tcm_handle = 0;\n-\t\tdev_flow->tcf.applied = 0;\n-\t}\n-}\n-\n-/**\n- * Fetch the applied rule handle. This is callback routine called by\n- * libmnl mnl_cb_run() in loop for every message in received packet.\n- * When the NLM_F_ECHO flag is specified the kernel sends the created\n- * rule descriptor back to the application and we can retrieve the\n- * actual rule handle from updated descriptor.\n- *\n- * @param[in] nlh\n- *   Pointer to reply header.\n- * @param[in, out] arg\n- *   Context pointer for this callback.\n- *\n- * @return\n- *   A positive, nonzero value on success (required by libmnl\n- *   to continue messages processing).\n- */\n-static int\n-flow_tcf_collect_apply_cb(const struct nlmsghdr *nlh, void *arg)\n-{\n-\tstruct nlmsghdr *nlhrq = arg;\n-\tstruct tcmsg *tcmrq = mnl_nlmsg_get_payload(nlhrq);\n-\tstruct tcmsg *tcm = mnl_nlmsg_get_payload(nlh);\n-\tstruct nlattr *na;\n-\n-\tif (nlh->nlmsg_type != RTM_NEWTFILTER ||\n-\t    nlh->nlmsg_seq != nlhrq->nlmsg_seq)\n-\t\treturn 1;\n-\tmnl_attr_for_each(na, nlh, sizeof(*tcm)) {\n-\t\tswitch (mnl_attr_get_type(na)) {\n-\t\tcase TCA_KIND:\n-\t\t\tif (strcmp(mnl_attr_get_payload(na), \"flower\")) {\n-\t\t\t\t/* Not flower filter, drop entire message. */\n-\t\t\t\treturn 1;\n-\t\t\t}\n-\t\t\ttcmrq->tcm_handle = tcm->tcm_handle;\n-\t\t\treturn 1;\n-\t\t}\n-\t}\n-\treturn 1;\n-}\n-/**\n- * Apply flow to E-Switch by sending Netlink message.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in, out] flow\n- *   Pointer to the sub flow.\n- * @param[out] error\n- *   Pointer to the error structure.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_apply(struct rte_eth_dev *dev, struct rte_flow *flow,\n-\t       struct rte_flow_error *error)\n-{\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_tcf_context *ctx = priv->tcf_context;\n-\tstruct mlx5_flow *dev_flow;\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\tuint64_t start = 0;\n-\tuint64_t twait = 0;\n-\tint ret;\n-\n-\tdev_flow = LIST_FIRST(&flow->dev_flows);\n-\t/* E-Switch flow can't be expanded. */\n-\tassert(!LIST_NEXT(dev_flow, next));\n-\tif (dev_flow->tcf.applied)\n-\t\treturn 0;\n-\tnlh = dev_flow->tcf.nlh;\n-\tnlh->nlmsg_type = RTM_NEWTFILTER;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |\n-\t\t\t   NLM_F_EXCL | NLM_F_ECHO;\n-\ttcm = mnl_nlmsg_get_payload(nlh);\n-\t/* Allow kernel to assign handle on its own. */\n-\ttcm->tcm_handle = 0;\n-\tif (dev_flow->tcf.tunnel) {\n-\t\t/*\n-\t\t * Replace the interface index, target for\n-\t\t * encapsulation, source for decapsulation.\n-\t\t */\n-\t\tassert(!dev_flow->tcf.tunnel->vtep);\n-\t\tassert(dev_flow->tcf.tunnel->ifindex_ptr);\n-\t\t/* Acquire actual VTEP device when rule is being applied. */\n-\t\tdev_flow->tcf.tunnel->vtep =\n-\t\t\tflow_tcf_vtep_acquire(ctx,\n-\t\t\t\t\tdev_flow->tcf.tunnel->ifindex_org,\n-\t\t\t\t\tdev_flow, error);\n-\t\tif (!dev_flow->tcf.tunnel->vtep)\n-\t\t\treturn -rte_errno;\n-\t\tDRV_LOG(INFO, \"Replace ifindex: %d->%d\",\n-\t\t\t\tdev_flow->tcf.tunnel->vtep->ifindex,\n-\t\t\t\tdev_flow->tcf.tunnel->ifindex_org);\n-\t\t*dev_flow->tcf.tunnel->ifindex_ptr =\n-\t\t\tdev_flow->tcf.tunnel->vtep->ifindex;\n-\t\tif (dev_flow->tcf.tunnel->vtep->waitreg) {\n-\t\t\t/* Clear wait flag for VXLAN port registration. */\n-\t\t\tdev_flow->tcf.tunnel->vtep->waitreg = 0;\n-\t\t\ttwait = rte_get_timer_hz();\n-\t\t\tassert(twait > MS_PER_S);\n-\t\t\ttwait = twait * MLX5_VXLAN_WAIT_PORT_REG_MS;\n-\t\t\ttwait = twait / MS_PER_S;\n-\t\t\tstart = rte_get_timer_cycles();\n-\t\t}\n-\t}\n-\t/*\n-\t * Kernel creates the VXLAN devices and registers UDP ports to\n-\t * be hardware offloaded within the NIC kernel drivers. The\n-\t * registration process is being performed into context of\n-\t * working kernel thread and the race conditions might happen.\n-\t * The VXLAN device is created and success is returned to\n-\t * calling application, but the UDP port registration process\n-\t * is not completed yet. The next applied rule may be rejected\n-\t * by the driver with ENOSUP code. We are going to wait a bit,\n-\t * allowing registration process to be completed. The waiting\n-\t * is performed once after device been created.\n-\t */\n-\tdo {\n-\t\tstruct timespec onems;\n-\n-\t\tret = flow_tcf_nl_ack(ctx, nlh,\n-\t\t\t\t      flow_tcf_collect_apply_cb, nlh);\n-\t\tif (!ret || ret != -ENOTSUP || !twait)\n-\t\t\tbreak;\n-\t\t/* Wait one millisecond and try again till timeout. */\n-\t\tonems.tv_sec = 0;\n-\t\tonems.tv_nsec = NS_PER_S / MS_PER_S;\n-\t\tnanosleep(&onems, 0);\n-\t\tif ((rte_get_timer_cycles() - start) > twait) {\n-\t\t\t/* Timeout elapsed, try once more and exit. */\n-\t\t\ttwait = 0;\n-\t\t}\n-\t} while (true);\n-\tif (!ret) {\n-\t\tif (!tcm->tcm_handle) {\n-\t\t\tflow_tcf_remove(dev, flow);\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOENT,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t \"netlink: rule zero handle returned\");\n-\t\t}\n-\t\tdev_flow->tcf.applied = 1;\n-\t\tif (*dev_flow->tcf.ptc_flags & TCA_CLS_FLAGS_SKIP_SW)\n-\t\t\treturn 0;\n-\t\t/*\n-\t\t * Rule was applied without skip_sw flag set.\n-\t\t * We should check whether the rule was acctually\n-\t\t * accepted by hardware (have look at in_hw flag).\n-\t\t */\n-\t\tif (flow_tcf_check_inhw(ctx, dev_flow)) {\n-\t\t\tflow_tcf_remove(dev, flow);\n-\t\t\treturn rte_flow_error_set\n-\t\t\t\t(error, ENOENT,\n-\t\t\t\t RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t \"netlink: rule has no in_hw flag set\");\n-\t\t}\n-\t\treturn 0;\n-\t}\n-\tif (dev_flow->tcf.tunnel) {\n-\t\t/* Rollback the VTEP configuration if rule apply failed. */\n-\t\tassert(dev_flow->tcf.tunnel->vtep);\n-\t\tflow_tcf_vtep_release(ctx, dev_flow->tcf.tunnel->vtep,\n-\t\t\t\t      dev_flow);\n-\t\tdev_flow->tcf.tunnel->vtep = NULL;\n-\t}\n-\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t  \"netlink: failed to create TC flow rule\");\n-}\n-\n-/**\n- * Remove flow from E-Switch and release resources of the device flow.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in, out] flow\n- *   Pointer to the sub flow.\n- */\n-static void\n-flow_tcf_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)\n-{\n-\tstruct mlx5_flow *dev_flow;\n-\n-\tif (!flow)\n-\t\treturn;\n-\tflow_tcf_remove(dev, flow);\n-\tif (flow->counter) {\n-\t\tif (--flow->counter->ref_cnt == 0) {\n-\t\t\trte_free(flow->counter);\n-\t\t\tflow->counter = NULL;\n-\t\t}\n-\t}\n-\tdev_flow = LIST_FIRST(&flow->dev_flows);\n-\tif (!dev_flow)\n-\t\treturn;\n-\t/* E-Switch flow can't be expanded. */\n-\tassert(!LIST_NEXT(dev_flow, next));\n-\tLIST_REMOVE(dev_flow, next);\n-\trte_free(dev_flow);\n-}\n-\n-/**\n- * Helper routine for figuring the space size required for a parse buffer.\n- *\n- * @param array\n- *   array of values to use.\n- * @param idx\n- *   Current location in array.\n- * @param value\n- *   Value to compare with.\n- *\n- * @return\n- *   The maximum between the given value and the array value on index.\n- */\n-static uint16_t\n-flow_tcf_arr_val_max(uint16_t array[], int idx, uint16_t value)\n-{\n-\treturn idx < 0 ? (value) : RTE_MAX((array)[idx], value);\n-}\n-\n-/**\n- * Parse rtnetlink message attributes filling the attribute table with the info\n- * retrieved.\n- *\n- * @param tb\n- *   Attribute table to be filled.\n- * @param[out] max\n- *   Maxinum entry in the attribute table.\n- * @param rte\n- *   The attributes section in the message to be parsed.\n- * @param len\n- *   The length of the attributes section in the message.\n- */\n-static void\n-flow_tcf_nl_parse_rtattr(struct rtattr *tb[], int max,\n-\t\t\t struct rtattr *rta, int len)\n-{\n-\tunsigned short type;\n-\tmemset(tb, 0, sizeof(struct rtattr *) * (max + 1));\n-\twhile (RTA_OK(rta, len)) {\n-\t\ttype = rta->rta_type;\n-\t\tif (type <= max && !tb[type])\n-\t\t\ttb[type] = rta;\n-\t\trta = RTA_NEXT(rta, len);\n-\t}\n-}\n-\n-/**\n- * Extract flow counters from flower action.\n- *\n- * @param rta\n- *   flower action stats properties in the Netlink message received.\n- * @param rta_type\n- *   The backward sequence of rta_types, as written in the attribute table,\n- *   we need to traverse in order to get to the requested object.\n- * @param idx\n- *   Current location in rta_type table.\n- * @param[out] data\n- *   data holding the count statistics of the rte_flow retrieved from\n- *   the message.\n- *\n- * @return\n- *   0 if data was found and retrieved, -1 otherwise.\n- */\n-static int\n-flow_tcf_nl_action_stats_parse_and_get(struct rtattr *rta,\n-\t\t\t\t       uint16_t rta_type[], int idx,\n-\t\t\t\t       struct gnet_stats_basic *data)\n-{\n-\tint tca_stats_max = flow_tcf_arr_val_max(rta_type, idx,\n-\t\t\t\t\t\t TCA_STATS_BASIC);\n-\tstruct rtattr *tbs[tca_stats_max + 1];\n-\n-\tif (rta == NULL || idx < 0)\n-\t\treturn -1;\n-\tflow_tcf_nl_parse_rtattr(tbs, tca_stats_max,\n-\t\t\t\t RTA_DATA(rta), RTA_PAYLOAD(rta));\n-\tswitch (rta_type[idx]) {\n-\tcase TCA_STATS_BASIC:\n-\t\tif (tbs[TCA_STATS_BASIC]) {\n-\t\t\tmemcpy(data, RTA_DATA(tbs[TCA_STATS_BASIC]),\n-\t\t\t       RTE_MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]),\n-\t\t\t       sizeof(*data)));\n-\t\t\treturn 0;\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn -1;\n-}\n-\n-/**\n- * Parse flower single action retrieving the requested action attribute,\n- * if found.\n- *\n- * @param arg\n- *   flower action properties in the Netlink message received.\n- * @param rta_type\n- *   The backward sequence of rta_types, as written in the attribute table,\n- *   we need to traverse in order to get to the requested object.\n- * @param idx\n- *   Current location in rta_type table.\n- * @param[out] data\n- *   Count statistics retrieved from the message query.\n- *\n- * @return\n- *   0 if data was found and retrieved, -1 otherwise.\n- */\n-static int\n-flow_tcf_nl_parse_one_action_and_get(struct rtattr *arg,\n-\t\t\t\t     uint16_t rta_type[], int idx, void *data)\n-{\n-\tint tca_act_max = flow_tcf_arr_val_max(rta_type, idx, TCA_ACT_STATS);\n-\tstruct rtattr *tb[tca_act_max + 1];\n-\n-\tif (arg == NULL || idx < 0)\n-\t\treturn -1;\n-\tflow_tcf_nl_parse_rtattr(tb, tca_act_max,\n-\t\t\t\t RTA_DATA(arg), RTA_PAYLOAD(arg));\n-\tif (tb[TCA_ACT_KIND] == NULL)\n-\t\treturn -1;\n-\tswitch (rta_type[idx]) {\n-\tcase TCA_ACT_STATS:\n-\t\tif (tb[TCA_ACT_STATS])\n-\t\t\treturn flow_tcf_nl_action_stats_parse_and_get\n-\t\t\t\t\t(tb[TCA_ACT_STATS],\n-\t\t\t\t\t rta_type, --idx,\n-\t\t\t\t\t (struct gnet_stats_basic *)data);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn -1;\n-}\n-\n-/**\n- * Parse flower action section in the message retrieving the requested\n- * attribute from the first action that provides it.\n- *\n- * @param opt\n- *   flower section in the Netlink message received.\n- * @param rta_type\n- *   The backward sequence of rta_types, as written in the attribute table,\n- *   we need to traverse in order to get to the requested object.\n- * @param idx\n- *   Current location in rta_type table.\n- * @param[out] data\n- *   data retrieved from the message query.\n- *\n- * @return\n- *   0 if data was found and retrieved, -1 otherwise.\n- */\n-static int\n-flow_tcf_nl_action_parse_and_get(struct rtattr *arg,\n-\t\t\t\t uint16_t rta_type[], int idx, void *data)\n-{\n-\tstruct rtattr *tb[TCA_ACT_MAX_PRIO + 1];\n-\tint i;\n-\n-\tif (arg == NULL || idx < 0)\n-\t\treturn -1;\n-\tflow_tcf_nl_parse_rtattr(tb, TCA_ACT_MAX_PRIO,\n-\t\t\t\t RTA_DATA(arg), RTA_PAYLOAD(arg));\n-\tswitch (rta_type[idx]) {\n-\t/*\n-\t * flow counters are stored in the actions defined by the flow\n-\t * and not in the flow itself, therefore we need to traverse the\n-\t * flower chain of actions in search for them.\n-\t *\n-\t * Note that the index is not decremented here.\n-\t */\n-\tcase TCA_ACT_STATS:\n-\t\tfor (i = 0; i <= TCA_ACT_MAX_PRIO; i++) {\n-\t\t\tif (tb[i] &&\n-\t\t\t!flow_tcf_nl_parse_one_action_and_get(tb[i],\n-\t\t\t\t\t\t\t      rta_type,\n-\t\t\t\t\t\t\t      idx, data))\n-\t\t\t\treturn 0;\n-\t\t}\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn -1;\n-}\n-\n-/**\n- * Parse flower classifier options in the message, retrieving the requested\n- * attribute if found.\n- *\n- * @param opt\n- *   flower section in the Netlink message received.\n- * @param rta_type\n- *   The backward sequence of rta_types, as written in the attribute table,\n- *   we need to traverse in order to get to the requested object.\n- * @param idx\n- *   Current location in rta_type table.\n- * @param[out] data\n- *   data retrieved from the message query.\n- *\n- * @return\n- *   0 if data was found and retrieved, -1 otherwise.\n- */\n-static int\n-flow_tcf_nl_opts_parse_and_get(struct rtattr *opt,\n-\t\t\t       uint16_t rta_type[], int idx, void *data)\n-{\n-\tint tca_flower_max = flow_tcf_arr_val_max(rta_type, idx,\n-\t\t\t\t\t\t  TCA_FLOWER_ACT);\n-\tstruct rtattr *tb[tca_flower_max + 1];\n-\n-\tif (!opt || idx < 0)\n-\t\treturn -1;\n-\tflow_tcf_nl_parse_rtattr(tb, tca_flower_max,\n-\t\t\t\t RTA_DATA(opt), RTA_PAYLOAD(opt));\n-\tswitch (rta_type[idx]) {\n-\tcase TCA_FLOWER_ACT:\n-\t\tif (tb[TCA_FLOWER_ACT])\n-\t\t\treturn flow_tcf_nl_action_parse_and_get\n-\t\t\t\t\t\t\t(tb[TCA_FLOWER_ACT],\n-\t\t\t\t\t\t\t rta_type, --idx, data);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn -1;\n-}\n-\n-/**\n- * Parse Netlink reply on filter query, retrieving the flow counters.\n- *\n- * @param nlh\n- *   Message received from Netlink.\n- * @param rta_type\n- *   The backward sequence of rta_types, as written in the attribute table,\n- *   we need to traverse in order to get to the requested object.\n- * @param idx\n- *   Current location in rta_type table.\n- * @param[out] data\n- *   data retrieved from the message query.\n- *\n- * @return\n- *   0 if data was found and retrieved, -1 otherwise.\n- */\n-static int\n-flow_tcf_nl_filter_parse_and_get(struct nlmsghdr *cnlh,\n-\t\t\t\t uint16_t rta_type[], int idx, void *data)\n-{\n-\tstruct nlmsghdr *nlh = cnlh;\n-\tstruct tcmsg *t = NLMSG_DATA(nlh);\n-\tint len = nlh->nlmsg_len;\n-\tint tca_max = flow_tcf_arr_val_max(rta_type, idx, TCA_OPTIONS);\n-\tstruct rtattr *tb[tca_max + 1];\n-\n-\tif (idx < 0)\n-\t\treturn -1;\n-\tif (nlh->nlmsg_type != RTM_NEWTFILTER &&\n-\t    nlh->nlmsg_type != RTM_GETTFILTER &&\n-\t    nlh->nlmsg_type != RTM_DELTFILTER)\n-\t\treturn -1;\n-\tlen -= NLMSG_LENGTH(sizeof(*t));\n-\tif (len < 0)\n-\t\treturn -1;\n-\tflow_tcf_nl_parse_rtattr(tb, tca_max, TCA_RTA(t), len);\n-\t/* Not a TC flower flow - bail out */\n-\tif (!tb[TCA_KIND] ||\n-\t    strcmp(RTA_DATA(tb[TCA_KIND]), \"flower\"))\n-\t\treturn -1;\n-\tswitch (rta_type[idx]) {\n-\tcase TCA_OPTIONS:\n-\t\tif (tb[TCA_OPTIONS])\n-\t\t\treturn flow_tcf_nl_opts_parse_and_get(tb[TCA_OPTIONS],\n-\t\t\t\t\t\t\t      rta_type,\n-\t\t\t\t\t\t\t      --idx, data);\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-\treturn -1;\n-}\n-\n-/**\n- * A callback to parse Netlink reply on TC flower query.\n- *\n- * @param nlh\n- *   Message received from Netlink.\n- * @param[out] data\n- *   Pointer to data area to be filled by the parsing routine.\n- *   assumed to be a pointer to struct flow_tcf_stats_basic.\n- *\n- * @return\n- *   MNL_CB_OK value.\n- */\n-static int\n-flow_tcf_nl_message_get_stats_basic(const struct nlmsghdr *nlh, void *data)\n-{\n-\t/*\n-\t * The backward sequence of rta_types to pass in order to get\n-\t *  to the counters.\n-\t */\n-\tuint16_t rta_type[] = { TCA_STATS_BASIC, TCA_ACT_STATS,\n-\t\t\t\tTCA_FLOWER_ACT, TCA_OPTIONS };\n-\tstruct flow_tcf_stats_basic *sb_data = data;\n-\tunion {\n-\t\tconst struct nlmsghdr *c;\n-\t\tstruct nlmsghdr *nc;\n-\t} tnlh = { .c = nlh };\n-\n-\tif (!flow_tcf_nl_filter_parse_and_get(tnlh.nc, rta_type,\n-\t\t\t\t\t      RTE_DIM(rta_type) - 1,\n-\t\t\t\t\t      (void *)&sb_data->counters))\n-\t\tsb_data->valid = true;\n-\treturn MNL_CB_OK;\n-}\n-\n-/**\n- * Query a TC flower rule for its statistics via netlink.\n- *\n- * @param[in] dev\n- *   Pointer to Ethernet device.\n- * @param[in] flow\n- *   Pointer to the sub flow.\n- * @param[out] data\n- *   data retrieved by the query.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-flow_tcf_query_count(struct rte_eth_dev *dev,\n-\t\t\t  struct rte_flow *flow,\n-\t\t\t  void *data,\n-\t\t\t  struct rte_flow_error *error)\n-{\n-\tstruct flow_tcf_stats_basic sb_data;\n-\tstruct rte_flow_query_count *qc = data;\n-\tstruct mlx5_priv *priv = dev->data->dev_private;\n-\tstruct mlx5_flow_tcf_context *ctx = priv->tcf_context;\n-\tstruct mnl_socket *nl = ctx->nl;\n-\tstruct mlx5_flow *dev_flow;\n-\tstruct nlmsghdr *nlh;\n-\tuint32_t seq = priv->tcf_context->seq++;\n-\tssize_t ret;\n-\tassert(qc);\n-\n-\tmemset(&sb_data, 0, sizeof(sb_data));\n-\tdev_flow = LIST_FIRST(&flow->dev_flows);\n-\t/* E-Switch flow can't be expanded. */\n-\tassert(!LIST_NEXT(dev_flow, next));\n-\tif (!dev_flow->flow->counter)\n-\t\tgoto notsup_exit;\n-\tnlh = dev_flow->tcf.nlh;\n-\tnlh->nlmsg_type = RTM_GETTFILTER;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ECHO;\n-\tnlh->nlmsg_seq = seq;\n-\tif (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) == -1)\n-\t\tgoto error_exit;\n-\tdo {\n-\t\tret = mnl_socket_recvfrom(nl, ctx->buf, ctx->buf_size);\n-\t\tif (ret <= 0)\n-\t\t\tbreak;\n-\t\tret = mnl_cb_run(ctx->buf, ret, seq,\n-\t\t\t\t mnl_socket_get_portid(nl),\n-\t\t\t\t flow_tcf_nl_message_get_stats_basic,\n-\t\t\t\t (void *)&sb_data);\n-\t} while (ret > 0);\n-\t/* Return the delta from last reset. */\n-\tif (sb_data.valid) {\n-\t\t/* Return the delta from last reset. */\n-\t\tqc->hits_set = 1;\n-\t\tqc->bytes_set = 1;\n-\t\tqc->hits = sb_data.counters.packets - flow->counter->hits;\n-\t\tqc->bytes = sb_data.counters.bytes - flow->counter->bytes;\n-\t\tif (qc->reset) {\n-\t\t\tflow->counter->hits = sb_data.counters.packets;\n-\t\t\tflow->counter->bytes = sb_data.counters.bytes;\n-\t\t}\n-\t\treturn 0;\n-\t}\n-\treturn rte_flow_error_set(error, EINVAL,\n-\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t\t  NULL,\n-\t\t\t\t  \"flow does not have counter\");\n-error_exit:\n-\treturn rte_flow_error_set\n-\t\t\t(error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t NULL, \"netlink: failed to read flow rule counters\");\n-notsup_exit:\n-\treturn rte_flow_error_set\n-\t\t\t(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,\n-\t\t\t NULL, \"counters are not available.\");\n-}\n-\n-/**\n- * Query a flow.\n- *\n- * @see rte_flow_query()\n- * @see rte_flow_ops\n- */\n-static int\n-flow_tcf_query(struct rte_eth_dev *dev,\n-\t       struct rte_flow *flow,\n-\t       const struct rte_flow_action *actions,\n-\t       void *data,\n-\t       struct rte_flow_error *error)\n-{\n-\tint ret = -EINVAL;\n-\n-\tfor (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {\n-\t\tswitch (actions->type) {\n-\t\tcase RTE_FLOW_ACTION_TYPE_VOID:\n-\t\t\tbreak;\n-\t\tcase RTE_FLOW_ACTION_TYPE_COUNT:\n-\t\t\tret = flow_tcf_query_count(dev, flow, data, error);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\treturn rte_flow_error_set(error, ENOTSUP,\n-\t\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_ACTION,\n-\t\t\t\t\t\t  actions,\n-\t\t\t\t\t\t  \"action not supported\");\n-\t\t}\n-\t}\n-\treturn ret;\n-}\n-\n-const struct mlx5_flow_driver_ops mlx5_flow_tcf_drv_ops = {\n-\t.validate = flow_tcf_validate,\n-\t.prepare = flow_tcf_prepare,\n-\t.translate = flow_tcf_translate,\n-\t.apply = flow_tcf_apply,\n-\t.remove = flow_tcf_remove,\n-\t.destroy = flow_tcf_destroy,\n-\t.query = flow_tcf_query,\n-};\n-\n-/**\n- * Create and configure a libmnl socket for Netlink flow rules.\n- *\n- * @return\n- *   A valid libmnl socket object pointer on success, NULL otherwise and\n- *   rte_errno is set.\n- */\n-static struct mnl_socket *\n-flow_tcf_mnl_socket_create(void)\n-{\n-\tstruct mnl_socket *nl = mnl_socket_open(NETLINK_ROUTE);\n-\n-\tif (nl) {\n-\t\tmnl_socket_setsockopt(nl, NETLINK_CAP_ACK, &(int){ 1 },\n-\t\t\t\t      sizeof(int));\n-\t\tif (!mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID))\n-\t\t\treturn nl;\n-\t}\n-\trte_errno = errno;\n-\tif (nl)\n-\t\tmnl_socket_close(nl);\n-\treturn NULL;\n-}\n-\n-/**\n- * Destroy a libmnl socket.\n- *\n- * @param nl\n- *   Libmnl socket of the @p NETLINK_ROUTE kind.\n- */\n-static void\n-flow_tcf_mnl_socket_destroy(struct mnl_socket *nl)\n-{\n-\tif (nl)\n-\t\tmnl_socket_close(nl);\n-}\n-\n-/**\n- * Initialize ingress qdisc of a given network interface.\n- *\n- * @param ctx\n- *   Pointer to tc-flower context to use.\n- * @param ifindex\n- *   Index of network interface to initialize.\n- * @param[out] error\n- *   Perform verbose error reporting if not NULL.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_flow_tcf_init(struct mlx5_flow_tcf_context *ctx,\n-\t\t   unsigned int ifindex, struct rte_flow_error *error)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct tcmsg *tcm;\n-\talignas(struct nlmsghdr)\n-\tuint8_t buf[mnl_nlmsg_size(sizeof(*tcm)) +\n-\t\t    SZ_NLATTR_STRZ_OF(\"ingress\") +\n-\t\t    MNL_BUF_EXTRA_SPACE];\n-\n-\t/* Destroy existing ingress qdisc and everything attached to it. */\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = RTM_DELQDISC;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST;\n-\ttcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm));\n-\ttcm->tcm_family = AF_UNSPEC;\n-\ttcm->tcm_ifindex = ifindex;\n-\ttcm->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0);\n-\ttcm->tcm_parent = TC_H_INGRESS;\n-\tassert(sizeof(buf) >= nlh->nlmsg_len);\n-\t/* Ignore errors when qdisc is already absent. */\n-\tif (flow_tcf_nl_ack(ctx, nlh, NULL, NULL) &&\n-\t    rte_errno != EINVAL && rte_errno != ENOENT)\n-\t\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t\t  \"netlink: failed to remove ingress\"\n-\t\t\t\t\t  \" qdisc\");\n-\t/* Create fresh ingress qdisc. */\n-\tnlh = mnl_nlmsg_put_header(buf);\n-\tnlh->nlmsg_type = RTM_NEWQDISC;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;\n-\ttcm = mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm));\n-\ttcm->tcm_family = AF_UNSPEC;\n-\ttcm->tcm_ifindex = ifindex;\n-\ttcm->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0);\n-\ttcm->tcm_parent = TC_H_INGRESS;\n-\tmnl_attr_put_strz_check(nlh, sizeof(buf), TCA_KIND, \"ingress\");\n-\tassert(sizeof(buf) >= nlh->nlmsg_len);\n-\tif (flow_tcf_nl_ack(ctx, nlh, NULL, NULL))\n-\t\treturn rte_flow_error_set(error, rte_errno,\n-\t\t\t\t\t  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,\n-\t\t\t\t\t  \"netlink: failed to create ingress\"\n-\t\t\t\t\t  \" qdisc\");\n-\treturn 0;\n-}\n-\n-/**\n- * Create libmnl context for Netlink flow rules.\n- *\n- * @return\n- *   A valid libmnl socket object pointer on success, NULL otherwise and\n- *   rte_errno is set.\n- */\n-struct mlx5_flow_tcf_context *\n-mlx5_flow_tcf_context_create(void)\n-{\n-\tstruct mlx5_flow_tcf_context *ctx = rte_zmalloc(__func__,\n-\t\t\t\t\t\t\tsizeof(*ctx),\n-\t\t\t\t\t\t\tsizeof(uint32_t));\n-\tif (!ctx)\n-\t\tgoto error;\n-\tctx->nl = flow_tcf_mnl_socket_create();\n-\tif (!ctx->nl)\n-\t\tgoto error;\n-\tctx->buf_size = MNL_SOCKET_BUFFER_SIZE;\n-\tctx->buf = rte_zmalloc(__func__,\n-\t\t\t       ctx->buf_size, sizeof(uint32_t));\n-\tif (!ctx->buf)\n-\t\tgoto error;\n-\tctx->seq = random();\n-\treturn ctx;\n-error:\n-\tmlx5_flow_tcf_context_destroy(ctx);\n-\treturn NULL;\n-}\n-\n-/**\n- * Destroy a libmnl context.\n- *\n- * @param ctx\n- *   Libmnl socket of the @p NETLINK_ROUTE kind.\n- */\n-void\n-mlx5_flow_tcf_context_destroy(struct mlx5_flow_tcf_context *ctx)\n-{\n-\tif (!ctx)\n-\t\treturn;\n-\tflow_tcf_mnl_socket_destroy(ctx->nl);\n-\trte_free(ctx->buf);\n-\trte_free(ctx);\n-}\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 2b5696a..ad76b17 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -179,7 +179,7 @@ endif\n _LDLIBS-$(CONFIG_RTE_LIBRTE_LIO_PMD)        += -lrte_pmd_lio\n _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_MEMIF)      += -lrte_pmd_memif\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -lrte_pmd_mlx4\n-_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -lrte_pmd_mlx5 -lmnl\n+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -lrte_pmd_mlx5\n ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y)\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -ldl\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -ldl\n",
    "prefixes": [
        "v6",
        "2/2"
    ]
}