Hi, I've added the Ubuntu 24.04 environment to the Community Lab but without werror enabled as the rte_pcapng.c warning would cause them to fail. Once the rte_pcapng.c warning is fixed, I will re-enable werror. I will send an email to the ci mailing list with the logs of the warning so that people are aware of it. Thanks, Cody On Tue, May 21, 2024 at 4:14 PM Stephen Hemminger < stephen@networkplumber.org> wrote: > There were multiple issues in the RSS queue support in the TAP > driver. This required extensive rework of the BPF support. > > Change the BPF loading to use bpftool to > create a skeleton header file, and load with libbpf. > The BPF is always compiled from source so less chance that > source and instructions diverge. Also resolves issue where > libbpf and source get out of sync. The program > is only loaded once, so if multiple rules are created > only one BPF program is loaded in kernel. > > The new BPF program only needs a single action. > No need for action and re-classification step. > > It also fixes the missing bits from the original. > - supports setting RSS key per flow > - level of hash can be L3 or L3/L4. > > Bugzilla ID: 1329 > > Signed-off-by: Stephen Hemminger > --- > doc/guides/rel_notes/release_24_07.rst | 3 + > drivers/net/tap/bpf/meson.build | 81 +++-- > drivers/net/tap/meson.build | 39 ++- > drivers/net/tap/rte_eth_tap.c | 14 +- > drivers/net/tap/rte_eth_tap.h | 6 +- > drivers/net/tap/tap_flow.c | 416 ++++++------------------- > drivers/net/tap/tap_flow.h | 17 +- > drivers/net/tap/tap_rss.h | 10 +- > drivers/net/tap/tap_tcmsgs.h | 4 +- > 9 files changed, 186 insertions(+), 404 deletions(-) > > diff --git a/doc/guides/rel_notes/release_24_07.rst > b/doc/guides/rel_notes/release_24_07.rst > index a6295359b1..37a6e98637 100644 > --- a/doc/guides/rel_notes/release_24_07.rst > +++ b/doc/guides/rel_notes/release_24_07.rst > @@ -59,6 +59,9 @@ New Features > > * Updated to support up to 8 queues when used by secondary process. > > + * Fixed support of RSS flow action to work with current Linux > + kernels and BPF tooling. Will only be enabled if clang, libbpf 1.0 > + and bpftool are available. > > Removed Items > ------------- > diff --git a/drivers/net/tap/bpf/meson.build > b/drivers/net/tap/bpf/meson.build > index f2c03a19fd..df497948e2 100644 > --- a/drivers/net/tap/bpf/meson.build > +++ b/drivers/net/tap/bpf/meson.build > @@ -1,17 +1,26 @@ > # SPDX-License-Identifier: BSD-3-Clause > # Copyright 2024 Stephen Hemminger > > -enable_tap_rss = false > - > -libbpf = dependency('libbpf', required: false, method: 'pkg-config') > +# Loading BPF requires libbpf > +# and the bpf_map__XXX API's were introduced in 0.8.0 > +libbpf = dependency('libbpf', version: '>= 1.0', > + required: false, method: 'pkg-config') > if not libbpf.found() > message('net/tap: no RSS support missing libbpf') > subdir_done() > endif > > +# Making skeleton needs bpftool > # Debian install this in /usr/sbin which is not in $PATH > -bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false, > version: '>= 5.6.0') > -if not bpftool.found() > +bpftool_supports_skel = false > +bpftool = find_program('bpftool', '/usr/sbin/bpftool', required: false) > +if bpftool.found() > + # Some Ubuntu versions have non-functional bpftool > + bpftool_supports_skel = run_command(bpftool, 'gen', 'help', > + check:false).returncode() == 0 > +endif > + > +if not bpftool_supports_skel > message('net/tap: no RSS support missing bpftool') > subdir_done() > endif > @@ -39,43 +48,47 @@ machine_name = run_command('uname', > '-m').stdout().strip() > march_include_dir = '/usr/include/' + machine_name + '-linux-gnu' > > clang_flags = [ > - '-O2', > - '-Wall', > - '-Wextra', > - '-target', > - 'bpf', > - '-g', > - '-c', > + # these are flags used to build the BPF code > + '-O2', > + '-Wall', > + '-Wextra', > + max_queues, > + '-target', > + 'bpf', > + '-g', > + '-c', > ] > > +# Command used to compile BPF pgrograme > bpf_o_cmd = [ > - clang, > - clang_flags, > - '-idirafter', > - libbpf_include_dir, > - '-idirafter', > - march_include_dir, > - '@INPUT@', > - '-o', > - '@OUTPUT@' > + clang, > + clang_flags, > + '-idirafter', > + libbpf_include_dir, > + '-idirafter', > + march_include_dir, > + '@INPUT@', > + '-o', > + '@OUTPUT@', > ] > > +# Command used to generate header file from BPF object > skel_h_cmd = [ > - bpftool, > - 'gen', > - 'skeleton', > - '@INPUT@' > + bpftool, > + 'gen', > + 'skeleton', > + '@INPUT@', > ] > > tap_rss_o = custom_target( > - 'tap_rss.bpf.o', > - input: 'tap_rss.c', > - output: 'tap_rss.o', > - command: bpf_o_cmd) > + 'tap_rss.bpf.o', > + input: 'tap_rss.c', > + output: 'tap_rss.o', > + command: bpf_o_cmd) > > tap_rss_skel_h = custom_target( > - 'tap_rss.skel.h', > - input: tap_rss_o, > - output: 'tap_rss.skel.h', > - command: skel_h_cmd, > - capture: true) > + 'tap_rss.skel.h', > + input: tap_rss_o, > + output: 'tap_rss.skel.h', > + command: skel_h_cmd, > + capture: true) > diff --git a/drivers/net/tap/meson.build b/drivers/net/tap/meson.build > index 66647a1c62..5e5a3ad3c6 100644 > --- a/drivers/net/tap/meson.build > +++ b/drivers/net/tap/meson.build > @@ -5,36 +5,33 @@ if not is_linux > build = false > reason = 'only supported on Linux' > endif > + > sources = files( > 'rte_eth_tap.c', > 'tap_intr.c', > 'tap_netlink.c', > ) > > +deps = ['bus_vdev', 'gso', 'hash'] > + > +max_queues = '-DTAP_MAX_QUEUES=16' > +cflags += max_queues > + > +require_iova_in_mbuf = false > + > if cc.has_header_symbol('linux/pkt_cls.h', 'TCA_FLOWER_ACT') > cflags += '-DHAVE_TCA_FLOWER' > sources += files( > - 'tap_bpf_api.c', > - 'tap_flow.c', > - 'tap_tcmsgs.c', > + 'tap_flow.c', > + 'tap_tcmsgs.c', > ) > -endif > - > -deps = ['bus_vdev', 'gso', 'hash'] > > -cflags += '-DTAP_MAX_QUEUES=16' > - > -# input array for meson symbol search: > -# [ "MACRO to define if found", "header for the search", > -# "enum/define", "symbol to search" ] > -# > -args = [ > - [ 'HAVE_TC_ACT_BPF', 'linux/tc_act/tc_bpf.h', > 'TCA_ACT_BPF_UNSPEC' ], > -] > -config = configuration_data() > -foreach arg:args > - config.set(arg[0], cc.has_header_symbol(arg[1], arg[2])) > -endforeach > -configure_file(output : 'tap_autoconf.h', configuration : config) > + enable_tap_rss = false > > -require_iova_in_mbuf = false > + subdir('bpf') > + if enable_tap_rss > + cflags += '-DHAVE_BPF_RSS' > + ext_deps += libbpf > + sources += tap_rss_skel_h > + endif > +endif > diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c > index 9058a47295..d847565073 100644 > --- a/drivers/net/tap/rte_eth_tap.c > +++ b/drivers/net/tap/rte_eth_tap.c > @@ -1140,6 +1140,7 @@ tap_dev_close(struct rte_eth_dev *dev) > tap_flow_implicit_flush(internals, NULL); > tap_nl_final(internals->nlsk_fd); > internals->nlsk_fd = -1; > + tap_flow_bpf_destroy(internals); > } > #endif > > @@ -1949,6 +1950,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, > const char *tap_name, > strlcpy(pmd->name, tap_name, sizeof(pmd->name)); > pmd->type = type; > pmd->ka_fd = -1; > + > #ifdef HAVE_TCA_FLOWER > pmd->nlsk_fd = -1; > #endif > @@ -2031,13 +2033,6 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, > const char *tap_name, > /* Make network device persist after application exit */ > pmd->persist = persist; > > - pmd->if_index = if_nametoindex(pmd->name); > - if (!pmd->if_index) { > - TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); > - goto disable_rte_flow; > - } > - > - > #ifdef HAVE_TCA_FLOWER > /* > * Set up everything related to rte_flow: > @@ -2053,6 +2048,11 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, > const char *tap_name, > pmd->name); > goto disable_rte_flow; > } > + pmd->if_index = if_nametoindex(pmd->name); > + if (!pmd->if_index) { > + TAP_LOG(ERR, "%s: failed to get if_index.", pmd->name); > + goto disable_rte_flow; > + } > if (qdisc_create_multiq(pmd->nlsk_fd, pmd->if_index) < 0) { > TAP_LOG(ERR, "%s: failed to create multiq qdisc.", > pmd->name); > diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h > index af18b29090..ce4322ad04 100644 > --- a/drivers/net/tap/rte_eth_tap.h > +++ b/drivers/net/tap/rte_eth_tap.h > @@ -81,10 +81,8 @@ struct pmd_internals { > #ifdef HAVE_TCA_FLOWER > int nlsk_fd; /* Netlink socket fd */ > int flow_isolate; /* 1 if flow isolation is > enabled */ > - int rss_enabled; /* 1 if RSS is enabled, else 0 */ > - /* implicit rules set when RSS is enabled */ > - int map_fd; /* BPF RSS map fd */ > - int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */ > + > + struct tap_rss *rss; /* BPF program */ > > LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ > /* implicit rte_flow rules set when a remote device is active */ > diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c > index 45321aee86..0a90c0487b 100644 > --- a/drivers/net/tap/tap_flow.c > +++ b/drivers/net/tap/tap_flow.c > @@ -15,25 +15,19 @@ > #include > #include > #include > +#include > > #include > -#include > #include > #include > > -/* RSS key management */ > -enum bpf_rss_key_e { > - KEY_CMD_GET = 1, > - KEY_CMD_RELEASE, > - KEY_CMD_INIT, > - KEY_CMD_DEINIT, > -}; > - > -enum key_status_e { > - KEY_STAT_UNSPEC, > - KEY_STAT_USED, > - KEY_STAT_AVAILABLE, > -}; > +#ifdef HAVE_BPF_RSS > +/* Workaround for warning in bpftool generated skeleton code */ > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wcast-qual" > +#include "tap_rss.skel.h" > +#pragma GCC diagnostic pop > +#endif > > #define ISOLATE_HANDLE 1 > #define REMOTE_PROMISCUOUS_HANDLE 2 > @@ -41,8 +35,6 @@ enum key_status_e { > struct rte_flow { > LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow > structure */ > struct rte_flow *remote_flow; /* associated remote flow */ > - int bpf_fd[SEC_MAX]; /* list of bfs fds per ELF section */ > - uint32_t key_idx; /* RSS rule key index into BPF map */ > struct nlmsg msg; > }; > > @@ -69,12 +61,16 @@ struct action_data { > struct skbedit { > struct tc_skbedit skbedit; > uint16_t queue; > + uint32_t mark; > } skbedit; > +#ifdef HAVE_BPF_RSS > struct bpf { > struct tc_act_bpf bpf; > + uint32_t map_key; > int bpf_fd; > const char *annotation; > } bpf; > +#endif > }; > }; > > @@ -112,13 +108,12 @@ tap_flow_isolate(struct rte_eth_dev *dev, > int set, > struct rte_flow_error *error); > > -static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx); > -static int rss_enable(struct pmd_internals *pmd, > - const struct rte_flow_attr *attr, > - struct rte_flow_error *error); > +#ifdef HAVE_BPF_RSS > +static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error > *error); > static int rss_add_actions(struct rte_flow *flow, struct pmd_internals > *pmd, > const struct rte_flow_action_rss *rss, > struct rte_flow_error *error); > +#endif > > static const struct rte_flow_ops tap_flow_ops = { > .validate = tap_flow_validate, > @@ -853,11 +848,13 @@ add_action(struct rte_flow *flow, size_t *act_index, > struct action_data *adata) > &adata->mirred); > } else if (strcmp("skbedit", adata->id) == 0) { > tap_nlattr_add(&msg->nh, TCA_SKBEDIT_PARMS, > - sizeof(adata->skbedit.skbedit), > - &adata->skbedit.skbedit); > - tap_nlattr_add16(&msg->nh, TCA_SKBEDIT_QUEUE_MAPPING, > - adata->skbedit.queue); > + sizeof(adata->skbedit.skbedit), > &adata->skbedit.skbedit); > + if (adata->skbedit.mark) > + tap_nlattr_add32(&msg->nh, TCA_SKBEDIT_MARK, > adata->skbedit.mark); > + else > + tap_nlattr_add16(&msg->nh, > TCA_SKBEDIT_QUEUE_MAPPING, adata->skbedit.queue); > } else if (strcmp("bpf", adata->id) == 0) { > +#ifdef HAVE_BPF_RSS > tap_nlattr_add32(&msg->nh, TCA_ACT_BPF_FD, > adata->bpf.bpf_fd); > tap_nlattr_add(&msg->nh, TCA_ACT_BPF_NAME, > strlen(adata->bpf.annotation) + 1, > @@ -865,7 +862,12 @@ add_action(struct rte_flow *flow, size_t *act_index, > struct action_data *adata) > tap_nlattr_add(&msg->nh, TCA_ACT_BPF_PARMS, > sizeof(adata->bpf.bpf), > &adata->bpf.bpf); > +#else > + TAP_LOG(ERR, "Internal error: bpf requested but not > supported"); > + return -1; > +#endif > } else { > + TAP_LOG(ERR, "Internal error: unknown action: %s", > adata->id); > return -1; > } > tap_nlattr_nested_finish(msg); /* nested TCA_ACT_OPTIONS */ > @@ -1104,8 +1106,7 @@ priv_flow_process(struct pmd_internals *pmd, > }, > }; > > - err = add_actions(flow, 1, &adata, > - TCA_FLOWER_ACT); > + err = add_actions(flow, 1, &adata, > TCA_FLOWER_ACT); > } > } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) { > const struct rte_flow_action_queue *queue = > @@ -1135,6 +1136,7 @@ priv_flow_process(struct pmd_internals *pmd, > err = add_actions(flow, 1, &adata, > TCA_FLOWER_ACT); > } > +#ifdef HAVE_BPF_RSS > } else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) { > const struct rte_flow_action_rss *rss = > (const struct rte_flow_action_rss *) > @@ -1143,13 +1145,14 @@ priv_flow_process(struct pmd_internals *pmd, > if (action++) > goto exit_action_not_supported; > > - if (!pmd->rss_enabled) { > - err = rss_enable(pmd, attr, error); > + if (pmd->rss == NULL) { > + err = rss_enable(pmd, error); > if (err) > goto exit_return_error; > } > if (flow) > err = rss_add_actions(flow, pmd, rss, > error); > +#endif > } else { > goto exit_action_not_supported; > } > @@ -1246,26 +1249,17 @@ tap_flow_set_handle(struct rte_flow *flow) > * > */ > static void > -tap_flow_free(struct pmd_internals *pmd, struct rte_flow *flow) > +tap_flow_free(struct pmd_internals *pmd __rte_unused, struct rte_flow > *flow) > { > - int i; > - > if (!flow) > return; > > - if (pmd->rss_enabled) { > - /* Close flow BPF file descriptors */ > - for (i = 0; i < SEC_MAX; i++) > - if (flow->bpf_fd[i] != 0) { > - close(flow->bpf_fd[i]); > - flow->bpf_fd[i] = 0; > - } > - > - /* Release the map key for this RSS rule */ > - bpf_rss_key(KEY_CMD_RELEASE, &flow->key_idx); > - flow->key_idx = 0; > - } > - > +#ifdef HAVE_BPF_RSS > + struct tap_rss *rss = pmd->rss; > + if (rss) > + bpf_map__delete_elem(rss->maps.rss_map, > + &flow->msg.t.tcm_handle, > sizeof(uint32_t), 0); > +#endif > /* Free flow allocated memory */ > rte_free(flow); > } > @@ -1733,14 +1727,18 @@ tap_flow_implicit_flush(struct pmd_internals *pmd, > struct rte_flow_error *error) > return 0; > } > > -#define MAX_RSS_KEYS 256 > -#define KEY_IDX_OFFSET (3 * MAX_RSS_KEYS) > -#define SEC_NAME_CLS_Q "cls_q" > - > -static const char *sec_name[SEC_MAX] = { > - [SEC_L3_L4] = "l3_l4", > -}; > +/** > + * Cleanup when device is closed > + */ > +void tap_flow_bpf_destroy(struct pmd_internals *pmd __rte_unused) > +{ > +#ifdef HAVE_BPF_RSS > + tap_rss__destroy(pmd->rss); > + pmd->rss = NULL; > +#endif > +} > > +#ifdef HAVE_BPF_RSS > /** > * Enable RSS on tap: create TC rules for queuing. > * > @@ -1755,225 +1753,32 @@ static const char *sec_name[SEC_MAX] = { > * > * @return 0 on success, negative value on failure. > */ > -static int rss_enable(struct pmd_internals *pmd, > - const struct rte_flow_attr *attr, > - struct rte_flow_error *error) > +static int rss_enable(struct pmd_internals *pmd, struct rte_flow_error > *error) > { > - struct rte_flow *rss_flow = NULL; > - struct nlmsg *msg = NULL; > - /* 4096 is the maximum number of instructions for a BPF program */ > - char annotation[64]; > - int i; > - int err = 0; > - > - /* unlimit locked memory */ > - struct rlimit memlock_limit = { > - .rlim_cur = RLIM_INFINITY, > - .rlim_max = RLIM_INFINITY, > - }; > - setrlimit(RLIMIT_MEMLOCK, &memlock_limit); > - > - /* Get a new map key for a new RSS rule */ > - err = bpf_rss_key(KEY_CMD_INIT, NULL); > - if (err < 0) { > - rte_flow_error_set( > - error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > - "Failed to initialize BPF RSS keys"); > - > - return -1; > - } > - > - /* > - * Create BPF RSS MAP > - */ > - pmd->map_fd = tap_flow_bpf_rss_map_create(sizeof(__u32), /* key > size */ > - sizeof(struct rss_key), > - MAX_RSS_KEYS); > - if (pmd->map_fd < 0) { > - TAP_LOG(ERR, > - "Failed to create BPF map (%d): %s", > - errno, strerror(errno)); > - rte_flow_error_set( > - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > - "Kernel too old or not configured " > - "to support BPF maps"); > - > - return -ENOTSUP; > - } > - > - /* > - * Add a rule per queue to match reclassified packets and direct > them to > - * the correct queue. > - */ > - for (i = 0; i < pmd->dev->data->nb_rx_queues; i++) { > - pmd->bpf_fd[i] = tap_flow_bpf_cls_q(i); > - if (pmd->bpf_fd[i] < 0) { > - TAP_LOG(ERR, > - "Failed to load BPF section %s for queue > %d", > - SEC_NAME_CLS_Q, i); > - rte_flow_error_set( > - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, > - NULL, > - "Kernel too old or not configured " > - "to support BPF programs loading"); > - > - return -ENOTSUP; > - } > - > - rss_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), > 0); > - if (!rss_flow) { > - TAP_LOG(ERR, > - "Cannot allocate memory for rte_flow"); > - return -1; > - } > - msg = &rss_flow->msg; > - tc_init_msg(msg, pmd->if_index, RTM_NEWTFILTER, > NLM_F_REQUEST | > - NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE); > - msg->t.tcm_info = TC_H_MAKE(0, htons(ETH_P_ALL)); > - tap_flow_set_handle(rss_flow); > - uint16_t group = attr->group << GROUP_SHIFT; > - uint16_t prio = group | (i + PRIORITY_OFFSET); > - msg->t.tcm_info = TC_H_MAKE(prio << 16, msg->t.tcm_info); > - msg->t.tcm_parent = TC_H_MAKE(MULTIQ_MAJOR_HANDLE, 0); > - > - tap_nlattr_add(&msg->nh, TCA_KIND, sizeof("bpf"), "bpf"); > - if (tap_nlattr_nested_start(msg, TCA_OPTIONS) < 0) > - return -1; > - tap_nlattr_add32(&msg->nh, TCA_BPF_FD, pmd->bpf_fd[i]); > - snprintf(annotation, sizeof(annotation), "[%s%d]", > - SEC_NAME_CLS_Q, i); > - tap_nlattr_add(&msg->nh, TCA_BPF_NAME, strlen(annotation) > + 1, > - annotation); > - /* Actions */ > - { > - struct action_data adata = { > - .id = "skbedit", > - .skbedit = { > - .skbedit = { > - .action = TC_ACT_PIPE, > - }, > - .queue = i, > - }, > - }; > - if (add_actions(rss_flow, 1, &adata, TCA_BPF_ACT) > < 0) > - return -1; > - } > - tap_nlattr_nested_finish(msg); /* nested TCA_OPTIONS */ > + int err; > > - /* Netlink message is now ready to be sent */ > - if (tap_nl_send(pmd->nlsk_fd, &msg->nh) < 0) > - return -1; > - err = tap_nl_recv_ack(pmd->nlsk_fd); > - if (err < 0) { > - TAP_LOG(ERR, > - "Kernel refused TC filter rule creation > (%d): %s", > - errno, strerror(errno)); > - return err; > - } > + /* Load the BPF program (defined in tap_bpf.h from skeleton) */ > + pmd->rss = tap_rss__open_and_load(); > + if (pmd->rss == NULL) { > + TAP_LOG(ERR, "Failed to load BPF object: %s", > strerror(errno)); > + rte_flow_error_set(error, errno, > RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > + "BPF object could not be loaded"); > + return -errno; > } > > - pmd->rss_enabled = 1; > - return err; > -} > - > -/** > - * Manage bpf RSS keys repository with operations: init, get, release > - * > - * @param[in] cmd > - * Command on RSS keys: init, get, release > - * > - * @param[in, out] key_idx > - * Pointer to RSS Key index (out for get command, in for release > command) > - * > - * @return -1 if couldn't get, release or init the RSS keys, 0 otherwise. > - */ > -static int bpf_rss_key(enum bpf_rss_key_e cmd, __u32 *key_idx) > -{ > - __u32 i; > - int err = 0; > - static __u32 num_used_keys; > - static __u32 rss_keys[MAX_RSS_KEYS] = {KEY_STAT_UNSPEC}; > - static __u32 rss_keys_initialized; > - __u32 key; > - > - switch (cmd) { > - case KEY_CMD_GET: > - if (!rss_keys_initialized) { > - err = -1; > - break; > - } > - > - if (num_used_keys == RTE_DIM(rss_keys)) { > - err = -1; > - break; > - } > - > - *key_idx = num_used_keys % RTE_DIM(rss_keys); > - while (rss_keys[*key_idx] == KEY_STAT_USED) > - *key_idx = (*key_idx + 1) % RTE_DIM(rss_keys); > - > - rss_keys[*key_idx] = KEY_STAT_USED; > - > - /* > - * Add an offset to key_idx in order to handle a case of > - * RSS and non RSS flows mixture. > - * If a non RSS flow is destroyed it has an eBPF map > - * index 0 (initialized on flow creation) and might > - * unintentionally remove RSS entry 0 from eBPF map. > - * To avoid this issue, add an offset to the real index > - * during a KEY_CMD_GET operation and subtract this offset > - * during a KEY_CMD_RELEASE operation in order to restore > - * the real index. > - */ > - *key_idx += KEY_IDX_OFFSET; > - num_used_keys++; > - break; > - > - case KEY_CMD_RELEASE: > - if (!rss_keys_initialized) > - break; > - > - /* > - * Subtract offset to restore real key index > - * If a non RSS flow is falsely trying to release map > - * entry 0 - the offset subtraction will calculate the real > - * map index as an out-of-range value and the release > operation > - * will be silently ignored. > - */ > - key = *key_idx - KEY_IDX_OFFSET; > - if (key >= RTE_DIM(rss_keys)) > - break; > - > - if (rss_keys[key] == KEY_STAT_USED) { > - rss_keys[key] = KEY_STAT_AVAILABLE; > - num_used_keys--; > - } > - break; > - > - case KEY_CMD_INIT: > - for (i = 0; i < RTE_DIM(rss_keys); i++) > - rss_keys[i] = KEY_STAT_AVAILABLE; > - > - rss_keys_initialized = 1; > - num_used_keys = 0; > - break; > - > - case KEY_CMD_DEINIT: > - for (i = 0; i < RTE_DIM(rss_keys); i++) > - rss_keys[i] = KEY_STAT_UNSPEC; > - > - rss_keys_initialized = 0; > - num_used_keys = 0; > - break; > - > - default: > - break; > + /* Attach the maps defined in BPF program */ > + err = tap_rss__attach(pmd->rss); > + if (err < 0) { > + TAP_LOG(ERR, "Failed to attach BPF object: %d", err); > + rte_flow_error_set(error, -err, > RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > + "BPF object could not be attached"); > + tap_flow_bpf_destroy(pmd); > + return err; > } > > - return err; > + return 0; > } > > - > /* Default RSS hash key also used by mlx devices */ > static const uint8_t rss_hash_default_key[] = { > 0x2c, 0xc6, 0x81, 0xd1, > @@ -2006,9 +1811,11 @@ static int rss_add_actions(struct rte_flow *flow, > struct pmd_internals *pmd, > const struct rte_flow_action_rss *rss, > struct rte_flow_error *error) > { > + const struct bpf_program *rss_prog = > pmd->rss->progs.rss_flow_action; > struct rss_key rss_entry = { }; > const uint8_t *key_in; > uint32_t hash_type = 0; > + uint32_t handle = flow->msg.t.tcm_handle; > unsigned int i; > int err; > > @@ -2067,34 +1874,24 @@ static int rss_add_actions(struct rte_flow *flow, > struct pmd_internals *pmd, > else if (rss->types & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | > RTE_ETH_RSS_IPV6_EX)) > hash_type |= RTE_BIT32(HASH_FIELD_IPV6_L3); > > - /* Get a new map key for a new RSS rule */ > - err = bpf_rss_key(KEY_CMD_GET, &flow->key_idx); > - if (err < 0) { > - rte_flow_error_set( > - error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > - "Failed to get BPF RSS key"); > - > - return -1; > - } > + rss_entry.hash_fields = hash_type; > + rte_convert_rss_key((const uint32_t *)key_in, (uint32_t > *)rss_entry.key, > + TAP_RSS_HASH_KEY_SIZE); > > /* Update RSS map entry with queues */ > rss_entry.nb_queues = rss->queue_num; > for (i = 0; i < rss->queue_num; i++) > rss_entry.queues[i] = rss->queue[i]; > > - rss_entry.hash_fields = hash_type; > - rte_convert_rss_key((const uint32_t *)key_in, (uint32_t > *)rss_entry.key, > - TAP_RSS_HASH_KEY_SIZE); > - > - > - /* Add this RSS entry to map */ > - err = tap_flow_bpf_update_rss_elem(pmd->map_fd, > - &flow->key_idx, &rss_entry); > > + /* Add this way for BPF to find entry in map */ > + err = bpf_map__update_elem(pmd->rss->maps.rss_map, > + &handle, sizeof(handle), > + &rss_entry, sizeof(rss_entry), 0); > if (err) { > TAP_LOG(ERR, > - "Failed to update BPF map entry #%u (%d): %s", > - flow->key_idx, errno, strerror(errno)); > + "Failed to update BPF map entry %#x (%d): %s", > + handle, errno, strerror(errno)); > rte_flow_error_set( > error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > "Kernel too old or not configured " > @@ -2103,47 +1900,28 @@ static int rss_add_actions(struct rte_flow *flow, > struct pmd_internals *pmd, > return -ENOTSUP; > } > > - > - /* > - * Load bpf rules to calculate hash for this key_idx > - */ > - > - flow->bpf_fd[SEC_L3_L4] = > - tap_flow_bpf_calc_l3_l4_hash(flow->key_idx, pmd->map_fd); > - if (flow->bpf_fd[SEC_L3_L4] < 0) { > - TAP_LOG(ERR, > - "Failed to load BPF section %s (%d): %s", > - sec_name[SEC_L3_L4], errno, > strerror(errno)); > - rte_flow_error_set( > - error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, > - "Kernel too old or not configured " > - "to support BPF program loading"); > - > - return -ENOTSUP; > - } > - > - /* Actions */ > - { > - struct action_data adata[] = { > - { > - .id = "bpf", > - .bpf = { > - .bpf_fd = flow->bpf_fd[SEC_L3_L4], > - .annotation = sec_name[SEC_L3_L4], > - .bpf = { > - .action = TC_ACT_PIPE, > - }, > - }, > + /* Add actions to mark packet then run the RSS BPF program */ > + struct action_data adata[] = { > + { > + .id = "skbedit", > + .skbedit = { > + .skbedit.action = TC_ACT_PIPE, > + .mark = handle, > }, > - }; > - > - if (add_actions(flow, RTE_DIM(adata), adata, > - TCA_FLOWER_ACT) < 0) > - return -1; > - } > + }, > + { > + .id = "bpf", > + .bpf = { > + .bpf.action = TC_ACT_PIPE, > + .annotation = "tap_rss", > + .bpf_fd = bpf_program__fd(rss_prog), > + }, > + }, > + }; > > - return 0; > + return add_actions(flow, RTE_DIM(adata), adata, TCA_FLOWER_ACT); > } > +#endif > > /** > * Get rte_flow operations. > diff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h > index 240fbc3dfa..8b19347a93 100644 > --- a/drivers/net/tap/tap_flow.h > +++ b/drivers/net/tap/tap_flow.h > @@ -9,7 +9,11 @@ > #include > #include > #include > -#include > + > +/** > + * Mask of unsupported RSS types > + */ > +#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | > RTE_ETH_RSS_TCP)) > > /** > * In TC, priority 0 means we require the kernel to allocate one for us. > @@ -41,11 +45,6 @@ enum implicit_rule_index { > TAP_REMOTE_MAX_IDX, > }; > > -enum bpf_fd_idx { > - SEC_L3_L4, > - SEC_MAX, > -}; > - > int tap_dev_flow_ops_get(struct rte_eth_dev *dev, > const struct rte_flow_ops **ops); > int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error); > @@ -57,10 +56,6 @@ int tap_flow_implicit_destroy(struct pmd_internals *pmd, > int tap_flow_implicit_flush(struct pmd_internals *pmd, > struct rte_flow_error *error); > > -int tap_flow_bpf_cls_q(__u32 queue_idx); > -int tap_flow_bpf_calc_l3_l4_hash(__u32 key_idx, int map_fd); > -int tap_flow_bpf_rss_map_create(unsigned int key_size, unsigned int > value_size, > - unsigned int max_entries); > -int tap_flow_bpf_update_rss_elem(int fd, void *key, void *value); > +void tap_flow_bpf_destroy(struct pmd_internals *pmd); > > #endif /* _TAP_FLOW_H_ */ > diff --git a/drivers/net/tap/tap_rss.h b/drivers/net/tap/tap_rss.h > index 6009be7031..65bd8991b1 100644 > --- a/drivers/net/tap/tap_rss.h > +++ b/drivers/net/tap/tap_rss.h > @@ -5,16 +5,14 @@ > #ifndef _TAP_RSS_H_ > #define _TAP_RSS_H_ > > -#ifndef TAP_MAX_QUEUES > -#define TAP_MAX_QUEUES 16 > +/* Size of the map from BPF classid to queue table */ > +#ifndef TAP_RSS_MAX > +#define TAP_RSS_MAX 32 > #endif > > -/* Fixed RSS hash key size in bytes. */ > +/* Standard Toeplitz hash key size */ > #define TAP_RSS_HASH_KEY_SIZE 40 > > -/* Supported RSS */ > -#define TAP_RSS_HF_MASK (~(RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | > RTE_ETH_RSS_TCP)) > - > /* hashed fields for RSS */ > enum hash_field { > HASH_FIELD_IPV4_L3, /* IPv4 src/dst addr */ > diff --git a/drivers/net/tap/tap_tcmsgs.h b/drivers/net/tap/tap_tcmsgs.h > index a64cb29d6f..9411626661 100644 > --- a/drivers/net/tap/tap_tcmsgs.h > +++ b/drivers/net/tap/tap_tcmsgs.h > @@ -6,7 +6,6 @@ > #ifndef _TAP_TCMSGS_H_ > #define _TAP_TCMSGS_H_ > > -#include > #include > #include > #include > @@ -14,9 +13,10 @@ > #include > #include > #include > -#ifdef HAVE_TC_ACT_BPF > +#ifdef HAVE_BPF_RSS > #include > #endif > + > #include > > #include > -- > 2.43.0 > >