net/af_xdp: workaround custom program loading
Since v0.4.0, if the underlying kernel supports it, libbpf uses 'bpf link' to manage the programs on the interfaces of the XDP sockets (xsks). This is not compatible with the PMD's custom XDP program loading feature which uses the netlink-based method for loading custom programs. The conflict arises when libbpf searches for a custom program on the interface using bpf link, but doesn't find one because the netlink method was used. libbpf then proceeds to try to load the default program on the interface, but fails due to the presence of the custom program. To work around this, the PMD now uses the XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD flag which prevents libbpf from attempting to search for or load a program. One repercussion is that DPDK must now insert the xsk into the xsks_map as this was previously handled by libbpf during the routines for program loading/probing. Ideally, the PMD would use bpf link to load the custom program, however at present there is no convenient and reliable way of detecting whether the underlying kernel supports bpf link. Perhaps this may become available in a future libbpf release, at which point we can switch the PMD over to the new bpf link based method. Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
This commit is contained in:
parent
9f394004c3
commit
01fa83c94d
@ -15,6 +15,7 @@
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sockios.h>
|
||||
#include "af_xdp_deps.h"
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/xsk.h>
|
||||
|
||||
#include <rte_ethdev.h>
|
||||
@ -139,6 +140,7 @@ struct pmd_internals {
|
||||
bool shared_umem;
|
||||
char prog_path[PATH_MAX];
|
||||
bool custom_prog_configured;
|
||||
struct bpf_map *map;
|
||||
|
||||
struct rte_ether_addr eth_addr;
|
||||
|
||||
@ -1147,11 +1149,10 @@ xsk_umem_info *xdp_umem_configure(struct pmd_internals *internals,
|
||||
}
|
||||
|
||||
static int
|
||||
load_custom_xdp_prog(const char *prog_path, int if_index)
|
||||
load_custom_xdp_prog(const char *prog_path, int if_index, struct bpf_map **map)
|
||||
{
|
||||
int ret, prog_fd = -1;
|
||||
struct bpf_object *obj;
|
||||
struct bpf_map *map;
|
||||
|
||||
ret = bpf_prog_load(prog_path, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
|
||||
if (ret) {
|
||||
@ -1161,11 +1162,10 @@ load_custom_xdp_prog(const char *prog_path, int if_index)
|
||||
|
||||
/*
|
||||
* The loaded program must provision for a map of xsks, such that some
|
||||
* traffic can be redirected to userspace. When the xsk is created,
|
||||
* libbpf inserts it into the map.
|
||||
* traffic can be redirected to userspace.
|
||||
*/
|
||||
map = bpf_object__find_map_by_name(obj, "xsks_map");
|
||||
if (!map) {
|
||||
*map = bpf_object__find_map_by_name(obj, "xsks_map");
|
||||
if (!*map) {
|
||||
AF_XDP_LOG(ERR, "Failed to find xsks_map in %s\n", prog_path);
|
||||
return -1;
|
||||
}
|
||||
@ -1272,13 +1272,15 @@ xsk_configure(struct pmd_internals *internals, struct pkt_rx_queue *rxq,
|
||||
if (strnlen(internals->prog_path, PATH_MAX) &&
|
||||
!internals->custom_prog_configured) {
|
||||
ret = load_custom_xdp_prog(internals->prog_path,
|
||||
internals->if_index);
|
||||
internals->if_index,
|
||||
&internals->map);
|
||||
if (ret) {
|
||||
AF_XDP_LOG(ERR, "Failed to load custom XDP program %s\n",
|
||||
internals->prog_path);
|
||||
goto err;
|
||||
}
|
||||
internals->custom_prog_configured = 1;
|
||||
cfg.libbpf_flags = XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD;
|
||||
}
|
||||
|
||||
if (internals->shared_umem)
|
||||
@ -1295,6 +1297,19 @@ xsk_configure(struct pmd_internals *internals, struct pkt_rx_queue *rxq,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* insert the xsk into the xsks_map */
|
||||
if (internals->custom_prog_configured) {
|
||||
int err, fd;
|
||||
|
||||
fd = xsk_socket__fd(rxq->xsk);
|
||||
err = bpf_map_update_elem(bpf_map__fd(internals->map),
|
||||
&rxq->xsk_queue_idx, &fd, 0);
|
||||
if (err) {
|
||||
AF_XDP_LOG(ERR, "Failed to insert xsk in map.\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
|
||||
ret = rte_pktmbuf_alloc_bulk(rxq->umem->mb_pool, fq_bufs, reserve_size);
|
||||
if (ret) {
|
||||
|
Loading…
Reference in New Issue
Block a user