get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 139205,
    "url": "http://patches.dpdk.org/api/patches/139205/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20240409034237.433270-7-stephen@networkplumber.org/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20240409034237.433270-7-stephen@networkplumber.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20240409034237.433270-7-stephen@networkplumber.org",
    "date": "2024-04-09T03:40:35",
    "name": "[v8,6/8] net/tap: use libbpf to load new BPF program",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "b3248835ee9651731db7fcb1a23833cb52ecefc0",
    "submitter": {
        "id": 27,
        "url": "http://patches.dpdk.org/api/people/27/?format=api",
        "name": "Stephen Hemminger",
        "email": "stephen@networkplumber.org"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20240409034237.433270-7-stephen@networkplumber.org/mbox/",
    "series": [
        {
            "id": 31709,
            "url": "http://patches.dpdk.org/api/series/31709/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=31709",
            "date": "2024-04-09T03:40:29",
            "name": "net/tap: cleanups and fix BPF support",
            "version": 8,
            "mbox": "http://patches.dpdk.org/series/31709/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/139205/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/139205/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 582CE43DD9;\n\tTue,  9 Apr 2024 05:43:32 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9753940A6E;\n\tTue,  9 Apr 2024 05:42:52 +0200 (CEST)",
            "from mail-oo1-f41.google.com (mail-oo1-f41.google.com\n [209.85.161.41]) by mails.dpdk.org (Postfix) with ESMTP id C518A4064C\n for <dev@dpdk.org>; Tue,  9 Apr 2024 05:42:44 +0200 (CEST)",
            "by mail-oo1-f41.google.com with SMTP id\n 006d021491bc7-5a9c875ceecso2887226eaf.2\n for <dev@dpdk.org>; Mon, 08 Apr 2024 20:42:44 -0700 (PDT)",
            "from hermes.lan (204-195-96-226.wavecable.com. [204.195.96.226])\n by smtp.gmail.com with ESMTPSA id\n gm24-20020a17090b101800b0029de90f4d44sm9238197pjb.9.2024.04.08.20.42.43\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 08 Apr 2024 20:42:43 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1712634164;\n x=1713238964; darn=dpdk.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=HKuONV9auvfmV0T0X8du4A4Xa1oiOMLKffvxuF8LHTI=;\n b=GHxT7rk4T7ovJ7VH1iUlYPEkHUTG7DuaiMEQsZffV81nLpTEMKcp0HhehGq8NUCeO7\n xTTEvRWqhobBuBp8Nyt0GaCsBJ4h0F4jkMrLuSlBLQUgCGYwfprux0xLRx0NcbfN4lvD\n UjlxzaUipJAj5o9TjiCxjjPQT6u9AuNa8GAp5/TUguD/G4vFPkEp+dmh/36tco8PKr/Y\n 8d689Cx2loak2ZLwGX8pICItxbNp8kDKojhQ9d02UACYbj4Ak/VzVjZw6zNavaME9kJb\n jgGQARgVAmWe/tFiKEgB0G92svZQkcJP9I76+/NsiVla6lKuVzqv1RkLhqB2CJE5hJx4\n N0sQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1712634164; x=1713238964;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=HKuONV9auvfmV0T0X8du4A4Xa1oiOMLKffvxuF8LHTI=;\n b=WxBWpMByuxZ34b0TPNo90T/AUOFyxOQ31fEVRZueGImjmW1WrZvapYQHE11rWW9ykR\n mgvot+KzQPwhqhb2fMzLRiISQY8ekX74Fsi2uvnok1rPk4y0TbqhFyPa54ViFVki6DCY\n jMEnpVcka2fPuseV733qiQa+LJ+HgjrqhMYm0VMHP8I3N40XRORN/kX1qHHhhqRxmHxF\n EPfySioWBDySIduBCUmJ6zz870KsfAB16CDmCNx8qMnFcIx8jGl61vKj3WoNGS1UMQBm\n J2SU9AA6Y9IKFGtRDven57eZ7HF/urh3fXYBlTpudfAa2khzKRh876xbQu0pbA9FVkIf\n CCKg==",
        "X-Gm-Message-State": "AOJu0YzGVrUnRxu2Fd7Cv1oZfC/2zAO5zxwAR5sXyxEbmrFV7+BZyGA2\n Uy8HskEUbeepaTk4HJXdCZit65fDtbGtV76doBj7MMxUGKUu0Q6VSPaCu8upwDbOyhWHU4E4osQ\n KlsQ=",
        "X-Google-Smtp-Source": "\n AGHT+IE5LezNMIocio/8uLg+QsVxYq5wJ0tvYJcQIrFcYdinkW3yl6hX3YjH+YFW/nUmhmTI+53slQ==",
        "X-Received": "by 2002:a05:6358:9817:b0:17f:1d00:62b6 with SMTP id\n y23-20020a056358981700b0017f1d0062b6mr9939194rwa.31.1712634163896;\n Mon, 08 Apr 2024 20:42:43 -0700 (PDT)",
        "From": "Stephen Hemminger <stephen@networkplumber.org>",
        "To": "dev@dpdk.org",
        "Cc": "Stephen Hemminger <stephen@networkplumber.org>",
        "Subject": "[PATCH v8 6/8] net/tap: use libbpf to load new BPF program",
        "Date": "Mon,  8 Apr 2024 20:40:35 -0700",
        "Message-ID": "<20240409034237.433270-7-stephen@networkplumber.org>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20240409034237.433270-1-stephen@networkplumber.org>",
        "References": "<20240130034925.44869-1-stephen@networkplumber.org>\n <20240409034237.433270-1-stephen@networkplumber.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "There were multiple issues in the RSS queue support in the TAP\ndriver. This required extensive rework of the BPF support.\n\nChange the BPF loading to use bpftool to\ncreate a skeleton header file, and load with libbpf.\nThe BPF is always compiled from source so less chance that\nsource and instructions diverge. Also resolves issue where\nlibbpf and source get out of sync. The program\nis only loaded once, so if multiple rules are created\nonly one BPF program is loaded in kernel.\n\nThe new BPF program only needs a single action.\nNo need for action and re-classification step.\n\nIt also fixes the missing bits from the original.\n    - supports setting RSS key per flow\n    - level of hash can be L3 or L3/L4.\n\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n drivers/net/tap/bpf/meson.build |  36 ++-\n drivers/net/tap/bpf/tap_rss.c   |  45 ++--\n drivers/net/tap/meson.build     |  35 ++-\n drivers/net/tap/rte_eth_tap.c   |  14 +-\n drivers/net/tap/rte_eth_tap.h   |   6 +-\n drivers/net/tap/tap_flow.c      | 418 ++++++++------------------------\n drivers/net/tap/tap_flow.h      |  17 +-\n drivers/net/tap/tap_rss.h       |  10 +-\n drivers/net/tap/tap_tcmsgs.h    |   4 +-\n 9 files changed, 189 insertions(+), 396 deletions(-)",
    "diff": "diff --git a/drivers/net/tap/bpf/meson.build b/drivers/net/tap/bpf/meson.build\nindex f2c03a19fd..45e8c3b498 100644\n--- a/drivers/net/tap/bpf/meson.build\n+++ b/drivers/net/tap/bpf/meson.build\n@@ -1,17 +1,26 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright 2024 Stephen Hemminger <stephen@networkplumber.org>\n \n-enable_tap_rss = false\n-\n-libbpf = dependency('libbpf', required: false, method: 'pkg-config')\n+# Loading BPF requires libbpf\n+# and the bpf_map__XXX API's were introduced in 0.8.0\n+libbpf = dependency('libbpf', version: '>= 1.0',\n+                    required: false, method: 'pkg-config')\n if not libbpf.found()\n     message('net/tap: no RSS support missing libbpf')\n     subdir_done()\n endif\n \n+# Making skeleton needs bpftool\n # Debian install this in /usr/sbin which is not in $PATH\n-bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false, version: '>= 5.6.0')\n-if not bpftool.found()\n+bpftool_supports_skel = false\n+bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false)\n+if bpftool.found()\n+    # Some Ubuntu versions have non-functional bpftool\n+    bpftool_supports_skel = run_command(bpftool, 'gen', 'help',\n+                                        check:false).returncode() == 0\n+endif\n+\n+if not bpftool_supports_skel\n     message('net/tap: no RSS support missing bpftool')\n     subdir_done()\n endif\n@@ -42,6 +51,7 @@ clang_flags = [\n     '-O2',\n     '-Wall',\n     '-Wextra',\n+    max_queues,\n     '-target',\n     'bpf',\n     '-g',\n@@ -67,6 +77,22 @@ skel_h_cmd = [\n     '@INPUT@'\n ]\n \n+vmlinux_h_cmd = [\n+    bpftool,\n+    'btf',\n+    'dump',\n+    'file',\n+    '/sys/kernel/btf/vmlinux',\n+    'format',\n+    'c'\n+]\n+\n+vmlinux_h = custom_target(\n+    'vmlinux.h',\n+    output: 'vmlinux.h',\n+    command: vmlinux_h_cmd,\n+    capture: true)\n+\n tap_rss_o = custom_target(\n     'tap_rss.bpf.o',\n     input: 'tap_rss.c',\ndiff --git a/drivers/net/tap/bpf/tap_rss.c b/drivers/net/tap/bpf/tap_rss.c\nindex 888b3bdc24..1d71941c53 100644\n--- a/drivers/net/tap/bpf/tap_rss.c\n+++ b/drivers/net/tap/bpf/tap_rss.c\n@@ -203,23 +203,6 @@ parse_ipv6(const struct __sk_buff *skb, __u32 hash_type, const __u32 *key)\n \treturn 0;\n }\n \n-/*\n- * Compute RSS hash for packets.\n- * Returns 0 if no hash is possible.\n- */\n-static __u32 __attribute__((always_inline))\n-calculate_rss_hash(const struct __sk_buff *skb, const struct rss_key *rsskey)\n-{\n-\tconst __u32 *key = (const __u32 *)rsskey->key;\n-\n-\tif (skb->protocol == bpf_htons(ETH_P_IP))\n-\t\treturn parse_ipv4(skb, rsskey->hash_fields, key);\n-\telse if (skb->protocol == bpf_htons(ETH_P_IPV6))\n-\t\treturn parse_ipv6(skb, rsskey->hash_fields, key);\n-\telse\n-\t\treturn 0;\n-}\n-\n /*\n  * Scale value to be into range [0, n)\n  * Assumes val is large (ie hash covers whole u32 range)\n@@ -244,20 +227,40 @@ SEC(\"action\") int\n rss_flow_action(struct __sk_buff *skb)\n {\n \tconst struct rss_key *rsskey;\n-\t__u32 mark = skb->mark;\n+\tconst __u32 *key;\n+\t__be16 proto;\n+\t__u32 mark;\n \t__u32 hash;\n+\t__u16 queue;\n+\n+\t__builtin_preserve_access_index(({\n+\t\tmark = skb->mark;\n+\t\tproto = skb->protocol;\n+\t}));\n \n \t/* Lookup RSS configuration for that BPF class */\n \trsskey = bpf_map_lookup_elem(&rss_map, &mark);\n \tif (rsskey == NULL)\n \t\treturn TC_ACT_OK;\n \n-\thash = calculate_rss_hash(skb, rsskey);\n-\tif (!hash)\n+\tkey = (const __u32 *)rsskey->key;\n+\n+\tif (proto == bpf_htons(ETH_P_IP))\n+\t\thash = parse_ipv4(skb, rsskey->hash_fields, key);\n+\telse if (proto == bpf_htons(ETH_P_IPV6))\n+\t\thash = parse_ipv6(skb, rsskey->hash_fields, key);\n+\telse\n+\t\thash = 0;\n+\n+\tif (hash == 0)\n \t\treturn TC_ACT_OK;\n \n \t/* Fold hash to the number of queues configured */\n-\tskb->queue_mapping = reciprocal_scale(hash, rsskey->nb_queues);\n+\tqueue = reciprocal_scale(hash, rsskey->nb_queues);\n+\n+\t__builtin_preserve_access_index(({\n+\t\tskb->queue_mapping = queue;\n+\t}));\n \treturn TC_ACT_PIPE;\n }\n \ndiff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build\nindex 1fd20cfe93..26074059fa 100644\n--- a/drivers/net/tap/meson.build\n+++ b/drivers/net/tap/meson.build\n@@ -5,36 +5,33 @@ if not is_linux\n     build = false\n     reason = 'only supported on Linux'\n endif\n+\n sources = files(\n         'rte_eth_tap.c',\n         'tap_intr.c',\n         'tap_netlink.c',\n )\n \n+deps = ['bus_vdev', 'gso', 'hash']\n+\n+max_queues = '-DTAP_MAX_QUEUES=16'\n+cflags += max_queues\n+\n+require_iova_in_mbuf = false\n+\n if cc.has_header_symbol('linux/pkt_cls.h', 'TCA_FLOWER_ACT')\n     cflags += '-DHAVE_TCA_FLOWER'\n     sources += files(\n-        'tap_bpf_api.c',\n         'tap_flow.c',\n         'tap_tcmsgs.c',\n     )\n-endif\n-\n-deps = ['bus_vdev', 'gso', 'hash']\n \n-cflags += '-DTAP_MAX_QUEUES=8'\n-\n-# input array for meson symbol search:\n-# [ \"MACRO to define if found\", \"header for the search\",\n-#   \"enum/define\", \"symbol to search\" ]\n-#\n-args = [\n-        [ 'HAVE_TC_ACT_BPF', 'linux/tc_act/tc_bpf.h', 'TCA_ACT_BPF_UNSPEC' ],\n-]\n-config = configuration_data()\n-foreach arg:args\n-    config.set(arg[0], cc.has_header_symbol(arg[1], arg[2]))\n-endforeach\n-configure_file(output : 'tap_autoconf.h', configuration : config)\n+    enable_tap_rss = false\n \n-require_iova_in_mbuf = false\n+    subdir('bpf')\n+    if enable_tap_rss\n+        cflags += '-DHAVE_BPF_RSS'\n+        ext_deps += libbpf\n+        sources += tap_rss_skel_h\n+    endif\n+endif\ndiff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c\nindex 3f4fe95a09..793730de08 100644\n--- a/drivers/net/tap/rte_eth_tap.c\n+++ b/drivers/net/tap/rte_eth_tap.c\n@@ -1131,6 +1131,7 @@ tap_dev_close(struct rte_eth_dev *dev)\n \t\ttap_flow_implicit_flush(internals, NULL);\n \t\ttap_nl_final(internals->nlsk_fd);\n \t\tinternals->nlsk_fd = -1;\n+\t\ttap_flow_bpf_destroy(internals);\n \t}\n #endif\n \n@@ -1956,6 +1957,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,\n \tstrlcpy(pmd->name, tap_name, sizeof(pmd->name));\n \tpmd->type = type;\n \tpmd->ka_fd = -1;\n+\n #ifdef HAVE_TCA_FLOWER\n \tpmd->nlsk_fd = -1;\n #endif\n@@ -2038,13 +2040,6 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,\n \t/* Make network device persist after application exit */\n \tpmd->persist = persist;\n \n-\tpmd->if_index = if_nametoindex(pmd->name);\n-\tif (!pmd->if_index) {\n-\t\tTAP_LOG(ERR, \"%s: failed to get if_index.\", pmd->name);\n-\t\tgoto disable_rte_flow;\n-\t}\n-\n-\n #ifdef HAVE_TCA_FLOWER\n \t/*\n \t * Set up everything related to rte_flow:\n@@ -2060,6 +2055,11 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,\n \t\t\tpmd->name);\n \t\tgoto disable_rte_flow;\n \t}\n+\tpmd->if_index = if_nametoindex(pmd->name);\n+\tif (!pmd->if_index) {\n+\t\tTAP_LOG(ERR, \"%s: failed to get if_index.\", pmd->name);\n+\t\tgoto disable_rte_flow;\n+\t}\n \tif (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) {\n \t\tTAP_LOG(ERR, \"%s: failed to create multiq qdisc.\",\n \t\t\tpmd->name);\ndiff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h\nindex af18b29090..ce4322ad04 100644\n--- a/drivers/net/tap/rte_eth_tap.h\n+++ b/drivers/net/tap/rte_eth_tap.h\n@@ -81,10 +81,8 @@ struct pmd_internals {\n #ifdef HAVE_TCA_FLOWER\n \tint nlsk_fd;                      /* Netlink socket fd */\n \tint flow_isolate;                 /* 1 if flow isolation is enabled */\n-\tint rss_enabled;                  /* 1 if RSS is enabled, else 0 */\n-\t/* implicit rules set when RSS is enabled */\n-\tint map_fd;                       /* BPF RSS map fd */\n-\tint bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */\n+\n+\tstruct tap_rss *rss;\t\t  /* BPF program */\n \n \tLIST_HEAD(tap_flows, rte_flow) flows;        /* rte_flow rules */\n \t/* implicit rte_flow rules set when a remote device is active */\ndiff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c\nindex 5a5a4ea048..322153d806 100644\n--- a/drivers/net/tap/tap_flow.c\n+++ b/drivers/net/tap/tap_flow.c\n@@ -15,25 +15,19 @@\n #include <rte_random.h>\n #include <rte_malloc.h>\n #include <rte_eth_tap.h>\n+#include <rte_uuid.h>\n \n #include <tap_flow.h>\n-#include <tap_autoconf.h>\n #include <tap_tcmsgs.h>\n #include <tap_rss.h>\n \n-/* RSS key management */\n-enum bpf_rss_key_e {\n-\tKEY_CMD_GET = 1,\n-\tKEY_CMD_RELEASE,\n-\tKEY_CMD_INIT,\n-\tKEY_CMD_DEINIT,\n-};\n-\n-enum key_status_e {\n-\tKEY_STAT_UNSPEC,\n-\tKEY_STAT_USED,\n-\tKEY_STAT_AVAILABLE,\n-};\n+#ifdef HAVE_BPF_RSS\n+/* Workaround for warning in bpftool generated skeleton code */\n+#pragma GCC diagnostic push\n+#pragma GCC diagnostic ignored \"-Wcast-qual\"\n+#include \"tap_rss.skel.h\"\n+#pragma GCC diagnostic pop\n+#endif\n \n #define ISOLATE_HANDLE 1\n #define REMOTE_PROMISCUOUS_HANDLE 2\n@@ -41,8 +35,6 @@ enum key_status_e {\n struct rte_flow {\n \tLIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */\n \tstruct rte_flow *remote_flow; /* associated remote flow */\n-\tint bpf_fd[SEC_MAX]; /* list of bfs fds per ELF section */\n-\tuint32_t key_idx; /* RSS rule key index into BPF map */\n \tstruct nlmsg msg;\n };\n \n@@ -69,12 +61,16 @@ struct action_data {\n \t\tstruct skbedit {\n \t\t\tstruct tc_skbedit skbedit;\n \t\t\tuint16_t queue;\n+\t\t\tuint32_t mark;\n \t\t} skbedit;\n+#ifdef HAVE_BPF_RSS\n \t\tstruct bpf {\n \t\t\tstruct tc_act_bpf bpf;\n+\t\t\tuint32_t map_key;\n \t\t\tint bpf_fd;\n \t\t\tconst char *annotation;\n \t\t} bpf;\n+#endif\n \t};\n };\n \n@@ -112,13 +108,12 @@ tap_flow_isolate(struct rte_eth_dev *dev,\n \t\t int set,\n \t\t struct rte_flow_error *error);\n \n-static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx);\n-static int rss_enable(struct pmd_internals *pmd,\n-\t\t\tconst struct rte_flow_attr *attr,\n-\t\t\tstruct rte_flow_error *error);\n+#ifdef HAVE_BPF_RSS\n+static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error *error);\n static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,\n \t\t\tconst struct rte_flow_action_rss *rss,\n \t\t\tstruct rte_flow_error *error);\n+#endif\n \n static const struct rte_flow_ops tap_flow_ops = {\n \t.validate = tap_flow_validate,\n@@ -853,11 +848,14 @@ add_action(struct rte_flow *flow, size_t *act_index, struct action_data *adata)\n \t\t\t   &adata->mirred);\n \t} else if (strcmp(\"skbedit\", adata->id) == 0) {\n \t\ttap_nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS,\n-\t\t\t   sizeof(adata->skbedit.skbedit),\n-\t\t\t   &adata->skbedit.skbedit);\n-\t\ttap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING,\n-\t\t\t     adata->skbedit.queue);\n-\t} else if (strcmp(\"bpf\", adata->id) == 0) {\n+\t\t\t   sizeof(adata->skbedit.skbedit), &adata->skbedit.skbedit);\n+\t\tif (adata->skbedit.mark)\n+\t\t\ttap_nlattr_add32(&msg->nh, TCA_SKBEDIT_MARK, adata->skbedit.mark);\n+\t\telse\n+\t\t\ttap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, adata->skbedit.queue);\n+\t}\n+#ifdef HAVE_BPF_RSS\n+\telse if (strcmp(\"bpf\", adata->id) == 0) {\n \t\ttap_nlattr_add32(&msg->nh, TCA_ACT_BPF_FD, adata->bpf.bpf_fd);\n \t\ttap_nlattr_add(&msg->nh, TCA_ACT_BPF_NAME,\n \t\t\t   strlen(adata->bpf.annotation) + 1,\n@@ -865,7 +863,9 @@ add_action(struct rte_flow *flow, size_t *act_index, struct action_data *adata)\n \t\ttap_nlattr_add(&msg->nh, TCA_ACT_BPF_PARMS,\n \t\t\t   sizeof(adata->bpf.bpf),\n \t\t\t   &adata->bpf.bpf);\n-\t} else {\n+\t}\n+#endif\n+\telse {\n \t\treturn -1;\n \t}\n \ttap_nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */\n@@ -1104,8 +1104,7 @@ priv_flow_process(struct pmd_internals *pmd,\n \t\t\t\t\t},\n \t\t\t\t};\n \n-\t\t\t\terr = add_actions(flow, 1, &adata,\n-\t\t\t\t\t\t  TCA_FLOWER_ACT);\n+\t\t\t\terr = add_actions(flow, 1, &adata, TCA_FLOWER_ACT);\n \t\t\t}\n \t\t} else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {\n \t\t\tconst struct rte_flow_action_queue *queue =\n@@ -1135,6 +1134,7 @@ priv_flow_process(struct pmd_internals *pmd,\n \t\t\t\terr = add_actions(flow, 1, &adata,\n \t\t\t\t\tTCA_FLOWER_ACT);\n \t\t\t}\n+#ifdef HAVE_BPF_RSS\n \t\t} else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {\n \t\t\tconst struct rte_flow_action_rss *rss =\n \t\t\t\t(const struct rte_flow_action_rss *)\n@@ -1143,13 +1143,14 @@ priv_flow_process(struct pmd_internals *pmd,\n \t\t\tif (action++)\n \t\t\t\tgoto exit_action_not_supported;\n \n-\t\t\tif (!pmd->rss_enabled) {\n-\t\t\t\terr = rss_enable(pmd, attr, error);\n+\t\t\tif (pmd->rss == NULL) {\n+\t\t\t\terr = rss_enable(pmd, error);\n \t\t\t\tif (err)\n \t\t\t\t\tgoto exit_return_error;\n \t\t\t}\n \t\t\tif (flow)\n \t\t\t\terr = rss_add_actions(flow, pmd, rss, error);\n+#endif\n \t\t} else {\n \t\t\tgoto exit_action_not_supported;\n \t\t}\n@@ -1246,26 +1247,17 @@ tap_flow_set_handle(struct rte_flow *flow)\n  *\n  */\n static void\n-tap_flow_free(struct pmd_internals *pmd, struct rte_flow *flow)\n+tap_flow_free(struct pmd_internals *pmd __rte_unused, struct rte_flow *flow)\n {\n-\tint i;\n-\n \tif (!flow)\n \t\treturn;\n \n-\tif (pmd->rss_enabled) {\n-\t\t/* Close flow BPF file descriptors */\n-\t\tfor (i = 0; i < SEC_MAX; i++)\n-\t\t\tif (flow->bpf_fd[i] != 0) {\n-\t\t\t\tclose(flow->bpf_fd[i]);\n-\t\t\t\tflow->bpf_fd[i] = 0;\n-\t\t\t}\n-\n-\t\t/* Release the map key for this RSS rule */\n-\t\tbpf_rss_key(KEY_CMD_RELEASE, &flow->key_idx);\n-\t\tflow->key_idx = 0;\n-\t}\n-\n+#ifdef HAVE_BPF_RSS\n+\tstruct tap_rss *rss = pmd->rss;\n+\tif (rss)\n+\t\tbpf_map__delete_elem(rss->maps.rss_map,\n+\t\t\t\t     &flow->msg.t.tcm_handle, sizeof(uint32_t), 0);\n+#endif\n \t/* Free flow allocated memory */\n \trte_free(flow);\n }\n@@ -1733,14 +1725,18 @@ tap_flow_implicit_flush(struct pmd_internals *pmd, struct rte_flow_error *error)\n \treturn 0;\n }\n \n-#define MAX_RSS_KEYS 256\n-#define KEY_IDX_OFFSET (3 * MAX_RSS_KEYS)\n-#define SEC_NAME_CLS_Q \"cls_q\"\n-\n-static const char *sec_name[SEC_MAX] = {\n-\t[SEC_L3_L4] = \"l3_l4\",\n-};\n+/**\n+ * Cleanup when device is closed\n+ */\n+void tap_flow_bpf_destroy(struct pmd_internals *pmd __rte_unused)\n+{\n+#ifdef HAVE_BPF_RSS\n+\ttap_rss__destroy(pmd->rss);\n+\tpmd->rss = NULL;\n+#endif\n+}\n \n+#ifdef HAVE_BPF_RSS\n /**\n  * Enable RSS on tap: create TC rules for queuing.\n  *\n@@ -1755,225 +1751,32 @@ static const char *sec_name[SEC_MAX] = {\n  *\n  * @return 0 on success, negative value on failure.\n  */\n-static int rss_enable(struct pmd_internals *pmd,\n-\t\t\tconst struct rte_flow_attr *attr,\n-\t\t\tstruct rte_flow_error *error)\n+static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error *error)\n {\n-\tstruct rte_flow *rss_flow = NULL;\n-\tstruct nlmsg *msg = NULL;\n-\t/* 4096 is the maximum number of instructions for a BPF program */\n-\tchar annotation[64];\n-\tint i;\n-\tint err = 0;\n-\n-\t/* unlimit locked memory */\n-\tstruct rlimit memlock_limit = {\n-\t\t.rlim_cur = RLIM_INFINITY,\n-\t\t.rlim_max = RLIM_INFINITY,\n-\t};\n-\tsetrlimit(RLIMIT_MEMLOCK, &memlock_limit);\n-\n-\t /* Get a new map key for a new RSS rule */\n-\terr = bpf_rss_key(KEY_CMD_INIT, NULL);\n-\tif (err < 0) {\n-\t\trte_flow_error_set(\n-\t\t\terror, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n-\t\t\t\"Failed to initialize BPF RSS keys\");\n-\n-\t\treturn -1;\n-\t}\n-\n-\t/*\n-\t *  Create BPF RSS MAP\n-\t */\n-\tpmd->map_fd = tap_flow_bpf_rss_map_create(sizeof(__u32), /* key size */\n-\t\t\t\tsizeof(struct rss_key),\n-\t\t\t\tMAX_RSS_KEYS);\n-\tif (pmd->map_fd < 0) {\n-\t\tTAP_LOG(ERR,\n-\t\t\t\"Failed to create BPF map (%d): %s\",\n-\t\t\t\terrno, strerror(errno));\n-\t\trte_flow_error_set(\n-\t\t\terror, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n-\t\t\t\"Kernel too old or not configured \"\n-\t\t\t\"to support BPF maps\");\n+\tint err;\n \n-\t\treturn -ENOTSUP;\n+\t/* Load the BPF program (defined in tap_bpf.h from skeleton) */\n+\tpmd->rss = tap_rss__open_and_load();\n+\tif (pmd->rss == NULL) {\n+\t\tTAP_LOG(ERR, \"Failed to load BPF object: %s\", strerror(errno));\n+\t\trte_flow_error_set(error, errno, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\"BPF object could not be loaded\");\n+\t\treturn -errno;\n \t}\n \n-\t/*\n-\t * Add a rule per queue to match reclassified packets and direct them to\n-\t * the correct queue.\n-\t */\n-\tfor (i = 0; i < pmd->dev->data->nb_rx_queues; i++) {\n-\t\tpmd->bpf_fd[i] = tap_flow_bpf_cls_q(i);\n-\t\tif (pmd->bpf_fd[i] < 0) {\n-\t\t\tTAP_LOG(ERR,\n-\t\t\t\t\"Failed to load BPF section %s for queue %d\",\n-\t\t\t\tSEC_NAME_CLS_Q, i);\n-\t\t\trte_flow_error_set(\n-\t\t\t\terror, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,\n-\t\t\t\tNULL,\n-\t\t\t\t\"Kernel too old or not configured \"\n-\t\t\t\t\"to support BPF programs loading\");\n-\n-\t\t\treturn -ENOTSUP;\n-\t\t}\n-\n-\t\trss_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0);\n-\t\tif (!rss_flow) {\n-\t\t\tTAP_LOG(ERR,\n-\t\t\t\t\"Cannot allocate memory for rte_flow\");\n-\t\t\treturn -1;\n-\t\t}\n-\t\tmsg = &rss_flow->msg;\n-\t\ttc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER, NLM_F_REQUEST |\n-\t\t\t    NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE);\n-\t\tmsg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL));\n-\t\ttap_flow_set_handle(rss_flow);\n-\t\tuint16_t group = attr->group << GROUP_SHIFT;\n-\t\tuint16_t prio = group | (i + PRIORITY_OFFSET);\n-\t\tmsg->t.tcm_info = TC_H_MAKE(prio << 16, msg->t.tcm_info);\n-\t\tmsg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0);\n-\n-\t\ttap_nlattr_add(&msg->nh, TCA_KIND, sizeof(\"bpf\"), \"bpf\");\n-\t\tif (tap_nlattr_nested_start(msg, TCA_OPTIONS) < 0)\n-\t\t\treturn -1;\n-\t\ttap_nlattr_add32(&msg->nh, TCA_BPF_FD, pmd->bpf_fd[i]);\n-\t\tsnprintf(annotation, sizeof(annotation), \"[%s%d]\",\n-\t\t\tSEC_NAME_CLS_Q, i);\n-\t\ttap_nlattr_add(&msg->nh, TCA_BPF_NAME, strlen(annotation) + 1,\n-\t\t\t   annotation);\n-\t\t/* Actions */\n-\t\t{\n-\t\t\tstruct action_data adata = {\n-\t\t\t\t.id = \"skbedit\",\n-\t\t\t\t.skbedit = {\n-\t\t\t\t\t.skbedit = {\n-\t\t\t\t\t\t.action = TC_ACT_PIPE,\n-\t\t\t\t\t},\n-\t\t\t\t\t.queue = i,\n-\t\t\t\t},\n-\t\t\t};\n-\t\t\tif (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) < 0)\n-\t\t\t\treturn -1;\n-\t\t}\n-\t\ttap_nlattr_nested_finish(msg); /* nested TCA_OPTIONS */\n-\n-\t\t/* Netlink message is now ready to be sent */\n-\t\tif (tap_nl_send(pmd->nlsk_fd, &msg->nh) < 0)\n-\t\t\treturn -1;\n-\t\terr = tap_nl_recv_ack(pmd->nlsk_fd);\n-\t\tif (err < 0) {\n-\t\t\tTAP_LOG(ERR,\n-\t\t\t\t\"Kernel refused TC filter rule creation (%d): %s\",\n-\t\t\t\terrno, strerror(errno));\n-\t\t\treturn err;\n-\t\t}\n-\t}\n-\n-\tpmd->rss_enabled = 1;\n-\treturn err;\n-}\n-\n-/**\n- * Manage bpf RSS keys repository with operations: init, get, release\n- *\n- * @param[in] cmd\n- *   Command on RSS keys: init, get, release\n- *\n- * @param[in, out] key_idx\n- *   Pointer to RSS Key index (out for get command, in for release command)\n- *\n- * @return -1 if couldn't get, release or init the RSS keys, 0 otherwise.\n- */\n-static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx)\n-{\n-\t__u32 i;\n-\tint err = 0;\n-\tstatic __u32 num_used_keys;\n-\tstatic __u32 rss_keys[MAX_RSS_KEYS] = {KEY_STAT_UNSPEC};\n-\tstatic __u32 rss_keys_initialized;\n-\t__u32 key;\n-\n-\tswitch (cmd) {\n-\tcase KEY_CMD_GET:\n-\t\tif (!rss_keys_initialized) {\n-\t\t\terr = -1;\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (num_used_keys == RTE_DIM(rss_keys)) {\n-\t\t\terr = -1;\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\t*key_idx = num_used_keys % RTE_DIM(rss_keys);\n-\t\twhile (rss_keys[*key_idx] == KEY_STAT_USED)\n-\t\t\t*key_idx = (*key_idx + 1) % RTE_DIM(rss_keys);\n-\n-\t\trss_keys[*key_idx] = KEY_STAT_USED;\n-\n-\t\t/*\n-\t\t * Add an offset to key_idx in order to handle a case of\n-\t\t * RSS and non RSS flows mixture.\n-\t\t * If a non RSS flow is destroyed it has an eBPF map\n-\t\t * index 0 (initialized on flow creation) and might\n-\t\t * unintentionally remove RSS entry 0 from eBPF map.\n-\t\t * To avoid this issue, add an offset to the real index\n-\t\t * during a KEY_CMD_GET operation and subtract this offset\n-\t\t * during a KEY_CMD_RELEASE operation in order to restore\n-\t\t * the real index.\n-\t\t */\n-\t\t*key_idx += KEY_IDX_OFFSET;\n-\t\tnum_used_keys++;\n-\tbreak;\n-\n-\tcase KEY_CMD_RELEASE:\n-\t\tif (!rss_keys_initialized)\n-\t\t\tbreak;\n-\n-\t\t/*\n-\t\t * Subtract offset to restore real key index\n-\t\t * If a non RSS flow is falsely trying to release map\n-\t\t * entry 0 - the offset subtraction will calculate the real\n-\t\t * map index as an out-of-range value and the release operation\n-\t\t * will be silently ignored.\n-\t\t */\n-\t\tkey = *key_idx - KEY_IDX_OFFSET;\n-\t\tif (key >= RTE_DIM(rss_keys))\n-\t\t\tbreak;\n-\n-\t\tif (rss_keys[key] == KEY_STAT_USED) {\n-\t\t\trss_keys[key] = KEY_STAT_AVAILABLE;\n-\t\t\tnum_used_keys--;\n-\t\t}\n-\tbreak;\n-\n-\tcase KEY_CMD_INIT:\n-\t\tfor (i = 0; i < RTE_DIM(rss_keys); i++)\n-\t\t\trss_keys[i] = KEY_STAT_AVAILABLE;\n-\n-\t\trss_keys_initialized = 1;\n-\t\tnum_used_keys = 0;\n-\tbreak;\n-\n-\tcase KEY_CMD_DEINIT:\n-\t\tfor (i = 0; i < RTE_DIM(rss_keys); i++)\n-\t\t\trss_keys[i] = KEY_STAT_UNSPEC;\n-\n-\t\trss_keys_initialized = 0;\n-\t\tnum_used_keys = 0;\n-\tbreak;\n-\n-\tdefault:\n-\t\tbreak;\n+\t/* Attach the maps defined in BPF program */\n+\terr = tap_rss__attach(pmd->rss);\n+\tif (err < 0) {\n+\t\tTAP_LOG(ERR, \"Failed to attach BPF object: %d\", err);\n+\t\trte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n+\t\t\t\"BPF object could not be attached\");\n+\t\ttap_flow_bpf_destroy(pmd);\n+\t\treturn err;\n \t}\n \n-\treturn err;\n+\treturn 0;\n }\n \n-\n /* Default RSS hash key also used by mlx devices */\n static const uint8_t rss_hash_default_key[] = {\n \t0x2c, 0xc6, 0x81, 0xd1,\n@@ -2006,9 +1809,11 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,\n \t\t\t   const struct rte_flow_action_rss *rss,\n \t\t\t   struct rte_flow_error *error)\n {\n+\tconst struct bpf_program *rss_prog = pmd->rss->progs.rss_flow_action;\n \tstruct rss_key rss_entry = { };\n \tconst uint8_t *key_in;\n \tuint32_t hash_type = 0;\n+\tuint32_t handle = flow->msg.t.tcm_handle;\n \tunsigned int i;\n \tint err;\n \n@@ -2057,34 +1862,24 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,\n \telse if (rss->types & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_IPV6_EX))\n \t\thash_type |= RTE_BIT32(HASH_FIELD_IPV6_L3);\n \n-\t/* Get a new map key for a new RSS rule */\n-\terr = bpf_rss_key(KEY_CMD_GET, &flow->key_idx);\n-\tif (err < 0) {\n-\t\trte_flow_error_set(\n-\t\t\terror, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n-\t\t\t\"Failed to get BPF RSS key\");\n-\n-\t\treturn -1;\n-\t}\n+\trss_entry.hash_fields = hash_type;\n+\trte_convert_rss_key((const uint32_t *)key_in, (uint32_t *)rss_entry.key,\n+\t\t\t    TAP_RSS_HASH_KEY_SIZE);\n \n \t/* Update RSS map entry with queues */\n \trss_entry.nb_queues = rss->queue_num;\n \tfor (i = 0; i < rss->queue_num; i++)\n \t\trss_entry.queues[i] = rss->queue[i];\n \n-\trss_entry.hash_fields = hash_type;\n-\trte_convert_rss_key((const uint32_t *)key_in, (uint32_t *)rss_entry.key,\n-\t\t\t    TAP_RSS_HASH_KEY_SIZE);\n-\n-\n-\t/* Add this RSS entry to map */\n-\terr = tap_flow_bpf_update_rss_elem(pmd->map_fd,\n-\t\t\t\t&flow->key_idx, &rss_entry);\n \n+\t/* Add this way for BPF to find  entry in map */\n+\terr = bpf_map__update_elem(pmd->rss->maps.rss_map,\n+\t\t\t\t   &handle, sizeof(handle),\n+\t\t\t\t   &rss_entry, sizeof(rss_entry), 0);\n \tif (err) {\n \t\tTAP_LOG(ERR,\n-\t\t\t\"Failed to update BPF map entry #%u (%d): %s\",\n-\t\t\tflow->key_idx, errno, strerror(errno));\n+\t\t\t\"Failed to update BPF map entry %#x (%d): %s\",\n+\t\t\thandle,  errno, strerror(errno));\n \t\trte_flow_error_set(\n \t\t\terror, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n \t\t\t\"Kernel too old or not configured \"\n@@ -2093,47 +1888,28 @@ static int rss_add_actions(struct rte_flow *flow, struct pmd_internals *pmd,\n \t\treturn -ENOTSUP;\n \t}\n \n-\n-\t/*\n-\t * Load bpf rules to calculate hash for this key_idx\n-\t */\n-\n-\tflow->bpf_fd[SEC_L3_L4] =\n-\t\ttap_flow_bpf_calc_l3_l4_hash(flow->key_idx, pmd->map_fd);\n-\tif (flow->bpf_fd[SEC_L3_L4] < 0) {\n-\t\tTAP_LOG(ERR,\n-\t\t\t\"Failed to load BPF section %s (%d): %s\",\n-\t\t\t\tsec_name[SEC_L3_L4], errno, strerror(errno));\n-\t\trte_flow_error_set(\n-\t\t\terror, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,\n-\t\t\t\"Kernel too old or not configured \"\n-\t\t\t\"to support BPF program loading\");\n-\n-\t\treturn -ENOTSUP;\n-\t}\n-\n-\t/* Actions */\n-\t{\n-\t\tstruct action_data adata[] = {\n-\t\t\t{\n-\t\t\t\t.id = \"bpf\",\n-\t\t\t\t.bpf = {\n-\t\t\t\t\t.bpf_fd = flow->bpf_fd[SEC_L3_L4],\n-\t\t\t\t\t.annotation = sec_name[SEC_L3_L4],\n-\t\t\t\t\t.bpf = {\n-\t\t\t\t\t\t.action = TC_ACT_PIPE,\n-\t\t\t\t\t},\n-\t\t\t\t},\n+\t/* Add actions to mark packet then run the RSS BPF program */\n+\tstruct action_data adata[] = {\n+\t\t{\n+\t\t\t.id = \"skbedit\",\n+\t\t\t.skbedit = {\n+\t\t\t\t.skbedit.action = TC_ACT_PIPE,\n+\t\t\t\t.mark = handle,\n \t\t\t},\n-\t\t};\n-\n-\t\tif (add_actions(flow, RTE_DIM(adata), adata,\n-\t\t\tTCA_FLOWER_ACT) < 0)\n-\t\t\treturn -1;\n-\t}\n+\t\t},\n+\t\t{\n+\t\t\t.id = \"bpf\",\n+\t\t\t.bpf = {\n+\t\t\t\t.bpf.action = TC_ACT_PIPE,\n+\t\t\t\t.annotation = \"tap_rss\",\n+\t\t\t\t.bpf_fd = bpf_program__fd(rss_prog),\n+\t\t\t},\n+\t\t},\n+\t};\n \n-\treturn 0;\n+\treturn add_actions(flow, RTE_DIM(adata), adata, TCA_FLOWER_ACT);\n }\n+#endif\n \n /**\n  * Get rte_flow operations.\ndiff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h\nindex 240fbc3dfa..8b19347a93 100644\n--- a/drivers/net/tap/tap_flow.h\n+++ b/drivers/net/tap/tap_flow.h\n@@ -9,7 +9,11 @@\n #include <rte_flow.h>\n #include <rte_flow_driver.h>\n #include <rte_eth_tap.h>\n-#include <tap_autoconf.h>\n+\n+/**\n+ * Mask of unsupported RSS types\n+ */\n+#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP))\n \n /**\n  * In TC, priority 0 means we require the kernel to allocate one for us.\n@@ -41,11 +45,6 @@ enum implicit_rule_index {\n \tTAP_REMOTE_MAX_IDX,\n };\n \n-enum bpf_fd_idx {\n-\tSEC_L3_L4,\n-\tSEC_MAX,\n-};\n-\n int tap_dev_flow_ops_get(struct rte_eth_dev *dev,\n \t\t\t const struct rte_flow_ops **ops);\n int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);\n@@ -57,10 +56,6 @@ int tap_flow_implicit_destroy(struct pmd_internals *pmd,\n int tap_flow_implicit_flush(struct pmd_internals *pmd,\n \t\t\t    struct rte_flow_error *error);\n \n-int tap_flow_bpf_cls_q(__u32 queue_idx);\n-int tap_flow_bpf_calc_l3_l4_hash(__u32 key_idx, int map_fd);\n-int tap_flow_bpf_rss_map_create(unsigned int key_size, unsigned int value_size,\n-\t\t\tunsigned int max_entries);\n-int tap_flow_bpf_update_rss_elem(int fd, void *key, void *value);\n+void tap_flow_bpf_destroy(struct pmd_internals *pmd);\n \n #endif /* _TAP_FLOW_H_ */\ndiff --git a/drivers/net/tap/tap_rss.h b/drivers/net/tap/tap_rss.h\nindex 6009be7031..65bd8991b1 100644\n--- a/drivers/net/tap/tap_rss.h\n+++ b/drivers/net/tap/tap_rss.h\n@@ -5,16 +5,14 @@\n #ifndef _TAP_RSS_H_\n #define _TAP_RSS_H_\n \n-#ifndef TAP_MAX_QUEUES\n-#define TAP_MAX_QUEUES 16\n+/* Size of the map from BPF classid to queue table */\n+#ifndef TAP_RSS_MAX\n+#define TAP_RSS_MAX\t32\n #endif\n \n-/* Fixed RSS hash key size in bytes. */\n+/* Standard Toeplitz hash key size */\n #define TAP_RSS_HASH_KEY_SIZE 40\n \n-/* Supported RSS */\n-#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP))\n-\n /* hashed fields for RSS */\n enum hash_field {\n \tHASH_FIELD_IPV4_L3,\t/* IPv4 src/dst addr */\ndiff --git a/drivers/net/tap/tap_tcmsgs.h b/drivers/net/tap/tap_tcmsgs.h\nindex a64cb29d6f..9411626661 100644\n--- a/drivers/net/tap/tap_tcmsgs.h\n+++ b/drivers/net/tap/tap_tcmsgs.h\n@@ -6,7 +6,6 @@\n #ifndef _TAP_TCMSGS_H_\n #define _TAP_TCMSGS_H_\n \n-#include <tap_autoconf.h>\n #include <linux/if_ether.h>\n #include <linux/rtnetlink.h>\n #include <linux/pkt_sched.h>\n@@ -14,9 +13,10 @@\n #include <linux/tc_act/tc_mirred.h>\n #include <linux/tc_act/tc_gact.h>\n #include <linux/tc_act/tc_skbedit.h>\n-#ifdef HAVE_TC_ACT_BPF\n+#ifdef HAVE_BPF_RSS\n #include <linux/tc_act/tc_bpf.h>\n #endif\n+\n #include <inttypes.h>\n \n #include <rte_ether.h>\n",
    "prefixes": [
        "v8",
        "6/8"
    ]
}