Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2229659/?format=api
{ "id": 2229659, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229659/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260428151926.3798626-3-i.maximets@ovn.org/", "project": { "id": 47, "url": "http://patchwork.ozlabs.org/api/1.1/projects/47/?format=api", "name": "Open vSwitch", "link_name": "openvswitch", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "git@github.com:openvswitch/ovs.git", "webscm_url": "https://github.com/openvswitch/ovs" }, "msgid": "<20260428151926.3798626-3-i.maximets@ovn.org>", "date": "2026-04-28T15:19:07", "name": "[ovs-dev,2/6] dpif-netdev: Remove deprecated AVX512-optimized packet parsers.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "00ad58bc33cb48e660e8f21e3ee3f1f8c7f8cb3c", "submitter": { "id": 76798, "url": "http://patchwork.ozlabs.org/api/1.1/people/76798/?format=api", "name": "Ilya Maximets", "email": "i.maximets@ovn.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260428151926.3798626-3-i.maximets@ovn.org/mbox/", "series": [ { "id": 501877, "url": "http://patchwork.ozlabs.org/api/1.1/series/501877/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=501877", "date": "2026-04-28T15:19:05", "name": "dpif-netdev: Remove deprecated AVX512-based optimizations.", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/501877/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2229659/comments/", "check": "success", "checks": "http://patchwork.ozlabs.org/api/patches/2229659/checks/", "tags": {}, "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "ovs-dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp4.osuosl.org;\n dmarc=none (p=none dis=none) header.from=ovn.org" ], "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4kdN2VBnz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 01:20:08 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 28D8260F60;\n\tTue, 28 Apr 2026 15:20:06 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id h3WKbXxy-fk2; Tue, 28 Apr 2026 15:19:59 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 25A0260E23;\n\tTue, 28 Apr 2026 15:19:59 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id B571CC0591;\n\tTue, 28 Apr 2026 15:19:58 +0000 (UTC)", "from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 4E2DBC04FA\n for <ovs-dev@openvswitch.org>; Tue, 28 Apr 2026 15:19:57 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id B942141429\n for <ovs-dev@openvswitch.org>; Tue, 28 Apr 2026 15:19:48 +0000 (UTC)", "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id EnN_N3eerBBV for <ovs-dev@openvswitch.org>;\n Tue, 28 Apr 2026 15:19:45 +0000 (UTC)", "from mail-wm1-f68.google.com (mail-wm1-f68.google.com\n [209.85.128.68])\n by smtp4.osuosl.org (Postfix) with ESMTPS id 9248441301\n for <ovs-dev@openvswitch.org>; Tue, 28 Apr 2026 15:19:44 +0000 (UTC)", "by mail-wm1-f68.google.com with SMTP id\n 5b1f17b1804b1-488a88aeec9so142005395e9.2\n for <ovs-dev@openvswitch.org>; Tue, 28 Apr 2026 08:19:44 -0700 (PDT)", "from im-t490s.redhat.com (89-24-34-32.nat.epc.tmcz.cz.\n [89.24.34.32])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-4463fa89038sm7080967f8f.26.2026.04.28.08.19.39\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 28 Apr 2026 08:19:39 -0700 (PDT)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp3.osuosl.org 25A0260E23", "OpenDKIM Filter v2.11.0 smtp4.osuosl.org 9248441301" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=209.85.128.68;\n helo=mail-wm1-f68.google.com; envelope-from=i.maximets.ovn@gmail.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp4.osuosl.org 9248441301", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777389582; x=1777994382;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=d2Bm0PwKFlp8qJQjDgqdXnmztRFSGjwWKkDBBoGm/6w=;\n b=CKu/hCiUiW7HyerFXl76fAaRMKn9lF5fjOvCTuYI8KCITjQiPl1SyxRlotkbB9yBuv\n xYFgdskqNRlxlsl8AIM+CVzMbhgmmgA+Qadxs/5FYViHRTxAL/w0jGGgacJ46r1V8muk\n 8NKB9tiGp+ay/CF0Dkk3IoTUMwRk0lYhky+7hBaykfoy2U42Bj6Rhu0Fkpq285ApcAP7\n /ommLIwjng0mNWmXP9i3lLOMF1ssL66ihQE41CIqYHPBNSA9aMMFVS5aKOxy3qlc373d\n SrqVAsRniuNwbKv94fPdllpzqjZegOuMjLqa9MAeMPpVsHlGKkVFnUffFeME6ZMZnJNv\n 2XGg==", "X-Gm-Message-State": "AOJu0YzD/iyPcANfAXRM6SZeoc+M9a4/ItgfU5zeE4QBqqS2r89X9eQI\n U6pT/5ZyJGTBimstTMyzEcXsMilZVriNHVY3xXT+rmfuH3/OHCDPGLqfXblO3Yumn6E=", "X-Gm-Gg": "AeBDieuVNByzVTWZx59psCDp2gb1sjlLiG9mFDGEiZJ0JNcqLuOb/fiVHJJxG0Jlvvw\n b1bXZn+m/+K3sOkszPgdmpQuOCMUOd0FGpPdwV4CeqBTDofAx0wEZoOqc/5KMaiXvnPAe5eyYx5\n LntTU6LrjlEh0dDLBJLswEWdzvB04y/NQr+o2nO+bFGEMehoiXG94Hg8aFup67CZByaNhgF2obF\n sqI7OpnIU0YBOPQD4rMxgL6fyIZNl7KovgBUY5eoxpNe8/Kbz0inMhTja8cbxijAt4YG6kduE/8\n Us3AMdp3RTFuLz5lIMDtNpwx3G+9sT2+WlNhxbGt9LdM6x3mxXdjhiOQAOrfLbBKdD44W78X8TA\n 7Rllwz5tcbKCHOeXLP/yWziXhKij6OtosoXOHbRiKcBJRlHoWTCQV4657i7Rf4gy2ENqDcu4v8q\n 3yeJNSvNyIDEf6U2LRu1U4f+hw0wadhGPptAojKsUjwM7ykCHwfLSN6Bv3UojnLXbD+JQ=", "X-Received": "by 2002:a05:600c:81ca:b0:488:7ff6:1f75 with SMTP id\n 5b1f17b1804b1-48a77b1468dmr57043675e9.21.1777389580258;\n Tue, 28 Apr 2026 08:19:40 -0700 (PDT)", "From": "Ilya Maximets <i.maximets@ovn.org>", "To": "ovs-dev@openvswitch.org", "Cc": "Ilya Maximets <i.maximets@ovn.org>", "Date": "Tue, 28 Apr 2026 17:19:07 +0200", "Message-ID": "<20260428151926.3798626-3-i.maximets@ovn.org>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260428151926.3798626-1-i.maximets@ovn.org>", "References": "<20260428151926.3798626-1-i.maximets@ovn.org>", "MIME-Version": "1.0", "Subject": "[ovs-dev] [PATCH 2/6] dpif-netdev: Remove deprecated\n AVX512-optimized packet parsers.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "This functionality was deprecated in 3.7 due to lack of use, testing\nand maintenance. It's time to remove it.\n\nThis removes the only couple of tests that require scapy, so it is\nno longer one of the test dependencies.\n\nSigned-off-by: Ilya Maximets <i.maximets@ovn.org>\n---\n Documentation/topics/dpdk/bridge.rst | 61 --\n Documentation/topics/testing.rst | 21 +-\n NEWS | 4 +-\n acinclude.m4 | 22 -\n configure.ac | 1 -\n lib/automake.mk | 4 -\n lib/dpif-netdev-avx512.c | 33 +-\n lib/dpif-netdev-extract-avx512.c | 1066 --------------------------\n lib/dpif-netdev-extract-study.c | 153 ----\n lib/dpif-netdev-perf.c | 3 -\n lib/dpif-netdev-perf.h | 1 -\n lib/dpif-netdev-private-extract.c | 471 ------------\n lib/dpif-netdev-private-extract.h | 241 ------\n lib/dpif-netdev-private-thread.h | 4 -\n lib/dpif-netdev-unixctl.man | 15 -\n lib/dpif-netdev.c | 237 +-----\n python/test_requirements.txt | 1 -\n tests/automake.mk | 1 -\n tests/dpif-netdev.at | 165 ----\n tests/genpkts.py | 84 --\n tests/pmd.at | 6 +-\n 21 files changed, 18 insertions(+), 2576 deletions(-)\n delete mode 100644 lib/dpif-netdev-extract-avx512.c\n delete mode 100644 lib/dpif-netdev-extract-study.c\n delete mode 100644 lib/dpif-netdev-private-extract.c\n delete mode 100644 lib/dpif-netdev-private-extract.h\n delete mode 100755 tests/genpkts.py", "diff": "diff --git a/Documentation/topics/dpdk/bridge.rst b/Documentation/topics/dpdk/bridge.rst\nindex b4c583df9..3c7896f28 100644\n--- a/Documentation/topics/dpdk/bridge.rst\n+++ b/Documentation/topics/dpdk/bridge.rst\n@@ -285,64 +285,3 @@ name::\n \n $ ovs-appctl dpif-netdev/dpif-impl-set dpif_scalar\n DPIF implementation set to dpif_scalar.\n-\n-Packet parsing performance\n---------------------------\n-\n-.. note::\n-\n- The AVX512 Packet parsing performance feature is deprecated and will be\n- removed in a future release.\n-\n-Open vSwitch performs parsing of the raw packets and extracts the important\n-header information into a compressed miniflow structure. This miniflow is\n-composed of bits and blocks where the bits signify which blocks are set or have\n-values where as the blocks hold the metadata, ip, udp, vlan, etc. These values\n-are used by the datapath for switching decisions later.\n-\n-Most modern CPUs have some SIMD (single instruction, multiple data)\n-capabilities. These SIMD instructions are able to process a vector rather than\n-act on one variable. OVS provides multiple implementations of packet parsing\n-functions. This allows the user to take advantage of SIMD instructions like\n-AVX512 to gain additional performance.\n-\n-A list of implementations can be obtained by the following command. The\n-command also shows whether the CPU supports each implementation::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-get\n- Available Optimized Miniflow Extracts:\n- autovalidator (available: True, pmds: none)\n- scalar (available: True, pmds: 1,15)\n- study (available: True, pmds: none)\n-\n-An implementation can be selected manually by the following command::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-set [-pmd core_id] name \\\n- [study_cnt]\n-\n-The above command has two optional parameters: ``study_cnt`` and ``core_id``.\n-The ``core_id`` sets a particular packet parsing function to a specific\n-PMD thread on the core. The third parameter ``study_cnt``, which is specific\n-to ``study`` and ignored by other implementations, means how many packets\n-are needed to choose the best implementation.\n-\n-Also user can select the ``study`` implementation which studies the traffic for\n-a specific number of packets by applying all available implementations of\n-the packet parsing function and then chooses the one with the most optimal\n-result for that traffic pattern. The user can optionally provide a packet\n-count ``study_cnt`` parameter which is the minimum number of packets that OVS\n-must study before choosing an optimal implementation. If no packet count is\n-provided, then the default value, ``128`` is chosen.\n-\n-``study`` can be selected with packet count by the following command::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-set study 1024\n-\n-``study`` can be selected with packet count and explicit PMD selection by the\n-following command::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 study 1024\n-\n-``scalar`` can be selected on core ``3`` by the following command::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 scalar\ndiff --git a/Documentation/topics/testing.rst b/Documentation/topics/testing.rst\nindex 9531e1e14..6c835c663 100644\n--- a/Documentation/topics/testing.rst\n+++ b/Documentation/topics/testing.rst\n@@ -333,12 +333,11 @@ Userspace datapath: Testing and Validation of CPU-specific Optimizations\n The AVX512 CPU-specific optimization features are deprecated and will be\n removed in a future release.\n \n-As multiple versions of the datapath classifier, packet parsing functions\n-can co-exist, each with different CPU ISA optimizations, it is important to\n-validate that they all give the exact same results. To easily test all the\n-implementations, an ``autovalidator`` implementation of them exists. This\n-implementation runs all other available implementations, and verifies that\n-the results are identical.\n+As multiple versions of the datapath classifier each with different CPU ISA\n+optimizations, it is important to validate that they all give the exact same\n+results. To easily test all the implementations, an ``autovalidator``\n+implementation of them exists. This implementation runs all other available\n+implementations, and verifies that the results are identical.\n \n Running the OVS unit tests with the autovalidator enabled ensures all\n implementations provide the same results. Note that the performance of the\n@@ -350,26 +349,20 @@ command::\n \n $ ovs-appctl dpif-netdev/subtable-lookup-prio-set autovalidator 7\n \n-To set the autovalidator for the packet parser, use this command::\n-\n- $ ovs-appctl dpif-netdev/miniflow-parser-set autovalidator\n-\n To run the OVS unit test suite with the autovalidator as the default\n implementation, it is required to recompile OVS. During the recompilation,\n the default priority of the `autovalidator` implementation is set to the\n maximum priority, ensuring every test will be run with every implementation::\n \n- $ ./configure --enable-autovalidator --enable-mfex-default-autovalidator\n+ $ ./configure --enable-autovalidator\n \n The following line should be seen in the configuration log when the above\n options are used::\n \n checking whether DPCLS Autovalidator is default implementation... yes\n- checking whether MFEX Autovalidator is default implementation... yes\n \n Compile OVS in debug mode to have `ovs_assert` statements error out if\n-there is a mismatch in the datapath classifier lookup or packet parser\n-implementations.\n+there is a mismatch in the datapath classifier lookup.\n \n Since the AVX512 implementation of the datapath interface is disabled by\n default, a compile time option is available in order to test it with the OVS\ndiff --git a/NEWS b/NEWS\nindex f1c5ba871..81be6dcd7 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -3,8 +3,10 @@ Post-v3.7.0\n - Userspace datapath:\n * ARP/ND lookups for native tunnel are now rate limited. The holdout\n timer can be configured with 'tnl/neigh/retrans_time'.\n- - The following deprecated AVX512-specific features are now removed:\n+ - The following deprecated AVX512-specific features of the userspace\n+ datapath are now removed:\n * AVX512-optimized action handling.\n+ * AVX512-optimized packet parsing (miniflow extraction).\n \n \n v3.7.0 - 16 Feb 2026\ndiff --git a/acinclude.m4 b/acinclude.m4\nindex 8dda44262..43c8e9d03 100644\n--- a/acinclude.m4\n+++ b/acinclude.m4\n@@ -14,27 +14,6 @@\n # See the License for the specific language governing permissions and\n # limitations under the License.\n \n-dnl Set OVS MFEX Autovalidator as default miniflow extract at compile time?\n-dnl This enables automatically running all unit tests with all MFEX\n-dnl implementations.\n-AC_DEFUN([OVS_CHECK_MFEX_AUTOVALIDATOR], [\n- AC_ARG_ENABLE([mfex-default-autovalidator],\n- [AS_HELP_STRING([--enable-mfex-default-autovalidator],\n- [Enable MFEX autovalidator as default\n- miniflow_extract implementation.])],\n- [autovalidator=yes],[autovalidator=no])\n- AC_MSG_CHECKING([whether MFEX Autovalidator is default implementation])\n- if test \"$autovalidator\" != yes; then\n- AC_MSG_RESULT([no])\n- else\n- AC_DEFINE([MFEX_AUTOVALIDATOR_DEFAULT], [1],\n- [Autovalidator for miniflow_extract is a default implementation.])\n- AC_MSG_RESULT([yes])\n- AC_MSG_WARN(\n- [Explicit AVX512 feature support will be deprecated in the next release.])\n- fi\n-])\n-\n dnl Set OVS DPCLS Autovalidator as default subtable search at compile time?\n dnl This enables automatically running all unit tests with all DPCLS\n dnl implementations.\n@@ -85,7 +64,6 @@ AC_DEFUN([OVS_CHECK_AVX512], [\n OVS_CONDITIONAL_CC_OPTION_DEFINE([-mavx512f], [HAVE_AVX512F])\n OVS_CONDITIONAL_CC_OPTION_DEFINE([-mavx512bw], [HAVE_AVX512BW])\n OVS_CONDITIONAL_CC_OPTION_DEFINE([-mavx512vl], [HAVE_AVX512VL])\n- OVS_CONDITIONAL_CC_OPTION_DEFINE([-mavx512vbmi], [HAVE_AVX512VBMI])\n OVS_CHECK_AVX512VPOPCNTDQ\n ])\n \ndiff --git a/configure.ac b/configure.ac\nindex 0bc6f31ed..e57778d8d 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -192,7 +192,6 @@ OVS_ENABLE_SPARSE\n OVS_CTAGS_IDENTIFIERS\n OVS_CHECK_DPCLS_AUTOVALIDATOR\n OVS_CHECK_DPIF_AVX512_DEFAULT\n-OVS_CHECK_MFEX_AUTOVALIDATOR\n OVS_CHECK_AVX512\n \n AC_ARG_VAR(KARCH, [Kernel Architecture String])\ndiff --git a/lib/automake.mk b/lib/automake.mk\nindex f07265261..e482a92a1 100644\n--- a/lib/automake.mk\n+++ b/lib/automake.mk\n@@ -42,7 +42,6 @@ lib_libopenvswitchavx512_la_CFLAGS += \\\n \t-mavx512bw \\\n \t-mavx512vl\n lib_libopenvswitchavx512_la_SOURCES += \\\n-\tlib/dpif-netdev-extract-avx512.c \\\n \tlib/dpif-netdev-lookup-avx512-gather.c\n endif # HAVE_AVX512VL\n endif # HAVE_AVX512BW\n@@ -120,7 +119,6 @@ lib_libopenvswitch_la_SOURCES = \\\n \tlib/dp-packet-gso.c \\\n \tlib/dp-packet-gso.h \\\n \tlib/dpdk.h \\\n-\tlib/dpif-netdev-extract-study.c \\\n \tlib/dpif-netdev-lookup.h \\\n \tlib/dpif-netdev-lookup.c \\\n \tlib/dpif-netdev-lookup-autovalidator.c \\\n@@ -132,8 +130,6 @@ lib_libopenvswitch_la_SOURCES = \\\n \tlib/dpif-netdev-private-dpcls.h \\\n \tlib/dpif-netdev-private-dpif.c \\\n \tlib/dpif-netdev-private-dpif.h \\\n-\tlib/dpif-netdev-private-extract.c \\\n-\tlib/dpif-netdev-private-extract.h \\\n \tlib/dpif-netdev-private-flow.h \\\n \tlib/dpif-netdev-private-thread.h \\\n \tlib/dpif-netdev-private.h \\\ndiff --git a/lib/dpif-netdev-avx512.c b/lib/dpif-netdev-avx512.c\nindex 22cfad647..b530889d6 100644\n--- a/lib/dpif-netdev-avx512.c\n+++ b/lib/dpif-netdev-avx512.c\n@@ -182,14 +182,6 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,\n goto action_stage;\n }\n \n- /* Do a batch minfilow extract into keys. */\n- uint32_t mf_mask = 0;\n- miniflow_extract_func mfex_func;\n- atomic_read_relaxed(&pmd->miniflow_extract_opt, &mfex_func);\n- if (mfex_func) {\n- mf_mask = mfex_func(packets, keys, batch_size, in_port, pmd);\n- }\n-\n uint32_t iter = lookup_pkts_bitmask;\n while (iter) {\n uint32_t i = raw_ctz(iter);\n@@ -209,12 +201,6 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,\n struct dp_netdev_flow *f = NULL;\n struct netdev_flow_key *key = &keys[i];\n \n- /* Check the minfiflow mask to see if the packet was correctly\n- * classifed by vector mfex else do a scalar miniflow extract\n- * for that packet.\n- */\n- bool mfex_hit = !!(mf_mask & (UINT32_C(1) << i));\n-\n /* Check for a partial hardware offload match. */\n if (hwol_enabled) {\n if (OVS_UNLIKELY(dp_netdev_hw_flow(pmd, packet, &f))) {\n@@ -224,14 +210,8 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,\n }\n if (f) {\n rules[i] = &f->cr;\n- /* If AVX512 MFEX already classified the packet, use it. */\n- if (mfex_hit) {\n- pkt_meta[i].tcp_flags = miniflow_get_tcp_flags(&key->mf);\n- } else {\n- pkt_meta[i].tcp_flags = parse_tcp_flags(packet,\n- NULL, NULL, NULL);\n- }\n-\n+ pkt_meta[i].tcp_flags = parse_tcp_flags(packet,\n+ NULL, NULL, NULL);\n pkt_meta[i].bytes = dp_packet_size(packet);\n phwol_hits++;\n hwol_emc_smc_hitmask |= (UINT32_C(1) << i);\n@@ -239,10 +219,8 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,\n }\n }\n \n- if (!mfex_hit) {\n- /* Do a scalar miniflow extract into keys. */\n- miniflow_extract(packet, &key->mf);\n- }\n+ /* Do a scalar miniflow extract into keys. */\n+ miniflow_extract(packet, &key->mf);\n \n /* Cache TCP and byte values for all packets. */\n pkt_meta[i].bytes = dp_packet_size(packet);\n@@ -342,10 +320,7 @@ dp_netdev_input_outer_avx512(struct dp_netdev_pmd_thread *pmd,\n }\n \n /* At this point we don't return error anymore, so commit stats here. */\n- uint32_t mfex_hit_cnt = __builtin_popcountll(mf_mask);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_PHWOL_HIT, phwol_hits);\n- pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MFEX_OPT_HIT,\n- mfex_hit_cnt);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_EXACT_HIT, emc_hits);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SMC_HIT, smc_hits);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MASKED_HIT,\ndiff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c\ndeleted file mode 100644\nindex 8741bbf29..000000000\n--- a/lib/dpif-netdev-extract-avx512.c\n+++ /dev/null\n@@ -1,1066 +0,0 @@\n-/*\n- * Copyright (c) 2021 Intel.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * AVX512 Miniflow Extract.\n- *\n- * This file contains optimized implementations of miniflow_extract()\n- * for specific common traffic patterns. The optimizations allow for\n- * quick probing of a specific packet type, and if a match with a specific\n- * type is found, a shuffle like procedure builds up the required miniflow.\n- *\n- * Process\n- * ---------\n- *\n- * The procedure is to classify the packet based on the traffic type\n- * using predifined bit-masks and arrage the packet header data using shuffle\n- * instructions to a pre-defined place as required by the miniflow.\n- * This elimates the if-else ladder to identify the packet data and add data\n- * as per protocol which is present.\n- */\n-\n-#ifdef __x86_64__\n-/* Sparse cannot handle the AVX512 instructions. */\n-#if !defined(__CHECKER__)\n-\n-#include <config.h>\n-#include <errno.h>\n-#include <immintrin.h>\n-#include <stdint.h>\n-#include <string.h>\n-\n-#include \"flow.h\"\n-\n-#include \"dpif-netdev-private-dpcls.h\"\n-#include \"dpif-netdev-private-extract.h\"\n-#include \"dpif-netdev-private-flow.h\"\n-#include \"dp-packet.h\"\n-#include \"packets.h\"\n-\n-/* AVX512-BW level permutex2var_epi8 emulation. */\n-static inline __m512i\n-_mm512_maskz_permutex2var_epi8_skx(__mmask64 k_mask,\n- __m512i v_data_0,\n- __m512i v_shuf_idxs,\n- __m512i v_data_1)\n-{\n- /* Manipulate shuffle indexes for u16 size. */\n- __mmask64 k_mask_odd_lanes = 0xAAAAAAAAAAAAAAAA;\n- /* Clear away ODD lane bytes. Cannot be done above due to no u8 shift. */\n- __m512i v_shuf_idx_evn = _mm512_mask_blend_epi8(k_mask_odd_lanes,\n- v_shuf_idxs,\n- _mm512_setzero_si512());\n- v_shuf_idx_evn = _mm512_srli_epi16(v_shuf_idx_evn, 1);\n-\n- __m512i v_shuf_idx_odd = _mm512_srli_epi16(v_shuf_idxs, 9);\n-\n- /* Shuffle each half at 16-bit width. */\n- __m512i v_shuf1 = _mm512_permutex2var_epi16(v_data_0, v_shuf_idx_evn,\n- v_data_1);\n- __m512i v_shuf2 = _mm512_permutex2var_epi16(v_data_0, v_shuf_idx_odd,\n- v_data_1);\n-\n- /* Find if the shuffle index was odd, via mask and compare. */\n- uint16_t index_odd_mask = 0x1;\n- const __m512i v_index_mask_u16 = _mm512_set1_epi16(index_odd_mask);\n-\n- /* EVEN lanes, find if u8 index was odd, result as u16 bitmask. */\n- __m512i v_idx_even_masked = _mm512_and_si512(v_shuf_idxs,\n- v_index_mask_u16);\n- __mmask32 evn_rotate_mask = _mm512_cmpeq_epi16_mask(v_idx_even_masked,\n- v_index_mask_u16);\n-\n- /* ODD lanes, find if u8 index was odd, result as u16 bitmask. */\n- __m512i v_shuf_idx_srli8 = _mm512_srli_epi16(v_shuf_idxs, 8);\n- __m512i v_idx_odd_masked = _mm512_and_si512(v_shuf_idx_srli8,\n- v_index_mask_u16);\n- __mmask32 odd_rotate_mask = _mm512_cmpeq_epi16_mask(v_idx_odd_masked,\n- v_index_mask_u16);\n- odd_rotate_mask = ~odd_rotate_mask;\n-\n- /* Rotate and blend results from each index. */\n- __m512i v_shuf_res_evn = _mm512_mask_srli_epi16(v_shuf1, evn_rotate_mask,\n- v_shuf1, 8);\n- __m512i v_shuf_res_odd = _mm512_mask_slli_epi16(v_shuf2, odd_rotate_mask,\n- v_shuf2, 8);\n-\n- /* If shuffle index was odd, blend shifted version. */\n- __m512i v_shuf_result = _mm512_mask_blend_epi8(k_mask_odd_lanes,\n- v_shuf_res_evn, v_shuf_res_odd);\n-\n- __m512i v_zeros = _mm512_setzero_si512();\n- __m512i v_result_kmskd = _mm512_mask_blend_epi8(k_mask, v_zeros,\n- v_shuf_result);\n-\n- return v_result_kmskd;\n-}\n-\n-/* Wrapper function to enable VBMI ISA required by the\n- * _mm512_maskz_permutexvar_epi8 intrinsic. */\n-#if HAVE_AVX512VBMI\n-static inline __m512i\n-__attribute__((__target__(\"avx512vbmi\")))\n-_mm512_maskz_permutexvar_epi8_wrap(__mmask64 kmask, __m512i idx, __m512i a)\n-{\n- return _mm512_maskz_permutexvar_epi8(kmask, idx, a);\n-}\n-#endif\n-\n-static inline __m512i\n-_mm512_maskz_permutexvar_epi8_selector(__mmask64 k_shuf, __m512i v_shuf,\n- __m512i v_pkt0,\n- const uint32_t use_vbmi OVS_UNUSED)\n-{\n- /* Permute the packet layout into miniflow blocks shape. */\n- __m512i v512_zeros = _mm512_setzero_si512();\n- __m512i v_blk0;\n-#if HAVE_AVX512VBMI\n-#if __GNUC__ >= 4\n- if (__builtin_constant_p(use_vbmi) && use_vbmi) {\n-#else\n- if (use_vbmi) {\n-#endif\n- /* As different AVX512 ISA levels have different implementations,\n- * this specializes on the use_vbmi attribute passed in.\n- */\n- v_blk0 = _mm512_maskz_permutexvar_epi8_wrap(k_shuf, v_shuf, v_pkt0);\n-\n- } else {\n- v_blk0 = _mm512_maskz_permutex2var_epi8_skx(k_shuf, v_pkt0, v_shuf,\n- v512_zeros);\n- }\n-#else\n- v_blk0 = _mm512_maskz_permutex2var_epi8_skx(k_shuf, v_pkt0, v_shuf,\n- v512_zeros);\n-#endif\n- return v_blk0;\n-}\n-\n-\n-/* This file contains optimized implementations of miniflow_extract()\n- * for specific common traffic patterns. The optimizations allow for\n- * quick probing of a specific packet type, and if a match with a specific\n- * type is found, a shuffle like procedure builds up the required miniflow.\n- *\n- * The functionality here can be easily auto-validated and tested against the\n- * scalar miniflow_extract() function. As such, manual review of the code by\n- * the community (although welcome) is not required. Confidence in the\n- * correctness of the code can be confirmed from the autovalidator results.\n- */\n-\n-/* Generator for EtherType masks and values. */\n-#define PATTERN_ETHERTYPE_GEN(type_b0, type_b1) \\\n- 0, 0, 0, 0, 0, 0, /* Ether MAC DST */ \\\n- 0, 0, 0, 0, 0, 0, /* Ether MAC SRC */ \\\n- type_b0, type_b1, /* EtherType */\n-\n-#define PATTERN_ETHERTYPE_MASK PATTERN_ETHERTYPE_GEN(0xFF, 0xFF)\n-#define PATTERN_ETHERTYPE_IPV4 PATTERN_ETHERTYPE_GEN(0x08, 0x00)\n-#define PATTERN_ETHERTYPE_DT1Q PATTERN_ETHERTYPE_GEN(0x81, 0x00)\n-#define PATTERN_ETHERTYPE_IPV6 PATTERN_ETHERTYPE_GEN(0x86, 0xDD)\n-\n-/* VLAN (Dot1Q) patterns and masks. */\n-#define PATTERN_DT1Q_MASK \\\n- 0x00, 0x00, 0xFF, 0xFF,\n-#define PATTERN_DT1Q_IPV4 \\\n- 0x00, 0x00, 0x08, 0x00,\n-\n-/* Generator for checking IPv4 ver, ihl, and proto */\n-#define PATTERN_IPV4_GEN(VER_IHL, FLAG_OFF_B0, FLAG_OFF_B1, PROTO) \\\n- VER_IHL, /* Version and IHL */ \\\n- 0, 0, 0, /* DSCP, ECN, Total Length */ \\\n- 0, 0, /* Identification */ \\\n- /* Flags/Fragment offset: don't match MoreFrag (MF) or FragOffset */ \\\n- FLAG_OFF_B0, FLAG_OFF_B1, \\\n- 0, /* TTL */ \\\n- PROTO, /* Protocol */ \\\n- 0, 0, /* Header checksum */ \\\n- 0, 0, 0, 0, /* Src IP */ \\\n- 0, 0, 0, 0, /* Dst IP */\n-\n-#define PATTERN_IPV4_MASK PATTERN_IPV4_GEN(0xFF, 0xBF, 0xFF, 0xFF)\n-#define PATTERN_IPV4_UDP PATTERN_IPV4_GEN(0x45, 0, 0, 0x11)\n-#define PATTERN_IPV4_TCP PATTERN_IPV4_GEN(0x45, 0, 0, 0x06)\n-#define PATTERN_IPV4_NVGRE PATTERN_IPV4_GEN(0x45, 0, 0, 0x2f)\n-\n-#define PATTERN_TCP_GEN(data_offset) \\\n- 0, 0, 0, 0, /* sport, dport */ \\\n- 0, 0, 0, 0, /* sequence number */ \\\n- 0, 0, 0, 0, /* ack number */ \\\n- data_offset, /* data offset: used to verify = 5, options not supported */\n-\n-#define PATTERN_TCP_MASK PATTERN_TCP_GEN(0xF0)\n-#define PATTERN_TCP PATTERN_TCP_GEN(0x50)\n-\n-#define NU 0\n-#define PATTERN_IPV4_UDP_SHUFFLE \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NU, NU, /* Ether */ \\\n- 26, 27, 28, 29, 30, 31, 32, 33, NU, NU, NU, NU, 20, 15, 22, 23, /* IPv4 */ \\\n- 34, 35, 36, 37, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* UDP */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused. */\n-\n-/* TCP shuffle: tcp_ctl bits require mask/processing, not included here. */\n-#define PATTERN_IPV4_TCP_SHUFFLE \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NU, NU, /* Ether */ \\\n- 26, 27, 28, 29, 30, 31, 32, 33, NU, NU, NU, NU, 20, 15, 22, 23, /* IPv4 */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, 34, 35, 36, 37, NU, NU, NU, NU, /* TCP */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused. */\n-\n-#define PATTERN_IPV4_NVGRE_SHUFFLE \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NU, NU, /* Ether */ \\\n- 26, 27, 28, 29, 30, 31, 32, 33, NU, NU, NU, NU, 20, 15, 22, 23, /* IPv4 */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */\\\n- NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */\n-\n-#define PATTERN_DT1Q_IPV4_UDP_SHUFFLE \\\n- /* Ether (2 blocks): Note that *VLAN* type is written here. */ \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 0, 0, \\\n- /* VLAN (1 block): Note that the *EtherHdr->Type* is written here. */ \\\n- 12, 13, 14, 15, 0, 0, 0, 0, \\\n- 30, 31, 32, 33, 34, 35, 36, 37, 0, 0, 0, 0, 24, 19, 26, 27, /* IPv4 */ \\\n- 38, 39, 40, 41, NU, NU, NU, NU, /* UDP */\n-\n-#define PATTERN_DT1Q_IPV4_TCP_SHUFFLE \\\n- /* Ether (2 blocks): Note that *VLAN* type is written here. */ \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 0, 0, \\\n- /* VLAN (1 block): Note that the *EtherHdr->Type* is written here. */ \\\n- 12, 13, 14, 15, 0, 0, 0, 0, \\\n- 30, 31, 32, 33, 34, 35, 36, 37, 0, 0, 0, 0, 24, 19, 26, 27, /* IPv4 */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, 38, 39, 40, 41, NU, NU, NU, NU, /* TCP */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, /* Unused. */\n-\n-/* Generator for checking IPv6 ver. */\n-#define PATTERN_IPV6_GEN(VER_TRC, PROTO) \\\n- VER_TRC, /* Version: 4bits and Traffic class: 4bits. */ \\\n- 0, 0, 0, /* Traffic class: 4bits and Flow Label: 24bits. */ \\\n- 0, 0, /* Payload length 16bits. */ \\\n- PROTO, 0, /* Next Header 8bits and Hop limit 8bits. */ \\\n- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Src IP: 128bits. */ \\\n- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dst IP: 128bits. */\n-\n-#define PATTERN_IPV6_MASK PATTERN_IPV6_GEN(0xF0, 0xFF)\n-#define PATTERN_IPV6_UDP PATTERN_IPV6_GEN(0x60, 0x11)\n-#define PATTERN_IPV6_TCP PATTERN_IPV6_GEN(0x60, 0x06)\n-\n-#define PATTERN_IPV6_SHUFFLE \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NU, NU, /* Ether */ \\\n- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, /* IPv6 */ \\\n- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, /* IPv6 */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */\n-\n-/* VLAN (Dot1Q) patterns and masks. */\n-#define PATTERN_DT1Q_MASK \\\n- 0x00, 0x00, 0xFF, 0xFF,\n-#define PATTERN_DT1Q_IPV6 \\\n- 0x00, 0x00, 0x86, 0xDD,\n-\n-#define PATTERN_DT1Q_IPV6_SHUFFLE \\\n- /* Ether (2 blocks): Note that *VLAN* type is written here. */ \\\n- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 0, 0, \\\n- /* VLAN (1 block): Note that the *EtherHdr->Type* is written here. */ \\\n- 12, 13, 14, 15, 0, 0, 0, 0, \\\n- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, /* IPv6 */ \\\n- 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, /* IPv6 */ \\\n- NU, NU, NU, NU, NU, NU, NU, NU, /* Unused */\n-\n-/* Generation of K-mask bitmask values, to zero out data in result. Note that\n- * these correspond 1:1 to the above \"*_SHUFFLE\" values, and bit used must be\n- * set in this K-mask, and \"NU\" values must be zero in the k-mask. Each mask\n- * defined here represents 2 blocks, so 16 bytes, so 4 characters (eg. 0xFFFF).\n- *\n- * Note the ULL suffix allows shifting by 32 or more without integer overflow.\n- */\n-#define KMASK_ETHER 0x1FFFULL\n-#define KMASK_DT1Q 0x0FULL\n-#define KMASK_IPV4 0xF0FFULL\n-#define KMASK_UDP 0x000FULL\n-#define KMASK_TCP 0x0F00ULL\n-#define KMASK_IPV6 0xFFFFULL\n-#define KMASK_ETHER_IPV6 0x3FFFULL\n-#define KMASK_DT1Q_IPV6 0xFF0FULL\n-#define KMASK_IPV6_NOHDR 0x00FFULL\n-\n-#define PATTERN_IPV4_KMASK \\\n- (KMASK_ETHER | (KMASK_IPV4 << 16))\n-\n-#define PATTERN_IPV4_UDP_KMASK \\\n- (KMASK_ETHER | (KMASK_IPV4 << 16) | (KMASK_UDP << 32))\n-\n-#define PATTERN_IPV4_TCP_KMASK \\\n- (KMASK_ETHER | (KMASK_IPV4 << 16) | (KMASK_TCP << 32))\n-\n-#define PATTERN_DT1Q_IPV4_UDP_KMASK \\\n- (KMASK_ETHER | (KMASK_DT1Q << 16) | (KMASK_IPV4 << 24) | (KMASK_UDP << 40))\n-\n-#define PATTERN_DT1Q_IPV4_TCP_KMASK \\\n- (KMASK_ETHER | (KMASK_DT1Q << 16) | (KMASK_IPV4 << 24) | (KMASK_TCP << 40))\n-\n-#define PATTERN_IPV6_KMASK \\\n- (KMASK_ETHER_IPV6 | (KMASK_IPV6 << 16) | (KMASK_IPV6 << 32))\n-\n-#define PATTERN_DT1Q_IPV6_KMASK \\\n- (KMASK_ETHER_IPV6 | (KMASK_DT1Q_IPV6 << 16) | (KMASK_IPV6 << 32) | \\\n- (KMASK_IPV6_NOHDR << 48))\n-\n-/* Miniflow Strip post-processing masks.\n- * This allows unsetting specific bits from the resulting miniflow. It is used\n- * for e.g. IPv4 where the \"DF\" bit is never pushed to the miniflow itself.\n- * The NC define is for \"No Change\", allowing the bits to pass through.\n- */\n-#define NC 0xFF\n-\n-#define PATTERN_STRIP_IPV4_MASK \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, 0xBF, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC\n-\n-#define PATTERN_STRIP_DOT1Q_IPV4_MASK \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, 0xBF, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC\n-\n-#define PKT_OFFSET_L2_PAD_SIZE (ETH_HEADER_LEN)\n-#define PKT_OFFSET_L3 (ETH_HEADER_LEN)\n-#define PKT_OFFSET_VLAN_L3 (ETH_HEADER_LEN + VLAN_HEADER_LEN)\n-#define PKT_OFFSET_IPV4_L4 (ETH_HEADER_LEN + IP_HEADER_LEN)\n-#define PKT_OFFSET_VLAN_IPV4_L4 (PKT_OFFSET_IPV4_L4 + VLAN_HEADER_LEN)\n-#define PKT_OFFSET_VLAN_IPV6_L4 (PKT_OFFSET_VLAN_L3 + IPV6_HEADER_LEN)\n-#define PKT_OFFSET_IPV6_L4 (PKT_OFFSET_L3 + IPV6_HEADER_LEN)\n-\n-#define PKT_MIN_ETH_IPV4 (ETH_HEADER_LEN + IP_HEADER_LEN)\n-#define PKT_MIN_ETH_IPV4_UDP (PKT_OFFSET_IPV4_L4 + UDP_HEADER_LEN)\n-#define PKT_MIN_ETH_VLAN_IPV4_UDP (PKT_OFFSET_VLAN_IPV4_L4 + UDP_HEADER_LEN)\n-#define PKT_MIN_ETH_IPV4_TCP (PKT_OFFSET_IPV4_L4 + TCP_HEADER_LEN)\n-#define PKT_MIN_ETH_VLAN_IPV4_TCP (PKT_OFFSET_VLAN_IPV4_L4 + TCP_HEADER_LEN)\n-#define PKT_MIN_ETH_IPV6_UDP (PKT_OFFSET_IPV6_L4 + UDP_HEADER_LEN)\n-#define PKT_MIN_ETH_VLAN_IPV6_UDP (PKT_OFFSET_VLAN_IPV6_L4 + UDP_HEADER_LEN)\n-#define PKT_MIN_ETH_IPV6_TCP (PKT_OFFSET_IPV6_L4 + TCP_HEADER_LEN)\n-#define PKT_MIN_ETH_VLAN_IPV6_TCP (PKT_OFFSET_VLAN_IPV6_L4 + TCP_HEADER_LEN)\n-\n-/* MF bits. */\n-#define MF_BIT(field) (MAP_1 << ((offsetof(struct flow, field) / 8) % \\\n- MAP_T_BITS))\n-#define MF_WORD(field, n_word) \\\n- (((MAP_1 << n_word) - 1) << ((offsetof(struct flow, field) / 8) % \\\n- MAP_T_BITS))\n-\n-#define MF_ETH (MF_BIT(dp_hash) | MF_BIT(in_port) | MF_BIT(packet_type)\\\n- | MF_BIT(dl_dst) | MF_BIT(dl_src)| MF_BIT(dl_type))\n-#define MF_ETH_VLAN (MF_ETH | MF_BIT(vlans))\n-\n-#define MF_IPV4 (MF_BIT(nw_src) | MF_BIT(ipv6_label))\n-#define MF_IPV4_UDP (MF_IPV4 | MF_BIT(tp_src) | MF_BIT(tp_dst))\n-#define MF_IPV4_TCP (MF_IPV4_UDP | MF_BIT(tcp_flags) | MF_BIT(arp_tha.ea[2]))\n-\n-#define MF_IPV6_UDP (MF_BIT(ipv6_label) | MF_WORD(ipv6_src, 2) | \\\n- MF_WORD(ipv6_dst, 2) | MF_BIT(tp_src) | MF_BIT(tp_dst))\n-#define MF_IPV6_TCP (MF_IPV6_UDP | MF_BIT(tcp_flags) | MF_BIT(arp_tha.ea[2]))\n-\n-#define PATTERN_STRIP_IPV6_MASK \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, \\\n- NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC\n-\n-/* This union allows initializing static data as u8, but easily loading it\n- * into AVX512 registers too. The union ensures proper alignment for the zmm.\n- */\n-union mfex_data {\n- uint8_t u8_data[64];\n- __m512i zmm;\n-};\n-\n-/* This structure represents a single traffic pattern. The AVX512 code to\n- * enable the specifics for each pattern is largely the same, so it is\n- * specialized to use the common profile data from here.\n- *\n- * Due to the nature of e.g. TCP flag handling, or VLAN CFI bit setting,\n- * some profiles require additional processing. This is handled by having\n- * all implementations call a post-process function, and specializing away\n- * the big switch() that handles all traffic types.\n- *\n- * This approach reduces AVX512 code-duplication for each traffic type.\n- */\n-struct mfex_profile {\n- /* Required for probing a packet with the mfex pattern. */\n- union mfex_data probe_mask;\n- union mfex_data probe_data;\n-\n- /* Required for reshaping packet into miniflow and post-processing it. */\n- union mfex_data store_shuf;\n- union mfex_data strip_mask;\n- __mmask64 store_kmsk;\n-\n- /* Constant data to set in mf.bits and dp_packet data on hit. */\n- uint64_t mf_bits[FLOWMAP_UNITS];\n- uint16_t dp_pkt_offs[4];\n- uint16_t dp_pkt_min_size;\n-};\n-\n-/* Ensure dp_pkt_offs[4] is the correct size as in struct dp_packet. */\n-BUILD_ASSERT_DECL((OFFSETOFEND(struct dp_packet, l4_ofs)\n- - offsetof(struct dp_packet, l2_pad_size)) ==\n- MEMBER_SIZEOF(struct mfex_profile, dp_pkt_offs));\n-\n-/* Ensure FLOWMAP_UNITS is 2 units, as the implementation assumes this. */\n-BUILD_ASSERT_DECL(FLOWMAP_UNITS == 2);\n-\n-/* Ensure the miniflow-struct ABI is the expected version. */\n-BUILD_ASSERT_DECL(FLOW_WC_SEQ == 43);\n-\n-/* If the above build assert happens, this means that you might need to make\n- * some modifications to the AVX512 miniflow extractor code. In general, the\n- * AVX512 flow extractor code uses hardcoded miniflow->map->bits which are\n- * defined into the mfex_profile structure as mf_bits. In addition to the\n- * hardcoded bits, it also has hardcoded offsets/masks that tell the AVX512\n- * code how to translate packet data in the required miniflow values. These\n- * are stored in the mfex_profile structure as store_shuf and store_kmsk.\n- * See the respective documentation on their usage.\n- *\n- * If you have made changes to the flow structure, but only additions, no\n- * re-arranging of the actual members, you might be good to go. To be 100%\n- * sure, if possible, run the AVX512 MFEX autovalidator tests on an AVX512\n- * enabled machine.\n- *\n- * If you did make changes to the order, you have to run the autovalidator\n- * tests on an AVX512 machine, and and in the case errors, the debug output\n- * will show what miniflow or dp_packet properties are not being correctly\n- * built from the input packet.\n- *\n- * In case your change increased the maximum size of the map, i.e.,\n- * FLOWMAP_UNITS, you need to study the code as it will need some rewriting.\n- *\n- * If you are not using the AVX512 MFEX implementation at all, i.e. keeping it\n- * to the default scalar implementation, see \"ovs-appctl\n- * dpif-netdev/miniflow-parser-get\", you could ignore this assert, and just\n- * just increase the FLOW_WC_SEQ number in the assert.\n- */\n-\n-enum MFEX_PROFILES {\n- PROFILE_ETH_IPV4_UDP,\n- PROFILE_ETH_IPV4_TCP,\n- PROFILE_ETH_VLAN_IPV4_UDP,\n- PROFILE_ETH_VLAN_IPV4_TCP,\n- PROFILE_ETH_IPV6_UDP,\n- PROFILE_ETH_IPV6_TCP,\n- PROFILE_ETH_VLAN_IPV6_TCP,\n- PROFILE_ETH_VLAN_IPV6_UDP,\n- PROFILE_ETH_IPV4_NVGRE,\n- PROFILE_COUNT,\n-};\n-\n-/* Static const instances of profiles. These are compile-time constants,\n- * and are specialized into individual miniflow-extract functions.\n- * NOTE: Order of the fields is significant, any change in the order must be\n- * reflected in miniflow_extract()!\n- */\n-static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =\n-{\n- [PROFILE_ETH_IPV4_UDP] = {\n- .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV4_MASK },\n- .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV4 PATTERN_IPV4_UDP},\n-\n- .store_shuf.u8_data = { PATTERN_IPV4_UDP_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV4_MASK },\n- .store_kmsk = PATTERN_IPV4_UDP_KMASK,\n-\n- .mf_bits = { MF_ETH, MF_IPV4_UDP},\n- .dp_pkt_offs = {\n- 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV4_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_IPV4_UDP,\n- },\n-\n- [PROFILE_ETH_IPV4_TCP] = {\n- .probe_mask.u8_data = {\n- PATTERN_ETHERTYPE_MASK\n- PATTERN_IPV4_MASK\n- PATTERN_TCP_MASK\n- },\n- .probe_data.u8_data = {\n- PATTERN_ETHERTYPE_IPV4\n- PATTERN_IPV4_TCP\n- PATTERN_TCP\n- },\n-\n- .store_shuf.u8_data = { PATTERN_IPV4_TCP_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV4_MASK },\n- .store_kmsk = PATTERN_IPV4_TCP_KMASK,\n-\n- .mf_bits = { MF_ETH, MF_IPV4_TCP},\n- .dp_pkt_offs = {\n- 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV4_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_IPV4_TCP,\n- },\n-\n- [PROFILE_ETH_VLAN_IPV4_UDP] = {\n- .probe_mask.u8_data = {\n- PATTERN_ETHERTYPE_MASK PATTERN_DT1Q_MASK PATTERN_IPV4_MASK\n- },\n- .probe_data.u8_data = {\n- PATTERN_ETHERTYPE_DT1Q PATTERN_DT1Q_IPV4 PATTERN_IPV4_UDP\n- },\n-\n- .store_shuf.u8_data = { PATTERN_DT1Q_IPV4_UDP_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_DOT1Q_IPV4_MASK },\n- .store_kmsk = PATTERN_DT1Q_IPV4_UDP_KMASK,\n-\n- .mf_bits = { MF_ETH_VLAN, MF_IPV4_UDP},\n- .dp_pkt_offs = {\n- PKT_OFFSET_L2_PAD_SIZE, UINT16_MAX, PKT_OFFSET_VLAN_L3,\n- PKT_OFFSET_VLAN_IPV4_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_VLAN_IPV4_UDP,\n- },\n-\n- [PROFILE_ETH_VLAN_IPV4_TCP] = {\n- .probe_mask.u8_data = {\n- PATTERN_ETHERTYPE_MASK\n- PATTERN_DT1Q_MASK\n- PATTERN_IPV4_MASK\n- PATTERN_TCP_MASK\n- },\n- .probe_data.u8_data = {\n- PATTERN_ETHERTYPE_DT1Q\n- PATTERN_DT1Q_IPV4\n- PATTERN_IPV4_TCP\n- PATTERN_TCP\n- },\n-\n- .store_shuf.u8_data = { PATTERN_DT1Q_IPV4_TCP_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_DOT1Q_IPV4_MASK },\n- .store_kmsk = PATTERN_DT1Q_IPV4_TCP_KMASK,\n-\n- .mf_bits = { MF_ETH_VLAN, MF_IPV4_TCP},\n- .dp_pkt_offs = {\n- PKT_OFFSET_L2_PAD_SIZE, UINT16_MAX, PKT_OFFSET_VLAN_L3,\n- PKT_OFFSET_VLAN_IPV4_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_VLAN_IPV4_TCP,\n- },\n-\n- [PROFILE_ETH_IPV6_UDP] = {\n- .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV6_MASK },\n- .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV6 PATTERN_IPV6_UDP },\n-\n- .store_shuf.u8_data = { PATTERN_IPV6_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV6_MASK },\n- .store_kmsk = PATTERN_IPV6_KMASK,\n-\n- .mf_bits = { MF_ETH, MF_IPV6_UDP},\n- .dp_pkt_offs = {\n- 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV6_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_IPV6_UDP,\n- },\n-\n- [PROFILE_ETH_IPV6_TCP] = {\n- .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV6_MASK },\n- .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV6 PATTERN_IPV6_TCP },\n-\n- .store_shuf.u8_data = { PATTERN_IPV6_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV6_MASK },\n- .store_kmsk = PATTERN_IPV6_KMASK,\n-\n- .mf_bits = { MF_ETH, MF_IPV6_TCP},\n- .dp_pkt_offs = {\n- 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV6_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_IPV6_TCP,\n- },\n-\n- [PROFILE_ETH_VLAN_IPV6_TCP] = {\n- .probe_mask.u8_data = {\n- PATTERN_ETHERTYPE_MASK PATTERN_DT1Q_MASK PATTERN_IPV6_MASK },\n- .probe_data.u8_data = {\n- PATTERN_ETHERTYPE_DT1Q PATTERN_DT1Q_IPV6 PATTERN_IPV6_TCP },\n-\n- .store_shuf.u8_data = { PATTERN_DT1Q_IPV6_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV6_MASK },\n- .store_kmsk = PATTERN_DT1Q_IPV6_KMASK,\n-\n- .mf_bits = { MF_ETH_VLAN, MF_IPV6_TCP},\n- .dp_pkt_offs = {\n- PKT_OFFSET_L2_PAD_SIZE, UINT16_MAX, PKT_OFFSET_VLAN_L3,\n- PKT_OFFSET_VLAN_IPV6_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_VLAN_IPV6_TCP,\n- },\n-\n- [PROFILE_ETH_VLAN_IPV6_UDP] = {\n- .probe_mask.u8_data = {\n- PATTERN_ETHERTYPE_MASK PATTERN_DT1Q_MASK PATTERN_IPV6_MASK },\n- .probe_data.u8_data = {\n- PATTERN_ETHERTYPE_DT1Q PATTERN_DT1Q_IPV6 PATTERN_IPV6_UDP },\n-\n- .store_shuf.u8_data = { PATTERN_DT1Q_IPV6_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV6_MASK },\n- .store_kmsk = PATTERN_DT1Q_IPV6_KMASK,\n-\n- .mf_bits = { MF_ETH_VLAN, MF_IPV6_UDP},\n- .dp_pkt_offs = {\n- PKT_OFFSET_L2_PAD_SIZE, UINT16_MAX, PKT_OFFSET_VLAN_L3,\n- PKT_OFFSET_VLAN_IPV6_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_VLAN_IPV6_UDP,\n- },\n-\n- [PROFILE_ETH_IPV4_NVGRE] = {\n- .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV4_MASK },\n- .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV4 PATTERN_IPV4_NVGRE},\n-\n- .store_shuf.u8_data = { PATTERN_IPV4_NVGRE_SHUFFLE },\n- .strip_mask.u8_data = { PATTERN_STRIP_IPV4_MASK },\n- .store_kmsk = PATTERN_IPV4_KMASK,\n-\n- .mf_bits = { MF_ETH, MF_IPV4},\n- .dp_pkt_offs = {\n- 0, UINT16_MAX, PKT_OFFSET_L3, PKT_OFFSET_IPV4_L4,\n- },\n- .dp_pkt_min_size = PKT_MIN_ETH_IPV4,\n- },\n-};\n-\n-/* IPv6 header helper function to fix TC, flow label and next header. */\n-static inline void ALWAYS_INLINE\n-mfex_handle_ipv6_hdr_block(const uint8_t *ipv6, uint64_t *block)\n-{\n- static const uint8_t data_shuf[16] = {\n- 0, 1, 2, 3, /* copy IPv6 label in place, it is masked later. */\n- 1, 0, /* Byte-swap TC fields for LE usage. */\n- 7, 6, /* Move TTL and next proto to MF required locations. */\n- };\n-\n- /* BE mask for IPv6 label, and mask to strip away unwanted TC bits. */\n- const uint64_t mask = 0xffff0f00 | (UINT64_MAX << 40);\n- uint64_t mask_data[2] = { mask, mask };\n-\n- /* Load constant data. Is lifted to occur 1x per burst, not per packet. */\n- __m128i ipv6_hdr = _mm_loadu_si128((void *) ipv6);\n- __m128i v_mask = _mm_loadu_si128((void *) mask_data);\n- __m128i v_shuf_mask = _mm_loadu_si128((void *) data_shuf);\n-\n- /* Shuffle data layout, shift 16-bits to get TC fixed, mask to cleanup. */\n- __m128i v_ipv6 = _mm_shuffle_epi8(ipv6_hdr, v_shuf_mask);\n- __m128i v_tc_shift = _mm_mask_slli_epi16(v_ipv6, 0b100, v_ipv6, 4);\n- __m128i v_ipv6_m = _mm_and_si128(v_tc_shift, v_mask);\n-\n- *block = _mm_extract_epi64(v_ipv6_m, 0);\n-}\n-\n-/* IPv6 Protocol specific helper functions, for handling L4 UDP/TCP. */\n-static inline void\n-mfex_handle_ipv6_l4(const uint8_t *ports, uint64_t *block)\n-{\n- memcpy(block, ports, sizeof(uint32_t));\n-}\n-\n-/* IPv6 specific helper functions, for calculating offsets/lengths. */\n-static int\n-mfex_ipv6_set_l2_pad_size(struct dp_packet *pkt,\n- struct ovs_16aligned_ip6_hdr *nh,\n- uint32_t len_from_ipv6,\n- uint32_t next_hdr_size)\n-{\n- /* Handle dynamic l2_pad_size. */\n- uint16_t p_len = ntohs(nh->ip6_ctlun.ip6_un1.ip6_un1_plen);\n-\n- /* Error if IP total length is greater than remaining packet size. */\n- bool err_ipv6_len_too_high = p_len + IPV6_HEADER_LEN > len_from_ipv6;\n-\n- /* Plen must be greater then the l4 packet header. */\n- bool err_ipv6_len_too_low = p_len < next_hdr_size;\n-\n- bool err_packet_size_low = len_from_ipv6 < sizeof *nh;\n-\n- /* Ensure the l2 pad size will not overflow. */\n- bool err_len_u16_overflow = (len_from_ipv6 - (p_len + IPV6_HEADER_LEN))\n- > UINT16_MAX;\n-\n- if (OVS_UNLIKELY(err_ipv6_len_too_high || err_ipv6_len_too_low ||\n- err_len_u16_overflow || err_packet_size_low)) {\n- return -1;\n- }\n- dp_packet_set_l2_pad_size(pkt, len_from_ipv6 - (p_len + IPV6_HEADER_LEN));\n- return 0;\n-}\n-\n-/* Protocol specific helper functions, for calculating offsets/lenghts. */\n-static int32_t\n-mfex_ipv4_set_l2_pad_size(struct dp_packet *pkt, struct ip_header *nh,\n- uint32_t len_from_ipv4, uint32_t next_proto_len)\n-{\n- /* Handle dynamic l2_pad_size; note that avx512 has already validated\n- * the IP->ihl field to be 5, so 20 bytes of IP header (no options).\n- */\n- uint16_t ip_tot_len = ntohs(nh->ip_tot_len);\n-\n- /* Error if IP total length is greater than remaining packet size. */\n- bool err_ip_tot_len_too_high = ip_tot_len > len_from_ipv4;\n-\n- /* Error if IP total length is less than the size of the IP header\n- * itself, and the size of the next-protocol this profile matches on.\n- */\n- bool err_ip_tot_len_too_low =\n- (IP_HEADER_LEN + next_proto_len) > ip_tot_len;\n-\n- /* Ensure the l2 pad size will not overflow. */\n- bool err_len_u16_overflow = (len_from_ipv4 - ip_tot_len) > UINT16_MAX;\n-\n- if (OVS_UNLIKELY(err_ip_tot_len_too_high || err_ip_tot_len_too_low ||\n- err_len_u16_overflow)) {\n- return -1;\n- }\n- dp_packet_set_l2_pad_size(pkt, len_from_ipv4 - ip_tot_len);\n- return 0;\n-}\n-\n-/* Fixup the VLAN CFI and PCP, reading the PCP from the input to this function,\n- * and storing the output CFI bit bitwise-OR-ed with the PCP to miniflow.\n- */\n-static void\n-mfex_vlan_pcp(const uint8_t vlan_pcp, uint64_t *block)\n-{\n- /* Bitwise-OR in the CFI flag, keeping other data the same. */\n- uint8_t *cfi_byte = (uint8_t *) block;\n- cfi_byte[2] = 0x10 | vlan_pcp;\n-}\n-\n-static void\n-mfex_handle_tcp_flags(const struct tcp_header *tcp, uint64_t *block)\n-{\n- uint16_t ctl = (OVS_FORCE uint16_t) TCP_FLAGS_BE16(tcp->tcp_ctl);\n- uint64_t ctl_u64 = ctl;\n- *block = ctl_u64 << 32;\n-}\n-\n-static int\n-mfex_check_tcp_data_offset(const struct tcp_header *tcp)\n-{\n- /* we dont support TCP options, offset must be 5. */\n- bool ret = TCP_OFFSET(tcp->tcp_ctl) == 5;\n- return ret;\n-}\n-\n-/* Generic loop to process any mfex profile. This code is specialized into\n- * multiple actual MFEX implementation functions. Its marked ALWAYS_INLINE\n- * to ensure the compiler specializes each instance. The code is marked \"hot\"\n- * to inform the compiler this is a hotspot in the program, encouraging\n- * inlining of callee functions such as the permute calls.\n- */\n-static inline uint32_t ALWAYS_INLINE\n-__attribute__ ((hot))\n-mfex_avx512_process(struct dp_packet_batch *packets,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size OVS_UNUSED,\n- odp_port_t in_port,\n- void *pmd_handle OVS_UNUSED,\n- const enum MFEX_PROFILES profile_id,\n- const uint32_t use_vbmi OVS_UNUSED)\n-{\n- uint32_t hitmask = 0;\n- struct dp_packet *packet;\n-\n- /* Here the profile to use is chosen by the variable used to specialize\n- * the function. This causes different MFEX traffic to be handled.\n- */\n- const struct mfex_profile *profile = &mfex_profiles[profile_id];\n-\n- /* Load profile constant data. */\n- __m512i v_vals = _mm512_loadu_si512(&profile->probe_data);\n- __m512i v_mask = _mm512_loadu_si512(&profile->probe_mask);\n- __m512i v_shuf = _mm512_loadu_si512(&profile->store_shuf);\n- __m512i v_strp = _mm512_loadu_si512(&profile->strip_mask);\n-\n- __mmask64 k_shuf = profile->store_kmsk;\n- __m128i v_bits = _mm_loadu_si128((void *) &profile->mf_bits);\n- uint16_t dp_pkt_min_size = profile->dp_pkt_min_size;\n-\n- __m128i v_zeros = _mm_setzero_si128();\n- __m128i v_blocks01 = _mm_insert_epi32(v_zeros, odp_to_u32(in_port), 1);\n-\n- DP_PACKET_BATCH_FOR_EACH (i, packet, packets) {\n- /* If the packet is smaller than the probe size, skip it. */\n- const uint32_t size = dp_packet_size(packet);\n- if (size < dp_pkt_min_size) {\n- continue;\n- }\n-\n- /* Load packet data and probe with AVX512 mask & compare. */\n- const uint8_t *pkt = dp_packet_data(packet);\n- __m512i v_pkt0;\n- if (size >= 64) {\n- v_pkt0 = _mm512_loadu_si512(pkt);\n- } else {\n- uint64_t load_kmask = (1ULL << size) - 1;\n- v_pkt0 = _mm512_maskz_loadu_epi8(load_kmask, pkt);\n- }\n-\n- __m512i v_pkt0_masked = _mm512_and_si512(v_pkt0, v_mask);\n- __mmask64 k_cmp = _mm512_cmpeq_epi8_mask(v_pkt0_masked, v_vals);\n- if (OVS_UNLIKELY(k_cmp != UINT64_MAX)) {\n- continue;\n- }\n-\n- /* Copy known dp packet offsets to the dp_packet instance. */\n- memcpy(&packet->l2_pad_size, &profile->dp_pkt_offs,\n- sizeof(uint16_t) * 4);\n-\n- /* Store known miniflow bits and first two blocks. */\n- struct miniflow *mf = &keys[i].mf;\n- uint64_t *bits = (void *) &mf->map.bits[0];\n- uint64_t *blocks = miniflow_values(mf);\n- _mm_storeu_si128((void *) bits, v_bits);\n- _mm_storeu_si128((void *) blocks, v_blocks01);\n-\n- __m512i v_blk0 = _mm512_maskz_permutexvar_epi8_selector(k_shuf, v_shuf,\n- v_pkt0,\n- use_vbmi);\n-\n- __m512i v_blk0_strip = _mm512_and_si512(v_blk0, v_strp);\n- _mm512_storeu_si512(&blocks[2], v_blk0_strip);\n-\n- /* Perform \"post-processing\" per profile, handling details not easily\n- * handled in the above generic AVX512 code. Examples include TCP flag\n- * parsing, adding the VLAN CFI bit, and handling IPv4 fragments.\n- */\n- switch (profile_id) {\n- case PROFILE_COUNT:\n- ovs_assert(0); /* avoid compiler warning on missing ENUM */\n- break;\n-\n- case PROFILE_ETH_VLAN_IPV4_TCP: {\n- mfex_vlan_pcp(pkt[14], &keys[i].buf[4]);\n-\n- uint32_t size_from_ipv4 = size - VLAN_ETH_HEADER_LEN;\n- struct ip_header *nh = (void *)&pkt[VLAN_ETH_HEADER_LEN];\n- if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,\n- TCP_HEADER_LEN)) {\n- continue;\n- }\n-\n- /* Process TCP flags, and store to blocks. */\n- const struct tcp_header *tcp = (void *)&pkt[38];\n- mfex_handle_tcp_flags(tcp, &blocks[7]);\n- dp_packet_update_rss_hash_ipv4_tcp_udp(packet);\n- dp_packet_l4_proto_set_tcp(packet);\n- } break;\n-\n- case PROFILE_ETH_VLAN_IPV4_UDP: {\n- mfex_vlan_pcp(pkt[14], &keys[i].buf[4]);\n-\n- uint32_t size_from_ipv4 = size - VLAN_ETH_HEADER_LEN;\n- struct ip_header *nh = (void *)&pkt[VLAN_ETH_HEADER_LEN];\n- if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,\n- UDP_HEADER_LEN)) {\n- continue;\n- }\n- dp_packet_update_rss_hash_ipv4_tcp_udp(packet);\n- dp_packet_l4_proto_set_udp(packet);\n- } break;\n-\n- case PROFILE_ETH_IPV4_TCP: {\n- /* Process TCP flags, and store to blocks. */\n- const struct tcp_header *tcp = (void *)&pkt[34];\n- mfex_handle_tcp_flags(tcp, &blocks[6]);\n-\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv4 = size - sizeof(struct eth_header);\n- struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)];\n- if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,\n- TCP_HEADER_LEN)) {\n- continue;\n- }\n- dp_packet_update_rss_hash_ipv4_tcp_udp(packet);\n- dp_packet_l4_proto_set_tcp(packet);\n- } break;\n-\n- case PROFILE_ETH_IPV4_UDP: {\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv4 = size - sizeof(struct eth_header);\n- struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)];\n- if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,\n- UDP_HEADER_LEN)) {\n- continue;\n- }\n- dp_packet_update_rss_hash_ipv4_tcp_udp(packet);\n- dp_packet_l4_proto_set_udp(packet);\n- } break;\n-\n- case PROFILE_ETH_IPV6_UDP: {\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv6 = size - sizeof(struct eth_header);\n- struct ovs_16aligned_ip6_hdr *nh = (void *)&pkt[sizeof\n- (struct eth_header)];\n- if (mfex_ipv6_set_l2_pad_size(packet, nh, size_from_ipv6,\n- UDP_HEADER_LEN)) {\n- continue;\n- }\n-\n- /* Process IPv6 header for TC, flow Label and next header. */\n- mfex_handle_ipv6_hdr_block(&pkt[ETH_HEADER_LEN], &blocks[8]);\n-\n- /* Process UDP header. */\n- mfex_handle_ipv6_l4((void *)&pkt[54], &blocks[9]);\n- dp_packet_update_rss_hash_ipv6_tcp_udp(packet);\n- dp_packet_l4_proto_set_udp(packet);\n- } break;\n-\n- case PROFILE_ETH_IPV6_TCP: {\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv6 = size - sizeof(struct eth_header);\n- struct ovs_16aligned_ip6_hdr *nh = (void *)&pkt[sizeof\n- (struct eth_header)];\n- if (mfex_ipv6_set_l2_pad_size(packet, nh, size_from_ipv6,\n- TCP_HEADER_LEN)) {\n- continue;\n- }\n-\n- /* Process IPv6 header for TC, flow Label and next header. */\n- mfex_handle_ipv6_hdr_block(&pkt[ETH_HEADER_LEN], &blocks[8]);\n-\n- /* Process TCP header. */\n- mfex_handle_ipv6_l4((void *)&pkt[54], &blocks[10]);\n- const struct tcp_header *tcp = (void *)&pkt[54];\n- if (!mfex_check_tcp_data_offset(tcp)) {\n- continue;\n- }\n- mfex_handle_tcp_flags(tcp, &blocks[9]);\n- dp_packet_update_rss_hash_ipv6_tcp_udp(packet);\n- dp_packet_l4_proto_set_tcp(packet);\n- } break;\n-\n- case PROFILE_ETH_VLAN_IPV6_TCP: {\n- mfex_vlan_pcp(pkt[14], &keys[i].buf[4]);\n-\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv6 = size - VLAN_ETH_HEADER_LEN;\n- struct ovs_16aligned_ip6_hdr *nh = (void *)&pkt\n- [VLAN_ETH_HEADER_LEN];\n- if (mfex_ipv6_set_l2_pad_size(packet, nh, size_from_ipv6,\n- TCP_HEADER_LEN)) {\n- continue;\n- }\n-\n- /* Process IPv6 header for TC, flow Label and next header. */\n- mfex_handle_ipv6_hdr_block(&pkt[VLAN_ETH_HEADER_LEN],\n- &blocks[9]);\n-\n- /* Process TCP header. */\n- mfex_handle_ipv6_l4((void *)&pkt[58], &blocks[11]);\n- const struct tcp_header *tcp = (void *)&pkt[58];\n- if (!mfex_check_tcp_data_offset(tcp)) {\n- continue;\n- }\n- mfex_handle_tcp_flags(tcp, &blocks[10]);\n- dp_packet_update_rss_hash_ipv6_tcp_udp(packet);\n- dp_packet_l4_proto_set_tcp(packet);\n- } break;\n-\n- case PROFILE_ETH_VLAN_IPV6_UDP: {\n- mfex_vlan_pcp(pkt[14], &keys[i].buf[4]);\n-\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv6 = size - VLAN_ETH_HEADER_LEN;\n- struct ovs_16aligned_ip6_hdr *nh = (void *)&pkt\n- [VLAN_ETH_HEADER_LEN];\n- if (mfex_ipv6_set_l2_pad_size(packet, nh, size_from_ipv6,\n- UDP_HEADER_LEN)) {\n- continue;\n- }\n-\n- /* Process IPv6 header for TC, flow Label and next header. */\n- mfex_handle_ipv6_hdr_block(&pkt[VLAN_ETH_HEADER_LEN],\n- &blocks[9]);\n-\n- /* Process UDP header. */\n- mfex_handle_ipv6_l4((void *)&pkt[58], &blocks[10]);\n- dp_packet_update_rss_hash_ipv6_tcp_udp(packet);\n- dp_packet_l4_proto_set_udp(packet);\n- } break;\n-\n- case PROFILE_ETH_IPV4_NVGRE: {\n- /* Handle dynamic l2_pad_size. */\n- uint32_t size_from_ipv4 = size - sizeof(struct eth_header);\n- struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)];\n- if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4, 0)) {\n- continue;\n- }\n- dp_packet_update_rss_hash_ipv4(packet);\n- dp_packet_l4_proto_set_udp(packet);\n- } break;\n-\n- default:\n- break;\n- };\n-\n- /* This packet has its miniflow created, add to hitmask. */\n- hitmask |= UINT32_C(1) << i;\n- }\n-\n- return hitmask;\n-}\n-\n-\n-#if HAVE_AVX512VBMI\n-#define VBMI_MFEX_FUNC(name, profile) \\\n-uint32_t \\\n-__attribute__((__target__(\"avx512vbmi\"))) \\\n-mfex_avx512_vbmi_##name(struct dp_packet_batch *packets, \\\n- struct netdev_flow_key *keys, uint32_t keys_size,\\\n- odp_port_t in_port, struct dp_netdev_pmd_thread \\\n- *pmd_handle) \\\n-{ \\\n- return mfex_avx512_process(packets, keys, keys_size, in_port, \\\n- pmd_handle, profile, 1); \\\n-}\n-#else\n-#define VBMI_MFEX_FUNC(name, profile)\n-#endif\n-\n-#define BASIC_MFEX_FUNC(name, profile) \\\n-uint32_t \\\n-mfex_avx512_##name(struct dp_packet_batch *packets, \\\n- struct netdev_flow_key *keys, uint32_t keys_size, \\\n- odp_port_t in_port, struct dp_netdev_pmd_thread \\\n- *pmd_handle) \\\n-{ \\\n- return mfex_avx512_process(packets, keys, keys_size, in_port, \\\n- pmd_handle, profile, 0); \\\n-}\n-\n-#define DECLARE_MFEX_FUNC(name, profile) \\\n-VBMI_MFEX_FUNC(name, profile) \\\n-BASIC_MFEX_FUNC(name, profile) \\\n-\n-/* Each profile gets a single declare here, which specializes the function\n- * as required.\n- */\n-DECLARE_MFEX_FUNC(ip_udp, PROFILE_ETH_IPV4_UDP)\n-DECLARE_MFEX_FUNC(ip_tcp, PROFILE_ETH_IPV4_TCP)\n-DECLARE_MFEX_FUNC(dot1q_ip_udp, PROFILE_ETH_VLAN_IPV4_UDP)\n-DECLARE_MFEX_FUNC(dot1q_ip_tcp, PROFILE_ETH_VLAN_IPV4_TCP)\n-DECLARE_MFEX_FUNC(ipv6_udp, PROFILE_ETH_IPV6_UDP)\n-DECLARE_MFEX_FUNC(ipv6_tcp, PROFILE_ETH_IPV6_TCP)\n-DECLARE_MFEX_FUNC(dot1q_ipv6_tcp, PROFILE_ETH_VLAN_IPV6_TCP)\n-DECLARE_MFEX_FUNC(dot1q_ipv6_udp, PROFILE_ETH_VLAN_IPV6_UDP)\n-DECLARE_MFEX_FUNC(ip_nvgre, PROFILE_ETH_IPV4_NVGRE)\n-\n-#endif /* __CHECKER__ */\n-#endif /* __x86_64__ */\ndiff --git a/lib/dpif-netdev-extract-study.c b/lib/dpif-netdev-extract-study.c\ndeleted file mode 100644\nindex 69077c844..000000000\n--- a/lib/dpif-netdev-extract-study.c\n+++ /dev/null\n@@ -1,153 +0,0 @@\n-/*\n- * Copyright (c) 2021 Intel.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include <config.h>\n-#include <errno.h>\n-#include <stdint.h>\n-#include <string.h>\n-\n-#include \"dpif-netdev-private-thread.h\"\n-#include \"openvswitch/vlog.h\"\n-#include \"ovs-thread.h\"\n-\n-VLOG_DEFINE_THIS_MODULE(dpif_mfex_extract_study);\n-\n-static atomic_uint32_t mfex_study_pkts_count = MFEX_MAX_PKT_COUNT;\n-\n-/* Struct to hold miniflow study stats. */\n-struct study_stats {\n- uint32_t pkt_count;\n- uint32_t impl_hitcount[MFEX_IMPL_MAX];\n-};\n-\n-/* Define per thread data to hold the study stats. */\n-DEFINE_PER_THREAD_MALLOCED_DATA(struct study_stats *, study_stats);\n-\n-/* Allocate per thread PMD pointer space for study_stats. */\n-static inline struct study_stats *\n-mfex_study_get_study_stats_ptr(void)\n-{\n- struct study_stats *stats = study_stats_get();\n- if (OVS_UNLIKELY(!stats)) {\n- stats = xzalloc(sizeof *stats);\n- study_stats_set_unsafe(stats);\n- }\n- return stats;\n-}\n-\n-int\n-mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count, const char *name)\n-{\n- struct dpif_miniflow_extract_impl *miniflow_funcs;\n- miniflow_funcs = dpif_mfex_impl_info_get();\n-\n- /* If the packet count is set and implementation called is study then\n- * set packet counter to requested number else return -EINVAL.\n- */\n- if ((strcmp(miniflow_funcs[MFEX_IMPL_STUDY].name, name) == 0) &&\n- (pkt_cmp_count != 0)) {\n-\n- atomic_store_relaxed(&mfex_study_pkts_count, pkt_cmp_count);\n- return 0;\n- }\n-\n- return -EINVAL;\n-}\n-\n-uint32_t\n-mfex_study_traffic(struct dp_packet_batch *packets,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size, odp_port_t in_port,\n- struct dp_netdev_pmd_thread *pmd_handle)\n-{\n- uint32_t hitmask = 0;\n- uint32_t mask = 0;\n- struct dp_netdev_pmd_thread *pmd = pmd_handle;\n- struct dpif_miniflow_extract_impl *miniflow_funcs;\n- struct study_stats *stats = mfex_study_get_study_stats_ptr();\n- miniflow_funcs = dpif_mfex_impl_info_get();\n-\n- /* Run traffic optimized miniflow_extract to collect the hitmask\n- * to be compared after certain packets have been hit to choose\n- * the best miniflow_extract version for that traffic.\n- */\n- for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {\n- if (!miniflow_funcs[i].available) {\n- continue;\n- }\n-\n- hitmask = miniflow_funcs[i].extract_func(packets, keys, keys_size,\n- in_port, pmd_handle);\n- stats->impl_hitcount[i] += count_1bits(hitmask);\n-\n- /* If traffic is not classified then we dont overwrite the keys\n- * array in minfiflow implementations so its safe to create a\n- * mask for all those packets whose miniflow have been created.\n- */\n- mask |= hitmask;\n- }\n-\n- stats->pkt_count += dp_packet_batch_size(packets);\n-\n- /* Choose the best implementation after a minimum packets have been\n- * processed.\n- */\n- uint32_t study_cnt_pkts;\n- atomic_read_relaxed(&mfex_study_pkts_count, &study_cnt_pkts);\n-\n- if (stats->pkt_count >= study_cnt_pkts) {\n- uint32_t best_func_index = MFEX_IMPL_START_IDX;\n- uint32_t max_hits = 0;\n- for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {\n- if (stats->impl_hitcount[i] > max_hits) {\n- max_hits = stats->impl_hitcount[i];\n- best_func_index = i;\n- }\n- }\n-\n- /* If 50% of the packets hit, enable the function. */\n- if (max_hits >= (mfex_study_pkts_count / 2)) {\n- atomic_store_relaxed(&pmd->miniflow_extract_opt,\n- miniflow_funcs[best_func_index].extract_func);\n- VLOG_INFO(\"MFEX study chose impl %s: (hits %u/%u pkts)\",\n- miniflow_funcs[best_func_index].name, max_hits,\n- stats->pkt_count);\n- } else {\n- /* Set the implementation to null for default miniflow. */\n- atomic_store_relaxed(&pmd->miniflow_extract_opt,\n- miniflow_funcs[MFEX_IMPL_SCALAR].extract_func);\n- VLOG_INFO(\"Not enough packets matched (%u/%u), disabling\"\n- \" optimized MFEX.\", max_hits, stats->pkt_count);\n- }\n-\n- /* In debug mode show stats for all the counters. */\n- if (VLOG_IS_DBG_ENABLED()) {\n-\n- for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {\n- VLOG_DBG(\"MFEX study results for implementation %s:\"\n- \" (hits %u/%u pkts)\", miniflow_funcs[i].name,\n- stats->impl_hitcount[i], stats->pkt_count);\n- }\n- }\n-\n- /* Reset stats so that study function can be called again\n- * for next traffic type and optimal function ptr can be\n- * chosen.\n- */\n- memset(stats, 0, sizeof(struct study_stats));\n- }\n- return mask;\n-}\ndiff --git a/lib/dpif-netdev-perf.c b/lib/dpif-netdev-perf.c\nindex 1cd4ee084..33db6acb7 100644\n--- a/lib/dpif-netdev-perf.c\n+++ b/lib/dpif-netdev-perf.c\n@@ -257,7 +257,6 @@ pmd_perf_format_overall_stats(struct ds *str, struct pmd_perf_stats *s,\n \" Rx packets: %12\"PRIu64\" (%.0f Kpps, %.0f cycles/pkt)\\n\"\n \" Datapath passes: %12\"PRIu64\" (%.2f passes/pkt)\\n\"\n \" - PHWOL hits: %12\"PRIu64\" (%5.1f %%)\\n\"\n- \" - MFEX Opt hits: %12\"PRIu64\" (%5.1f %%)\\n\"\n \" - Simple Match hits:%12\"PRIu64\" (%5.1f %%)\\n\"\n \" - EMC hits: %12\"PRIu64\" (%5.1f %%)\\n\"\n \" - SMC hits: %12\"PRIu64\" (%5.1f %%)\\n\"\n@@ -270,8 +269,6 @@ pmd_perf_format_overall_stats(struct ds *str, struct pmd_perf_stats *s,\n passes, 1.0 * passes / rx_packets,\n stats[PMD_STAT_PHWOL_HIT],\n 100.0 * stats[PMD_STAT_PHWOL_HIT] / passes,\n- stats[PMD_STAT_MFEX_OPT_HIT],\n- 100.0 * stats[PMD_STAT_MFEX_OPT_HIT] / passes,\n stats[PMD_STAT_SIMPLE_HIT],\n 100.0 * stats[PMD_STAT_SIMPLE_HIT] / passes,\n stats[PMD_STAT_EXACT_HIT],\ndiff --git a/lib/dpif-netdev-perf.h b/lib/dpif-netdev-perf.h\nindex 84beced15..22c28c6f4 100644\n--- a/lib/dpif-netdev-perf.h\n+++ b/lib/dpif-netdev-perf.h\n@@ -57,7 +57,6 @@ extern \"C\" {\n \n enum pmd_stat_type {\n PMD_STAT_PHWOL_HIT, /* Packets that had a partial HWOL hit (phwol). */\n- PMD_STAT_MFEX_OPT_HIT, /* Packets that had miniflow optimized match. */\n PMD_STAT_SIMPLE_HIT, /* Packets that had a simple match hit. */\n PMD_STAT_EXACT_HIT, /* Packets that had an exact match (emc). */\n PMD_STAT_SMC_HIT, /* Packets that had a sig match hit (SMC). */\ndiff --git a/lib/dpif-netdev-private-extract.c b/lib/dpif-netdev-private-extract.c\ndeleted file mode 100644\nindex ded08fd3e..000000000\n--- a/lib/dpif-netdev-private-extract.c\n+++ /dev/null\n@@ -1,471 +0,0 @@\n-/*\n- * Copyright (c) 2021 Intel.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include <config.h>\n-#include <errno.h>\n-#include <stdint.h>\n-#include <string.h>\n-\n-#include \"cpu.h\"\n-#include \"dp-packet.h\"\n-#include \"dpif-netdev-private-dpcls.h\"\n-#include \"dpif-netdev-private-extract.h\"\n-#include \"dpif-netdev-private-thread.h\"\n-#include \"flow.h\"\n-#include \"openvswitch/vlog.h\"\n-#include \"ovs-thread.h\"\n-#include \"util.h\"\n-\n-VLOG_DEFINE_THIS_MODULE(dpif_netdev_extract);\n-\n-/* Variable to hold the default MFEX implementation. */\n-static ATOMIC(miniflow_extract_func) default_mfex_func;\n-\n-#if MFEX_IMPL_AVX512_CHECK\n-static int32_t\n-avx512_isa_probe(bool needs_vbmi)\n-{\n- static enum ovs_cpu_isa isa_required[] = {\n- OVS_CPU_ISA_X86_AVX512F,\n- OVS_CPU_ISA_X86_AVX512BW,\n- OVS_CPU_ISA_X86_BMI2,\n- };\n-\n- for (uint32_t i = 0; i < ARRAY_SIZE(isa_required); i++) {\n- if (!cpu_has_isa(isa_required[i])) {\n- return -ENOTSUP;\n- }\n- }\n-\n- if (needs_vbmi && !cpu_has_isa(OVS_CPU_ISA_X86_AVX512VBMI)) {\n- return -ENOTSUP;\n- }\n-\n- return 0;\n-}\n-\n-/* Probe functions to check ISA requirements. */\n-static int32_t\n-mfex_avx512_probe(void)\n-{\n- return avx512_isa_probe(false);\n-}\n-\n-#if HAVE_AVX512VBMI\n-static int32_t\n-mfex_avx512_vbmi_probe(void)\n-{\n- return avx512_isa_probe(true);\n-}\n-#endif\n-#endif\n-\n-/* Implementations of available extract options and\n- * the implementations are always in order of preference.\n- */\n-static struct dpif_miniflow_extract_impl mfex_impls[] = {\n-\n- [MFEX_IMPL_AUTOVALIDATOR] = {\n- .probe = NULL,\n- .extract_func = dpif_miniflow_extract_autovalidator,\n- .name = \"autovalidator\", },\n-\n- [MFEX_IMPL_SCALAR] = {\n- .probe = NULL,\n- .extract_func = NULL,\n- .name = \"scalar\", },\n-\n- [MFEX_IMPL_STUDY] = {\n- .probe = NULL,\n- .extract_func = mfex_study_traffic,\n- .name = \"study\", },\n-\n-/* Compile in implementations only if the compiler ISA checks pass. */\n-#if MFEX_IMPL_AVX512_CHECK\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_IPv4_UDP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_ip_udp,\n- .name = \"avx512_vbmi_ipv4_udp\", },\n-#endif\n- [MFEX_IMPL_IPv4_UDP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_ip_udp,\n- .name = \"avx512_ipv4_udp\", },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_IPv4_TCP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_ip_tcp,\n- .name = \"avx512_vbmi_ipv4_tcp\", },\n-#endif\n- [MFEX_IMPL_IPv4_TCP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_ip_tcp,\n- .name = \"avx512_ipv4_tcp\", },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_DOT1Q_IPv4_UDP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_dot1q_ip_udp,\n- .name = \"avx512_vbmi_dot1q_ipv4_udp\", },\n-#endif\n- [MFEX_IMPL_DOT1Q_IPv4_UDP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_dot1q_ip_udp,\n- .name = \"avx512_dot1q_ipv4_udp\", },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_DOT1Q_IPv4_TCP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_dot1q_ip_tcp,\n- .name = \"avx512_vbmi_dot1q_ipv4_tcp\", },\n-#endif\n- [MFEX_IMPL_DOT1Q_IPv4_TCP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_dot1q_ip_tcp,\n- .name = \"avx512_dot1q_ipv4_tcp\",\n- },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_IPv6_UDP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_ipv6_udp,\n- .name = \"avx512_vbmi_ipv6_udp\",\n- },\n-#endif\n- [MFEX_IMPL_IPv6_UDP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_ipv6_udp,\n- .name = \"avx512_ipv6_udp\",\n- },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_IPv6_TCP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_ipv6_tcp,\n- .name = \"avx512_vbmi_ipv6_tcp\",\n- },\n-#endif\n- [MFEX_IMPL_IPv6_TCP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_ipv6_tcp,\n- .name = \"avx512_ipv6_tcp\",\n- },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_DOT1Q_IPv6_TCP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_dot1q_ipv6_tcp,\n- .name = \"avx512_vbmi_avx512_dot1q_ipv6_tcp\",\n- },\n-#endif\n- [MFEX_IMPL_DOT1Q_IPv6_TCP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_dot1q_ipv6_tcp,\n- .name = \"avx512_dot1q_ipv6_tcp\",\n- },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_DOT1Q_IPv6_UDP] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_dot1q_ipv6_udp,\n- .name = \"avx512_vbmi_avx512_dot1q_ipv6_udp\",\n- },\n-#endif\n- [MFEX_IMPL_DOT1Q_IPv6_UDP] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_dot1q_ipv6_udp,\n- .name = \"avx512_dot1q_ipv6_udp\",\n- },\n-#if HAVE_AVX512VBMI\n- [MFEX_IMPL_VBMI_IPv4_NVGRE] = {\n- .probe = mfex_avx512_vbmi_probe,\n- .extract_func = mfex_avx512_vbmi_ip_nvgre,\n- .name = \"avx512_vbmi_ipv4_nvgre\", },\n-#endif\n- [MFEX_IMPL_IPv4_NVGRE] = {\n- .probe = mfex_avx512_probe,\n- .extract_func = mfex_avx512_ip_nvgre,\n- .name = \"avx512_ipv4_nvgre\", },\n-#endif\n-};\n-\n-BUILD_ASSERT_DECL(MFEX_IMPL_MAX == ARRAY_SIZE(mfex_impls));\n-\n-void\n-dpif_miniflow_extract_init(void)\n-{\n- atomic_uintptr_t *mfex_func = (void *)&default_mfex_func;\n-#ifdef MFEX_AUTOVALIDATOR_DEFAULT\n- int mfex_idx = MFEX_IMPL_AUTOVALIDATOR;\n-#else\n- int mfex_idx = MFEX_IMPL_SCALAR;\n-#endif\n-\n- /* Call probe on each impl, and cache the result. */\n- for (int i = 0; i < MFEX_IMPL_MAX; i++) {\n- bool avail = true;\n- if (mfex_impls[i].probe) {\n- /* Return zero is success, non-zero means error. */\n- avail = (mfex_impls[i].probe() == 0);\n- }\n- VLOG_DBG(\"Miniflow Extract implementation '%s' %s available.\",\n- mfex_impls[i].name, avail ? \"is\" : \"is not\");\n- mfex_impls[i].available = avail;\n- }\n-\n- /* For the first call, this will be choosen based on the\n- * compile time flag.\n- */\n- VLOG_INFO(\"Default MFEX Extract implementation is %s.\\n\",\n- mfex_impls[mfex_idx].name);\n- atomic_store_relaxed(mfex_func, (uintptr_t) mfex_impls\n- [mfex_idx].extract_func);\n-}\n-\n-miniflow_extract_func\n-dp_mfex_impl_get_default(void)\n-{\n- miniflow_extract_func return_func;\n- atomic_uintptr_t *mfex_func = (void *)&default_mfex_func;\n-\n- atomic_read_relaxed(mfex_func, (uintptr_t *) &return_func);\n-\n- return return_func;\n-}\n-\n-int\n-dp_mfex_impl_set_default_by_name(const char *name)\n-{\n- miniflow_extract_func new_default;\n- atomic_uintptr_t *mfex_func = (void *)&default_mfex_func;\n-\n- int err = dp_mfex_impl_get_by_name(name, &new_default);\n-\n- if (!err) {\n- atomic_store_relaxed(mfex_func, (uintptr_t) new_default);\n- }\n-\n- return err;\n-\n-}\n-\n-void\n-dp_mfex_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,\n- size_t pmd_list_size)\n-{\n- /* Add all MFEX functions to reply string. */\n- ds_put_cstr(reply, \"Available MFEX implementations:\\n\");\n-\n- for (int i = 0; i < MFEX_IMPL_MAX; i++) {\n- ds_put_format(reply, \" %s (available: %s pmds: \",\n- mfex_impls[i].name, mfex_impls[i].available ?\n- \"True\" : \"False\");\n-\n- for (size_t j = 0; j < pmd_list_size; j++) {\n- struct dp_netdev_pmd_thread *pmd = pmd_list[j];\n- if (pmd->core_id == NON_PMD_CORE_ID) {\n- continue;\n- }\n-\n- if (pmd->miniflow_extract_opt == mfex_impls[i].extract_func) {\n- ds_put_format(reply, \"%u,\", pmd->core_id);\n- }\n- }\n-\n- ds_chomp(reply, ',');\n-\n- if (ds_last(reply) == ' ') {\n- ds_put_cstr(reply, \"none\");\n- }\n-\n- ds_put_cstr(reply, \")\\n\");\n- }\n-\n-}\n-\n-/* This function checks all available MFEX implementations, and selects and\n- * returns the function pointer to the one requested by \"name\". If nothing\n- * is found it returns error.\n- */\n-int\n-dp_mfex_impl_get_by_name(const char *name, miniflow_extract_func *out_func)\n-{\n- if (!name || !out_func) {\n- return -EINVAL;\n- }\n-\n- for (int i = 0; i < MFEX_IMPL_MAX; i++) {\n- if (strcmp(mfex_impls[i].name, name) == 0) {\n- /* Check available is set before exec. */\n- if (!mfex_impls[i].available) {\n- *out_func = NULL;\n- return -ENODEV;\n- }\n-\n- *out_func = mfex_impls[i].extract_func;\n- return 0;\n- }\n- }\n-\n- return -ENOENT;\n-}\n-\n-struct dpif_miniflow_extract_impl *\n-dpif_mfex_impl_info_get(void) {\n-\n- return mfex_impls;\n-\n-}\n-\n-uint32_t\n-dpif_miniflow_extract_autovalidator(struct dp_packet_batch *packets,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size, odp_port_t in_port,\n- struct dp_netdev_pmd_thread *pmd_handle)\n-{\n- const size_t cnt = dp_packet_batch_size(packets);\n- uint16_t good_l2_5_ofs[NETDEV_MAX_BURST];\n- uint16_t good_l3_ofs[NETDEV_MAX_BURST];\n- uint16_t good_l4_ofs[NETDEV_MAX_BURST];\n- uint16_t good_l2_pad_size[NETDEV_MAX_BURST];\n- struct dp_packet *packet;\n- struct dp_netdev_pmd_thread *pmd = pmd_handle;\n- struct netdev_flow_key test_keys[NETDEV_MAX_BURST];\n-\n- if (keys_size < cnt) {\n- atomic_store_relaxed(&pmd->miniflow_extract_opt, NULL);\n- VLOG_ERR(\"Invalid key size supplied, Key_size: %d less than\"\n- \"batch_size: %\" PRIuSIZE\"\\n\", keys_size, cnt);\n- VLOG_ERR(\"Autovalidatior is disabled.\\n\");\n- return 0;\n- }\n-\n- /* Run scalar miniflow_extract to get default result. */\n- DP_PACKET_BATCH_FOR_EACH (i, packet, packets) {\n- pkt_metadata_init(&packet->md, in_port);\n- miniflow_extract(packet, &keys[i].mf);\n-\n- /* Store known good metadata to compare with optimized metadata. */\n- good_l2_5_ofs[i] = packet->l2_5_ofs;\n- good_l3_ofs[i] = packet->l3_ofs;\n- good_l4_ofs[i] = packet->l4_ofs;\n- good_l2_pad_size[i] = packet->l2_pad_size;\n- }\n-\n- uint32_t batch_failed = 0;\n- /* Iterate through each version of miniflow implementations. */\n- for (int j = MFEX_IMPL_START_IDX; j < MFEX_IMPL_MAX; j++) {\n- if (!mfex_impls[j].available) {\n- continue;\n- }\n- /* Reset keys and offsets before each implementation. */\n- memset(test_keys, 0, keys_size * sizeof(struct netdev_flow_key));\n- DP_PACKET_BATCH_FOR_EACH (i, packet, packets) {\n- dp_packet_reset_offsets(packet);\n- }\n- /* Call optimized miniflow for each batch of packet. */\n- uint32_t hit_mask = mfex_impls[j].extract_func(packets, test_keys,\n- keys_size, in_port,\n- pmd_handle);\n-\n- /* Do a miniflow compare for bits, blocks and offsets for all the\n- * classified packets in the hitmask marked by set bits. */\n- while (hit_mask) {\n- /* Index for the set bit. */\n- uint32_t i = raw_ctz(hit_mask);\n- /* Set the index in hitmask to Zero. */\n- hit_mask &= (hit_mask - 1);\n-\n- uint32_t failed = 0;\n-\n- struct ds log_msg = DS_EMPTY_INITIALIZER;\n- ds_put_format(&log_msg, \"MFEX autovalidator pkt %d\\n\", i);\n-\n- /* Check miniflow bits are equal. */\n- if ((keys[i].mf.map.bits[0] != test_keys[i].mf.map.bits[0]) ||\n- (keys[i].mf.map.bits[1] != test_keys[i].mf.map.bits[1])) {\n- ds_put_format(&log_msg, \"Autovalidation map failed\\n\"\n- \"Good: 0x%llx 0x%llx Test: 0x%llx 0x%llx\\n\",\n- keys[i].mf.map.bits[0],\n- keys[i].mf.map.bits[1],\n- test_keys[i].mf.map.bits[0],\n- test_keys[i].mf.map.bits[1]);\n- failed = 1;\n- }\n-\n- if (!miniflow_equal(&keys[i].mf, &test_keys[i].mf)) {\n- uint32_t block_cnt = miniflow_n_values(&keys[i].mf);\n- uint32_t test_block_cnt = miniflow_n_values(&test_keys[i].mf);\n-\n- ds_put_format(&log_msg, \"Autovalidation blocks failed\\n\"\n- \"Good hex:\\n\");\n- ds_put_hex_dump(&log_msg, &keys[i].buf, block_cnt * 8, 0,\n- false);\n- ds_put_format(&log_msg, \"Test hex:\\n\");\n- ds_put_hex_dump(&log_msg, &test_keys[i].buf,\n- test_block_cnt * 8, 0, false);\n- failed = 1;\n- }\n-\n- packet = packets->packets[i];\n- if ((packet->l2_pad_size != good_l2_pad_size[i]) ||\n- (packet->l2_5_ofs != good_l2_5_ofs[i]) ||\n- (packet->l3_ofs != good_l3_ofs[i]) ||\n- (packet->l4_ofs != good_l4_ofs[i])) {\n- ds_put_format(&log_msg,\n- \"Autovalidation packet offsets failed\\n\");\n- ds_put_format(&log_msg, \"Good offsets: \"\n- \"l2_pad_size: %\"PRIu16\", l2_5_ofs: %\"PRIu16\", \"\n- \"l3_ofs: %\"PRIu16\", l4_ofs: %\"PRIu16\"\\n\",\n- good_l2_pad_size[i], good_l2_5_ofs[i],\n- good_l3_ofs[i], good_l4_ofs[i]);\n- ds_put_format(&log_msg, \"Test offsets: \"\n- \"l2_pad_size: %\"PRIu16\", l2_5_ofs: %\"PRIu16\", \"\n- \"l3_ofs: %\"PRIu16\", l4_ofs: %\"PRIu16\"\\n\",\n- packet->l2_pad_size, packet->l2_5_ofs,\n- packet->l3_ofs, packet->l4_ofs);\n- failed = 1;\n- }\n-\n- if (failed) {\n- VLOG_ERR(\"Autovalidation for %s failed in pkt %d,\"\n- \" disabling.\", mfex_impls[j].name, i);\n- VLOG_ERR(\"Autovalidation failure details:\\n%s\",\n- ds_cstr(&log_msg));\n- batch_failed = 1;\n- }\n- ds_destroy(&log_msg);\n- }\n- }\n-\n- /* Having dumped the debug info for the batch, disable autovalidator. */\n- if (batch_failed) {\n- atomic_store_relaxed(&pmd->miniflow_extract_opt, NULL);\n- }\n-\n- /* Preserve packet correctness by storing back the good offsets in\n- * packets back. */\n- DP_PACKET_BATCH_FOR_EACH (i, packet, packets) {\n- packet->l2_5_ofs = good_l2_5_ofs[i];\n- packet->l3_ofs = good_l3_ofs[i];\n- packet->l4_ofs = good_l4_ofs[i];\n- packet->l2_pad_size = good_l2_pad_size[i];\n- }\n-\n- /* Returning zero implies no packets were hit by autovalidation. This\n- * simplifies unit-tests as changing --enable-mfex-default-autovalidator\n- * would pass/fail. By always returning zero, autovalidator is a little\n- * slower, but we gain consistency in testing. The auto-validator is only\n- * meant to test different implementaions against a batch of packets\n- * without incrementing hit counters.\n- */\n- return 0;\n-}\ndiff --git a/lib/dpif-netdev-private-extract.h b/lib/dpif-netdev-private-extract.h\ndeleted file mode 100644\nindex 48549beaa..000000000\n--- a/lib/dpif-netdev-private-extract.h\n+++ /dev/null\n@@ -1,241 +0,0 @@\n-/*\n- * Copyright (c) 2021 Intel.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef MFEX_AVX512_EXTRACT\n-#define MFEX_AVX512_EXTRACT 1\n-\n-#include <sys/types.h>\n-\n-#define MFEX_IMPL_AVX512_CHECK (__x86_64__ && HAVE_AVX512F \\\n- && HAVE_LD_AVX512_GOOD && HAVE_AVX512BW && __SSE4_2__)\n-\n-/* Forward declarations. */\n-struct dp_packet;\n-struct miniflow;\n-struct dp_netdev_pmd_thread;\n-struct dp_packet_batch;\n-struct netdev_flow_key;\n-\n-/* Function pointer prototype to be implemented in the optimized miniflow\n- * extract code.\n- * returns the hitmask of the processed packets on success.\n- * returns zero on failure.\n- */\n-typedef uint32_t (*miniflow_extract_func)(struct dp_packet_batch *batch,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size,\n- odp_port_t in_port,\n- struct dp_netdev_pmd_thread\n- *pmd_handle);\n-\n-\n-/* The function pointer miniflow_extract_func depends on batch size. */\n-BUILD_ASSERT_DECL(NETDEV_MAX_BURST == 32);\n-\n-/* Assert if there is flow map units change. */\n-BUILD_ASSERT_DECL(FLOWMAP_UNITS == 2);\n-\n-/* Probe function is used to detect if this CPU has the ISA required\n- * to run the optimized miniflow implementation.\n- * returns one on successful probe.\n- * returns negative errno on failure.\n- */\n-typedef int (*miniflow_extract_probe)(void);\n-\n-/* Structure representing the attributes of an optimized implementation. */\n-struct dpif_miniflow_extract_impl {\n- /* When it is true, this impl has passed the probe() checks. */\n- bool available;\n-\n- /* Probe function is used to detect if this CPU has the ISA required\n- * to run the optimized miniflow implementation. It is optional and\n- * if it is not used, then it must be null.\n- */\n- miniflow_extract_probe probe;\n-\n- /* Optional function to call to extract miniflows for a burst of packets.\n- * If it is not used must be set to NULL;\n- */\n- miniflow_extract_func extract_func;\n-\n- /* Name of the optimized implementation. */\n- char *name;\n-};\n-\n-\n-/* Enum to hold implementation indexes. The list is traversed\n- * linearly as from the ISA perspective, the VBMI version\n- * should always come before the generic AVX512-F version.\n- */\n-enum dpif_miniflow_extract_impl_idx {\n- MFEX_IMPL_AUTOVALIDATOR,\n- MFEX_IMPL_SCALAR,\n- MFEX_IMPL_STUDY,\n-#if MFEX_IMPL_AVX512_CHECK\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_IPv4_UDP,\n-#endif\n- MFEX_IMPL_IPv4_UDP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_IPv4_TCP,\n-#endif\n- MFEX_IMPL_IPv4_TCP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_DOT1Q_IPv4_UDP,\n-#endif\n- MFEX_IMPL_DOT1Q_IPv4_UDP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_DOT1Q_IPv4_TCP,\n-#endif\n- MFEX_IMPL_DOT1Q_IPv4_TCP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_IPv6_UDP,\n-#endif\n- MFEX_IMPL_IPv6_UDP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_IPv6_TCP,\n-#endif\n- MFEX_IMPL_IPv6_TCP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_DOT1Q_IPv6_TCP,\n-#endif\n- MFEX_IMPL_DOT1Q_IPv6_TCP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_DOT1Q_IPv6_UDP,\n-#endif\n- MFEX_IMPL_DOT1Q_IPv6_UDP,\n-#if HAVE_AVX512VBMI\n- MFEX_IMPL_VBMI_IPv4_NVGRE,\n-#endif\n- MFEX_IMPL_IPv4_NVGRE,\n-#endif\n- MFEX_IMPL_MAX\n-};\n-\n-extern struct ovs_mutex dp_netdev_mutex;\n-\n-/* Define a index which points to the first traffic optimized MFEX\n- * option from the enum list else holds max value.\n- */\n-#if MFEX_IMPL_AVX512_CHECK\n-#if HAVE_AVX512VBMI\n-#define MFEX_IMPL_START_IDX MFEX_IMPL_VBMI_IPv4_UDP\n-#else\n-#define MFEX_IMPL_START_IDX MFEX_IMPL_IPv4_UDP\n-#endif\n-\n-#else\n-\n-#define MFEX_IMPL_START_IDX MFEX_IMPL_MAX\n-\n-#endif\n-\n-/* Max count of packets to be compared. */\n-#define MFEX_MAX_PKT_COUNT (128)\n-\n-/* This function returns all available implementations to the caller. The\n- * quantity of implementations is returned by the int return value.\n- */\n-void\n-dp_mfex_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,\n- size_t pmd_list_size) OVS_REQUIRES(dp_netdev_mutex);\n-\n-/* This function checks all available MFEX implementations, and selects the\n- * returns the function pointer to the one requested by \"name\".\n- */\n-int\n-dp_mfex_impl_get_by_name(const char *name, miniflow_extract_func *out_func);\n-\n-/* Returns the default MFEX which is first ./configure selected, but can be\n- * overridden at runtime. */\n-miniflow_extract_func dp_mfex_impl_get_default(void);\n-\n-/* Overrides the default MFEX with the user set MFEX. */\n-int dp_mfex_impl_set_default_by_name(const char *name);\n-\n-/* Retrieve the array of miniflow implementations for iteration. */\n-struct dpif_miniflow_extract_impl *\n-dpif_mfex_impl_info_get(void);\n-\n-/* Initializes the available miniflow extract implementations by probing for\n- * the CPU ISA requirements. As the runtime available CPU ISA does not change\n- * and the required ISA of the implementation also does not change, it is safe\n- * to cache the probe() results, and not call probe() at runtime.\n- */\n-void\n-dpif_miniflow_extract_init(void);\n-\n-/* Retrieve the hitmask of the batch of pakcets which is obtained by comparing\n- * different miniflow implementations with linear miniflow extract.\n- * Key_size need to be at least the size of the batch.\n- * On error, returns a zero.\n- * On success, returns the number of packets in the batch compared.\n- */\n-uint32_t\n-dpif_miniflow_extract_autovalidator(struct dp_packet_batch *batch,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size, odp_port_t in_port,\n- struct dp_netdev_pmd_thread *pmd_handle);\n-\n-/* Retrieve the number of packets by studying packets using different miniflow\n- * implementations to choose the best implementation using the maximum hitmask\n- * count.\n- * On error, returns a zero for no packets.\n- * On success, returns mask of the packets hit.\n- */\n-uint32_t\n-mfex_study_traffic(struct dp_packet_batch *packets,\n- struct netdev_flow_key *keys,\n- uint32_t keys_size, odp_port_t in_port,\n- struct dp_netdev_pmd_thread *pmd_handle);\n-\n-/* Sets the packet count from user to the stats for use in\n- * study function to match against the classified packets to choose\n- * the optimal implementation.\n- * On error, returns -EINVAL.\n- * On success, returns 0.\n- */\n-int\n-mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count, const char *name);\n-\n-/* AVX512 MFEX Implementation functions. */\n-#ifdef __x86_64__\n-\n-#define DECLARE_AVX512_MFEX_PROTOTYPE(name) \\\n- uint32_t \\\n- mfex_avx512_vbmi_##name(struct dp_packet_batch *packets, \\\n- struct netdev_flow_key *keys, uint32_t keys_size,\\\n- odp_port_t in_port, struct dp_netdev_pmd_thread \\\n- *pmd_handle); \\\n- uint32_t \\\n- mfex_avx512_##name(struct dp_packet_batch *packets, \\\n- struct netdev_flow_key *keys, uint32_t keys_size, \\\n- odp_port_t in_port, struct dp_netdev_pmd_thread \\\n- *pmd_handle); \\\n-\n-DECLARE_AVX512_MFEX_PROTOTYPE(ip_udp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(ip_tcp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ip_udp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ip_tcp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(ipv6_udp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(ipv6_tcp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ipv6_tcp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(dot1q_ipv6_udp);\n-DECLARE_AVX512_MFEX_PROTOTYPE(ip_nvgre);\n-\n-#endif /* __x86_64__ */\n-\n-#endif /* MFEX_AVX512_EXTRACT */\ndiff --git a/lib/dpif-netdev-private-thread.h b/lib/dpif-netdev-private-thread.h\nindex a46ce9991..1ab3e586a 100644\n--- a/lib/dpif-netdev-private-thread.h\n+++ b/lib/dpif-netdev-private-thread.h\n@@ -32,7 +32,6 @@\n #include \"dpif-netdev-private-dfc.h\"\n #include \"dpif-netdev-private-dpif.h\"\n #include \"dpif-netdev-perf.h\"\n-#include \"dpif-netdev-private-extract.h\"\n #include \"openvswitch/thread.h\"\n \n #ifdef __cplusplus\n@@ -127,9 +126,6 @@ struct dp_netdev_pmd_thread {\n /* Pointer for per-DPIF implementation scratch space. */\n void *netdev_input_func_userdata;\n \n- /* Function pointer to call for miniflow_extract() functionality. */\n- ATOMIC(miniflow_extract_func) miniflow_extract_opt;\n-\n struct seq *reload_seq;\n uint64_t last_reload_seq;\n \ndiff --git a/lib/dpif-netdev-unixctl.man b/lib/dpif-netdev-unixctl.man\nindex 8cd847416..69b3b1a4a 100644\n--- a/lib/dpif-netdev-unixctl.man\n+++ b/lib/dpif-netdev-unixctl.man\n@@ -17,9 +17,6 @@ datapath. Beware that a recirculated packet experiences one additional lookup\n per recirculation, so there may be more lookups than forwarded packets in the\n datapath.\n \n-The MFEX Opt hits displays the number of packets that are processed by the\n-optimized miniflow extract implementations.\n-\n Cycles are counted using the TSC or similar facilities (when available on\n the platform). The duration of one cycle depends on the processing platform.\n \n@@ -140,7 +137,6 @@ pmd thread numa_id 0 core_id 1:\n Rx packets: 2399607 (2381 Kpps, 848 cycles/pkt)\n Datapath passes: 3599415 (1.50 passes/pkt)\n - PHWOL hits: 0 ( 0.0 %)\n- - MFEX Opt hits: 3570133 ( 99.2 %)\n - Simple Match hits: 0 ( 0.0 %)\n - EMC hits: 336472 ( 9.3 %)\n - SMC hits: 0 ( 0.0 %)\n@@ -251,14 +247,3 @@ Lists the DPIF implementations that are available.\n .\n .IP \"\\fBdpif-netdev/dpif-impl-set\\fR \\fIdpif_impl\\fR\"\n Sets the DPIF to be used to \\fIdpif_impl\\fR. By default \"dpif_scalar\" is used.\n-.\n-.IP \"\\fBdpif-netdev/miniflow-parser-get\\fR\n-Lists the miniflow extract implementations that are available.\n-.\n-.IP \"\\fBdpif-netdev/miniflow-parser-set\\fR [\\fB-pmd\\fR \\fIcore\\fR] \\\n-\\fIminiflow_impl\\fR [\\fIstudy_cnt\\fR]\"\n-Sets the miniflow extract to \\fIminiflow_impl\\fR for a specified PMD or all\n-PMDs in the case where no value is specified. By default \"scalar\" is used.\n-\\fIstudy_cnt\\fR defaults to 128 and indicates the number of packets that the\n-\"study\" miniflow implementation must parse before choosing an optimal\n-implementation.\ndiff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c\nindex 9df05c4c2..5c96f3fc8 100644\n--- a/lib/dpif-netdev.c\n+++ b/lib/dpif-netdev.c\n@@ -47,7 +47,6 @@\n #include \"dpif.h\"\n #include \"dpif-netdev-lookup.h\"\n #include \"dpif-netdev-perf.h\"\n-#include \"dpif-netdev-private-extract.h\"\n #include \"dpif-provider.h\"\n #include \"dummy.h\"\n #include \"fat-rwlock.h\"\n@@ -124,7 +123,7 @@ COVERAGE_DEFINE(datapath_drop_hw_post_process);\n COVERAGE_DEFINE(datapath_drop_hw_post_process_consumed);\n \n /* Protects against changes to 'dp_netdevs'. */\n-struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;\n+static struct ovs_mutex dp_netdev_mutex = OVS_MUTEX_INITIALIZER;\n \n /* Contains all 'struct dp_netdev's. */\n static struct shash dp_netdevs OVS_GUARDED_BY(dp_netdev_mutex)\n@@ -676,7 +675,6 @@ pmd_info_show_stats(struct ds *reply,\n \" packet recirculations: %\"PRIu64\"\\n\"\n \" avg. datapath passes per packet: %.02f\\n\"\n \" phwol hits: %\"PRIu64\"\\n\"\n- \" mfex opt hits: %\"PRIu64\"\\n\"\n \" simple match hits: %\"PRIu64\"\\n\"\n \" emc hits: %\"PRIu64\"\\n\"\n \" smc hits: %\"PRIu64\"\\n\"\n@@ -687,7 +685,6 @@ pmd_info_show_stats(struct ds *reply,\n \" avg. packets per output batch: %.02f\\n\",\n total_packets, stats[PMD_STAT_RECIRC],\n passes_per_pkt, stats[PMD_STAT_PHWOL_HIT],\n- stats[PMD_STAT_MFEX_OPT_HIT],\n stats[PMD_STAT_SIMPLE_HIT],\n stats[PMD_STAT_EXACT_HIT],\n stats[PMD_STAT_SMC_HIT],\n@@ -1109,220 +1106,6 @@ dpif_netdev_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED,\n ds_destroy(&reply);\n }\n \n-static void\n-dpif_miniflow_extract_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED,\n- void *aux OVS_UNUSED)\n-{\n- struct ds reply = DS_EMPTY_INITIALIZER;\n- struct shash_node *node;\n-\n- ovs_mutex_lock(&dp_netdev_mutex);\n- SHASH_FOR_EACH (node, &dp_netdevs) {\n- struct dp_netdev_pmd_thread **pmd_list;\n- struct dp_netdev *dp = node->data;\n- size_t n;\n-\n- /* Get PMD threads list, required to get the DPIF impl used by each PMD\n- * thread. */\n- sorted_poll_thread_list(dp, &pmd_list, &n);\n- dp_mfex_impl_get(&reply, pmd_list, n);\n- free(pmd_list);\n- }\n- ovs_mutex_unlock(&dp_netdev_mutex);\n- unixctl_command_reply(conn, ds_cstr(&reply));\n- ds_destroy(&reply);\n-}\n-\n-static void\n-dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,\n- const char *argv[], void *aux OVS_UNUSED)\n-{\n- /* This command takes some optional and mandatory arguments. The function\n- * here first parses all of the options, saving results in local variables.\n- * Then the parsed values are acted on.\n- */\n- unsigned int pmd_thread_to_change = NON_PMD_CORE_ID;\n- unsigned int study_count = MFEX_MAX_PKT_COUNT;\n- struct ds reply = DS_EMPTY_INITIALIZER;\n- bool pmd_thread_update_done = false;\n- bool mfex_name_is_study = false;\n- const char *mfex_name = NULL;\n- const char *reply_str = NULL;\n- struct shash_node *node;\n- int err;\n-\n- while (argc > 1) {\n- /* Optional argument \"-pmd\" limits the commands actions to just this\n- * PMD thread.\n- */\n- if ((!strcmp(argv[1], \"-pmd\") && !mfex_name)) {\n- if (argc < 3) {\n- ds_put_format(&reply,\n- \"Error: -pmd option requires a thread id\"\n- \" argument.\\n\");\n- goto error;\n- }\n-\n- /* Ensure argument can be parsed to an integer. */\n- if (!str_to_uint(argv[2], 10, &pmd_thread_to_change) ||\n- (pmd_thread_to_change == NON_PMD_CORE_ID)) {\n- ds_put_format(&reply,\n- \"Error: miniflow extract parser not changed,\"\n- \" PMD thread passed is not valid: '%s'.\"\n- \" Pass a valid pmd thread ID.\\n\",\n- argv[2]);\n- goto error;\n- }\n-\n- argc -= 2;\n- argv += 2;\n-\n- } else if (!mfex_name) {\n- /* Name of MFEX impl requested by user. */\n- mfex_name = argv[1];\n- mfex_name_is_study = strcmp(\"study\", mfex_name) == 0;\n- argc -= 1;\n- argv += 1;\n-\n- /* If name is study and more args exist, parse study_count value. */\n- } else if (mfex_name && mfex_name_is_study) {\n- if (!str_to_uint(argv[1], 10, &study_count) ||\n- (study_count == 0)) {\n- ds_put_format(&reply,\n- \"Error: invalid study_pkt_cnt value: %s.\\n\",\n- argv[1]);\n- goto error;\n- }\n-\n- argc -= 1;\n- argv += 1;\n- } else {\n- ds_put_format(&reply, \"Error: unknown argument %s.\\n\", argv[1]);\n- goto error;\n- }\n- }\n-\n- /* Ensure user passed an MFEX name. */\n- if (!mfex_name) {\n- ds_put_format(&reply, \"Error: no miniflow extract name provided.\"\n- \" Output of miniflow-parser-get shows implementation\"\n- \" list.\\n\");\n- goto error;\n- }\n-\n- /* If the MFEX name is \"study\", set the study packet count. */\n- if (mfex_name_is_study) {\n- err = mfex_set_study_pkt_cnt(study_count, mfex_name);\n- if (err) {\n- ds_put_format(&reply, \"Error: failed to set study count %d for\"\n- \" miniflow extract implementation %s.\\n\",\n- study_count, mfex_name);\n- goto error;\n- }\n- }\n-\n- /* Set the default MFEX impl only if the command was applied to all PMD\n- * threads. If a PMD thread was selected, do NOT update the default.\n- */\n- if (pmd_thread_to_change == NON_PMD_CORE_ID) {\n- err = dp_mfex_impl_set_default_by_name(mfex_name);\n- if (err == -ENODEV) {\n- ds_put_format(&reply,\n- \"Error: miniflow extract not available due to CPU\"\n- \" ISA requirements: %s\",\n- mfex_name);\n- goto error;\n- } else if (err) {\n- ds_put_format(&reply,\n- \"Error: unknown miniflow extract implementation %s.\",\n- mfex_name);\n- goto error;\n- }\n- }\n-\n- /* Get the desired MFEX function pointer and error check its usage. */\n- miniflow_extract_func mfex_func = NULL;\n- err = dp_mfex_impl_get_by_name(mfex_name, &mfex_func);\n- if (err) {\n- if (err == -ENODEV) {\n- ds_put_format(&reply,\n- \"Error: miniflow extract not available due to CPU\"\n- \" ISA requirements: %s\", mfex_name);\n- } else {\n- ds_put_format(&reply,\n- \"Error: unknown miniflow extract implementation %s.\",\n- mfex_name);\n- }\n- goto error;\n- }\n-\n- /* Apply the MFEX pointer to each pmd thread in each netdev, filtering\n- * by the users \"-pmd\" argument if required.\n- */\n- ovs_mutex_lock(&dp_netdev_mutex);\n-\n- SHASH_FOR_EACH (node, &dp_netdevs) {\n- struct dp_netdev_pmd_thread **pmd_list;\n- struct dp_netdev *dp = node->data;\n- size_t n;\n-\n- sorted_poll_thread_list(dp, &pmd_list, &n);\n-\n- for (size_t i = 0; i < n; i++) {\n- struct dp_netdev_pmd_thread *pmd = pmd_list[i];\n- if (pmd->core_id == NON_PMD_CORE_ID) {\n- continue;\n- }\n-\n- /* If -pmd specified, skip all other pmd threads. */\n- if ((pmd_thread_to_change != NON_PMD_CORE_ID) &&\n- (pmd->core_id != pmd_thread_to_change)) {\n- continue;\n- }\n-\n- pmd_thread_update_done = true;\n- atomic_store_relaxed(&pmd->miniflow_extract_opt, mfex_func);\n- };\n-\n- free(pmd_list);\n- }\n-\n- ovs_mutex_unlock(&dp_netdev_mutex);\n-\n- /* If PMD thread was specified, but it wasn't found, return error. */\n- if (pmd_thread_to_change != NON_PMD_CORE_ID && !pmd_thread_update_done) {\n- ds_put_format(&reply,\n- \"Error: miniflow extract parser not changed, \"\n- \"PMD thread %d not in use, pass a valid pmd\"\n- \" thread ID.\\n\", pmd_thread_to_change);\n- goto error;\n- }\n-\n- /* Reply with success to command. */\n- ds_put_format(&reply, \"Miniflow extract implementation set to %s\",\n- mfex_name);\n- if (pmd_thread_to_change != NON_PMD_CORE_ID) {\n- ds_put_format(&reply, \", on pmd thread %d\", pmd_thread_to_change);\n- }\n- if (mfex_name_is_study) {\n- ds_put_format(&reply, \", studying %d packets\", study_count);\n- }\n- ds_put_format(&reply, \".\\n\");\n-\n- reply_str = ds_cstr(&reply);\n- VLOG_INFO(\"%s\", reply_str);\n- unixctl_command_reply(conn, reply_str);\n- ds_destroy(&reply);\n- return;\n-\n-error:\n- reply_str = ds_cstr(&reply);\n- VLOG_ERR(\"%s\", reply_str);\n- unixctl_command_reply_error(conn, reply_str);\n- ds_destroy(&reply);\n-}\n-\n static void\n dpif_netdev_pmd_rebalance(struct unixctl_conn *conn, int argc,\n const char *argv[], void *aux OVS_UNUSED)\n@@ -1606,14 +1389,6 @@ dpif_netdev_init(void)\n unixctl_command_register(\"dpif-netdev/dpif-impl-get\", \"\",\n 0, 0, dpif_netdev_impl_get,\n NULL);\n- unixctl_command_register(\"dpif-netdev/miniflow-parser-set\",\n- \"[-pmd core] miniflow_implementation_name\"\n- \" [study_pkt_cnt]\",\n- 1, 5, dpif_miniflow_extract_impl_set,\n- NULL);\n- unixctl_command_register(\"dpif-netdev/miniflow-parser-get\", \"\",\n- 0, 0, dpif_miniflow_extract_impl_get,\n- NULL);\n return 0;\n }\n \n@@ -1818,8 +1593,6 @@ create_dp_netdev(const char *name, const struct dpif_class *class,\n \n dp->conntrack = conntrack_init();\n \n- dpif_miniflow_extract_init();\n-\n atomic_init(&dp->emc_insert_min, DEFAULT_EM_FLOW_INSERT_MIN);\n atomic_init(&dp->tx_flush_interval, DEFAULT_TX_FLUSH_INTERVAL);\n \n@@ -7187,9 +6960,6 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp,\n /* Initialize DPIF function pointer to the default configured version. */\n atomic_init(&pmd->netdev_input_func, dp_netdev_impl_get_default());\n \n- /* Init default miniflow_extract function */\n- atomic_init(&pmd->miniflow_extract_opt, dp_mfex_impl_get_default());\n-\n /* init the 'flow_cache' since there is no\n * actual thread created for NON_PMD_CORE_ID. */\n if (core_id == NON_PMD_CORE_ID) {\n@@ -7823,11 +7593,10 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,\n size_t *n_flows, uint8_t *index_map,\n bool md_is_valid, odp_port_t port_no)\n {\n+ size_t n_missed = 0, n_emc_hit = 0, n_phwol_hit = 0, n_simple_hit = 0;\n const bool offload_enabled = dpif_offload_enabled();\n const uint32_t recirc_depth = *recirc_depth_get();\n const size_t cnt = dp_packet_batch_size(packets_);\n- size_t n_missed = 0, n_emc_hit = 0, n_phwol_hit = 0;\n- size_t n_mfex_opt_hit = 0, n_simple_hit = 0;\n struct dfc_cache *cache = &pmd->flow_cache;\n struct netdev_flow_key *key = &keys[0];\n struct dp_packet *packet;\n@@ -7940,8 +7709,6 @@ dfc_processing(struct dp_netdev_pmd_thread *pmd,\n *n_flows = map_cnt;\n \n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_PHWOL_HIT, n_phwol_hit);\n- pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_MFEX_OPT_HIT,\n- n_mfex_opt_hit);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_SIMPLE_HIT,\n n_simple_hit);\n pmd_perf_update_counter(&pmd->perf_stats, PMD_STAT_EXACT_HIT, n_emc_hit);\ndiff --git a/python/test_requirements.txt b/python/test_requirements.txt\nindex a1424506b..dae2d0189 100644\n--- a/python/test_requirements.txt\n+++ b/python/test_requirements.txt\n@@ -3,5 +3,4 @@ packaging\n pyftpdlib\n pyparsing\n pytest\n-scapy\n tftpy\ndiff --git a/tests/automake.mk b/tests/automake.mk\nindex 685d4d2de..078139a28 100644\n--- a/tests/automake.mk\n+++ b/tests/automake.mk\n@@ -546,7 +546,6 @@ tests_test_type_props_SOURCES = tests/test-type-props.c\n CHECK_PYFILES = \\\n \ttests/appctl.py \\\n \ttests/flowgen.py \\\n-\ttests/genpkts.py \\\n \ttests/ovsdb-monitor-sort.py \\\n \ttests/system-dpdk-find-device.py \\\n \ttests/test-daemon.py \\\ndiff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at\nindex 005c1991a..2b3ca450e 100644\n--- a/tests/dpif-netdev.at\n+++ b/tests/dpif-netdev.at\n@@ -3485,168 +3485,3 @@ OVS_VSWITCHD_STOP([\"dnl\n /.*failed to put.*$/d\n /.*failed to flow_del.*$/d\"])\n AT_CLEANUP\n-\n-AT_SETUP([dpif-netdev - MFEX Autovalidator])\n-AT_SKIP_IF([! $PYTHON3 -c \"import scapy\"], [], [])\n-AT_SKIP_IF([! $PYTHON3 $srcdir/genpkts.py 2000 > packets])\n-OVS_VSWITCHD_START(\n- [add-port br0 p1 \\\n- -- set Interface p1 type=dummy-pmd], [], [], [--dummy-numa=\"0,0,0,0,1,1,1,1\"])\n-\n-AT_SKIP_IF([! ovs-appctl dpif-netdev/miniflow-parser-get | sed 1,4d | grep \"True\"], [], [dnl\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/dpif-impl-set dpif_avx512], [0], [dnl\n-DPIF implementation set to dpif_avx512.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set autovalidator], [0], [dnl\n-Miniflow extract implementation set to autovalidator.\n-])\n-\n-cat packets | while read line; do\n- AT_CHECK([ovs-appctl netdev-dummy/receive p1 $line], [0], [ignore])\n-done\n-\n-OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics | grep -oP 'rx_packets=\\s*\\K\\d+'` -ge 16000])\n-\n-OVS_VSWITCHD_STOP\n-AT_CLEANUP\n-\n-AT_SETUP([dpif-netdev - MFEX Autovalidator Fuzzy])\n-AT_SKIP_IF([! $PYTHON3 -c \"import scapy\"], [], [])\n-AT_SKIP_IF([! $PYTHON3 $srcdir/genpkts.py 2000 fuzzy > packets])\n-OVS_VSWITCHD_START(\n- [add-port br0 p1 \\\n- -- set Interface p1 type=dummy-pmd], [], [], [--dummy-numa=\"0,0,0,0,1,1,1,1\"])\n-\n-AT_SKIP_IF([! ovs-appctl dpif-netdev/miniflow-parser-get | sed 1,4d | grep \"True\"], [], [dnl\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/dpif-impl-set dpif_avx512], [0], [dnl\n-DPIF implementation set to dpif_avx512.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set autovalidator], [0], [dnl\n-Miniflow extract implementation set to autovalidator.\n-])\n-\n-cat packets | while read line; do\n- AT_CHECK([ovs-appctl netdev-dummy/receive p1 $line], [0], [ignore])\n-done\n-\n-OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics | grep -oP 'rx_packets=\\s*\\K\\d+'` -ge 16000])\n-\n-OVS_VSWITCHD_STOP([\"dnl\n-/upcall: datapath reached the dynamic limit of .* flows./d\"])\n-AT_CLEANUP\n-\n-AT_SETUP([dpif-netdev - MFEX Configuration])\n-OVS_VSWITCHD_START(\n- [set Open_vSwitch . other_config:pmd-cpu-mask=0x1 \\\n- -- add-port br0 p1 \\\n- -- set Interface p1 type=dummy-pmd], [], [], [--dummy-numa=\"0,0,0,0,1,1,1,1\"])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set scalar 1], [2],\n-[], [dnl\n-Error: unknown argument 1.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 6 study 300 xyz], [2],\n-[], [dnl\n-Error: invalid study_pkt_cnt value: xyz.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set scalar abcd], [2],\n-[], [dnl\n-Error: unknown argument abcd.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 0 scalar abcd], [2],\n-[], [dnl\n-Error: unknown argument abcd.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd], [2],\n-[], [dnl\n-Error: -pmd option requires a thread id argument.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set tudy abcd], [2],\n-[], [dnl\n-Error: unknown argument abcd.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 7 study abcd], [2],\n-[], [dnl\n-Error: invalid study_pkt_cnt value: abcd.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 0 study], [0], [dnl\n-Miniflow extract implementation set to study, on pmd thread 0, studying 128 packets.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 0 study 512], [0], [dnl\n-Miniflow extract implementation set to study, on pmd thread 0, studying 512 packets.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set study 512], [0], [dnl\n-Miniflow extract implementation set to study, studying 512 packets.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set study], [0], [dnl\n-Miniflow extract implementation set to study, studying 128 packets.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 0 autovalidator], [0], [dnl\n-Miniflow extract implementation set to autovalidator, on pmd thread 0.\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd zero study], [2],\n-[], [dnl\n-Error: miniflow extract parser not changed, PMD thread passed is not valid: 'zero'. Pass a valid pmd thread ID.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 1], [2],\n-[], [dnl\n-Error: no miniflow extract name provided. Output of miniflow-parser-get shows implementation list.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 1 superstudy], [2],\n-[], [dnl\n-Error: unknown miniflow extract implementation superstudy.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set superstudy], [2],\n-[], [dnl\n-Error: unknown miniflow extract implementation superstudy.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set -pmd 1 study -pmd], [2],\n-[], [dnl\n-Error: invalid study_pkt_cnt value: -pmd.\n-ovs-appctl: ovs-vswitchd: server returned an error\n-])\n-\n-OVS_VSWITCHD_STOP([\"dnl\n-/Error: unknown argument 1./d\n-/Error: invalid study_pkt_cnt value: xyz./d\n-/Error: unknown argument abcd./d\n-/Error: -pmd option requires a thread id argument./d\n-/Error: invalid study_pkt_cnt value: abcd./d\n-/Error: miniflow extract parser not changed, PMD thread passed is not valid: 'zero'. Pass a valid pmd thread ID./d\n-/Error: no miniflow extract name provided. Output of miniflow-parser-get shows implementation list./d\n-/Error: unknown miniflow extract implementation superstudy./d\n-/Error: invalid study_pkt_cnt value: -pmd./d\"])\n-AT_CLEANUP\ndiff --git a/tests/genpkts.py b/tests/genpkts.py\ndeleted file mode 100755\nindex 3354e116d..000000000\n--- a/tests/genpkts.py\n+++ /dev/null\n@@ -1,84 +0,0 @@\n-#!/usr/bin/python3\n-\n-import sys\n-import warnings\n-\n-try:\n- from cryptography.utils import CryptographyDeprecationWarning\n- warnings.filterwarnings(\n- \"ignore\",\n- category=CryptographyDeprecationWarning,\n- message=r\"(blowfish|cast5)\",\n- )\n-except ModuleNotFoundError:\n- pass\n-\n-# flake8: noqa: E402\n-from scapy.all import RandMAC, RandIP, PcapWriter, RandIP6, RandShort, fuzz\n-from scapy.all import IPv6, Dot1Q, IP, Ether, UDP, TCP, random\n-\n-# The number of packets generated will be size * 8.\n-size = int(sys.argv[1])\n-# Traffic option is used to choose between fuzzy or simple packet type.\n-if len(sys.argv) > 2:\n- traffic_opt = str(sys.argv[2])\n-else:\n- traffic_opt = \"\"\n-\n-for i in range(0, size):\n- pkt = []\n-\n- if traffic_opt == \"fuzzy\":\n-\n- eth = Ether(src=RandMAC(), dst=RandMAC())\n- vlan = Dot1Q()\n- ipv4 = IP(src=RandIP(), dst=RandIP(), len=random.randint(0, 100))\n- ipv6 = IPv6(src=RandIP6(), dst=RandIP6(), plen=random.randint(0, 100))\n- udp = UDP(dport=RandShort(), sport=RandShort())\n- tcp = TCP(dport=RandShort(), sport=RandShort(), flags='S',\n- dataofs=random.randint(0, 15))\n-\n- # IPv4 packets with fuzzing\n- pkt.append(fuzz(eth / ipv4 / udp).build().hex())\n- pkt.append(fuzz(eth / ipv4 / tcp).build().hex())\n- pkt.append(fuzz(eth / vlan / ipv4 / udp).build().hex())\n- pkt.append(fuzz(eth / vlan / ipv4 / tcp).build().hex())\n-\n- # IPv6 packets with fuzzing\n- pkt.append(fuzz(eth / ipv6 / udp).build().hex())\n- pkt.append(fuzz(eth / ipv6 / tcp).build().hex())\n- pkt.append(fuzz(eth / vlan / ipv6 / udp).build().hex())\n- pkt.append(fuzz(eth / vlan / ipv6 / tcp).build().hex())\n-\n- else:\n- mac_addr_src = \"52:54:00:FF:FF:{:02X}\".format(i % 0xff)\n- mac_addr_dst = \"80:FF:FF:FF:FF:{:02X}\".format(i % 0xff)\n- eth = Ether(src=mac_addr_src, dst=mac_addr_dst)\n- vlan = Dot1Q(vlan=(i % 10))\n- # IPv4 address range limits to 255 and IPv6 limit to 65535\n- ipv4_addr_src = \"192.168.150.\" + str((i % 255))\n- ipv4_addr_dst = \"200.100.198.\" + str((i % 255))\n- ipv6_addr_src = \"2001:0db8:85a3:0000:0000:8a2e:0370:{:04x}\" \\\n- .format(i % 0xffff)\n- ipv6_addr_dst = \"3021:ffff:85a3:ffff:0000:8a2e:0480:{:04x}\" \\\n- .format(i % 0xffff)\n- ipv4 = IP(src=ipv4_addr_src, dst=ipv4_addr_dst)\n- ipv6 = IPv6(src=ipv6_addr_src, dst=ipv6_addr_dst)\n- src_port = 200 + (i % 20)\n- dst_port = 1000 + (i % 20)\n- udp = UDP(dport=src_port, sport=dst_port)\n- tcp = TCP(dport=src_port, sport=dst_port, flags='S')\n-\n- # IPv4 packets\n- pkt.append((eth / ipv4 / udp).build().hex())\n- pkt.append((eth / ipv4 / tcp).build().hex())\n- pkt.append((eth / vlan / ipv4 / udp).build().hex())\n- pkt.append((eth / vlan / ipv4 / tcp).build().hex())\n-\n- # IPv6 packets\n- pkt.append((eth / ipv6 / udp).build().hex())\n- pkt.append((eth / ipv6 / tcp).build().hex())\n- pkt.append((eth / vlan / ipv6 / udp).build().hex())\n- pkt.append((eth / vlan / ipv6 / tcp).build().hex())\n-\n- print(' '.join(pkt))\ndiff --git a/tests/pmd.at b/tests/pmd.at\nindex 8254ac3b0..19698f3e9 100644\n--- a/tests/pmd.at\n+++ b/tests/pmd.at\n@@ -440,13 +440,12 @@ dummy@ovs-dummy: hit:0 missed:0\n p0 7/1: (dummy-pmd: n_rxq=4, n_txq=1, numa_id=0)\n ])\n \n-AT_CHECK([ovs-appctl dpif-netdev/pmd-stats-show | sed SED_NUMA_CORE_PATTERN | sed '/cycles/d' | grep pmd -A 12], [0], [dnl\n+AT_CHECK([ovs-appctl dpif-netdev/pmd-stats-show | sed SED_NUMA_CORE_PATTERN | sed '/cycles/d' | grep pmd -A 11], [0], [dnl\n pmd thread numa_id <cleared> core_id <cleared>:\n packets received: 0\n packet recirculations: 0\n avg. datapath passes per packet: 0.00\n phwol hits: 0\n- mfex opt hits: 0\n simple match hits: 0\n emc hits: 0\n smc hits: 0\n@@ -474,13 +473,12 @@ AT_CHECK([cat ovs-vswitchd.log | filter_flow_install | strip_xout], [0], [dnl\n recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:77,dst=50:54:00:00:01:78),eth_type(0x0800),ipv4(frag=no), actions: <del>\n ])\n \n-AT_CHECK([ovs-appctl dpif-netdev/pmd-stats-show | sed SED_NUMA_CORE_PATTERN | sed '/cycles/d' | grep pmd -A 12], [0], [dnl\n+AT_CHECK([ovs-appctl dpif-netdev/pmd-stats-show | sed SED_NUMA_CORE_PATTERN | sed '/cycles/d' | grep pmd -A 11], [0], [dnl\n pmd thread numa_id <cleared> core_id <cleared>:\n packets received: 20\n packet recirculations: 0\n avg. datapath passes per packet: 1.00\n phwol hits: 0\n- mfex opt hits: 0\n simple match hits: 0\n emc hits: 19\n smc hits: 0\n", "prefixes": [ "ovs-dev", "2/6" ] }