Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/avf/virtchnl.h>
#include <linux/cpu_rmap.h>
#include <linux/dim.h>
#include <linux/btf.h>
#include <net/devlink.h>
#include <net/ipv6.h>
#include <net/xdp_sock.h>
Expand Down Expand Up @@ -349,6 +350,9 @@ struct ice_vsi {
u16 num_xdp_txq; /* Used XDP queues */
u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */

bool xdp_metadata_support; /* true if VSI should support xdp meta */
s32 btf_id;

/* setup back reference, to which aggregator node this VSI
* corresponds to
*/
Expand Down
26 changes: 24 additions & 2 deletions drivers/net/ethernet/intel/ice/ice_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,21 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)
WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
}

static void ice_xdp_rings_set_metadata(struct ice_vsi *vsi)
{
int i;

ice_for_each_rxq(vsi, i) {
vsi->rx_rings[i]->xdp_metadata_support = vsi->xdp_metadata_support;
vsi->rx_rings[i]->btf_id = vsi->btf_id;
}

for (i = 0; i < vsi->num_xdp_txq; i++) {
vsi->xdp_rings[i]->xdp_metadata_support = vsi->xdp_metadata_support;
vsi->xdp_rings[i]->btf_id = vsi->btf_id;
}
}

/**
* ice_prepare_xdp_rings - Allocate, configure and setup Tx rings for XDP
* @vsi: VSI to bring up Tx rings used by XDP
Expand Down Expand Up @@ -2458,6 +2473,8 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)
if (ice_xdp_alloc_setup_rings(vsi))
goto clear_xdp_rings;

ice_xdp_rings_set_metadata(vsi);

/* follow the logic from ice_vsi_map_rings_to_vectors */
ice_for_each_q_vector(vsi, v_idx) {
struct ice_q_vector *q_vector = vsi->q_vectors[v_idx];
Expand Down Expand Up @@ -2613,7 +2630,7 @@ static void ice_vsi_rx_napi_schedule(struct ice_vsi *vsi)
*/
static int
ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
struct netlink_ext_ack *extack, u32 flags)
{
int frame_size = vsi->netdev->mtu + ICE_ETH_PKT_HDR_PAD;
bool if_running = netif_running(vsi->netdev);
Expand All @@ -2633,6 +2650,11 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
}
}

if (flags & XDP_FLAGS_USE_METADATA) {
vsi->xdp_metadata_support = true;
vsi->btf_id = btf_get_type_id(THIS_MODULE, "xdp_meta_generic", BTF_KIND_STRUCT);
}

if (!ice_is_xdp_ena_vsi(vsi) && prog) {
vsi->num_xdp_txq = vsi->alloc_rxq;
xdp_ring_err = ice_prepare_xdp_rings(vsi, prog);
Expand Down Expand Up @@ -2686,7 +2708,7 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)

switch (xdp->command) {
case XDP_SETUP_PROG:
return ice_xdp_setup_prog(vsi, xdp->prog, xdp->extack);
return ice_xdp_setup_prog(vsi, xdp->prog, xdp->extack, xdp->flags);
case XDP_SETUP_XSK_POOL:
return ice_xsk_pool_setup(vsi, xdp->xsk.pool,
xdp->xsk.queue_id);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,10 @@ int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget)
hard_start = page_address(rx_buf->page) + rx_buf->page_offset -
offset;
xdp_prepare_buff(&xdp, hard_start, offset, size, true);

if (likely(rx_ring->xdp_metadata_support))
ice_xdp_set_meta(&xdp, rx_desc, rx_ring->btf_id);

#if (PAGE_SIZE > 4096)
/* At larger PAGE_SIZE, frame_sz depend on len size */
xdp.frame_sz = ice_rx_frame_truesize(rx_ring, size);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ struct ice_ring {
u16 q_handle; /* Queue handle per TC */

u8 ring_active:1; /* is ring online or not */
u8 xdp_metadata_support:1; /* is xdp metadata support */

u16 count; /* Number of descriptors */
u16 reg_idx; /* HW register index of the ring */
Expand All @@ -301,6 +302,9 @@ struct ice_ring {
/* CL3 - 3rd cacheline starts here */
struct xdp_rxq_info xdp_rxq;
struct sk_buff *skb;
s32 btf_id;


/* CLX - the below items are only accessed infrequently and should be
* in their own cache line if possible
*/
Expand Down
20 changes: 20 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_txrx_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ static inline void ice_xdp_ring_update_tail(struct ice_ring *xdp_ring)
writel_relaxed(xdp_ring->next_to_use, xdp_ring->tail);
}

static inline void ice_xdp_set_meta(struct xdp_buff *xdp, union ice_32b_rx_flex_desc *desc, s32 btf_id)
{
struct ice_32b_rx_flex_desc_nic *flex = (struct ice_32b_rx_flex_desc_nic *)desc;
struct xdp_meta_generic *md = xdp->data - sizeof(struct xdp_meta_generic);

md->rxcvid = le16_to_cpu(flex->flex_ts.flex.vlan_id);
md->hash = le32_to_cpu(flex->rss_hash);

md->flags = 0;
md->free_slot = 0;
md->csum_off = 0;
md->txcvid = 0;
md->csum = 0;
md->tstamp = 0;

md->btf_id = btf_id;

xdp->data_meta = md;
}

void ice_finalize_xdp_rx(struct ice_ring *rx_ring, unsigned int xdp_res);
int ice_xmit_xdp_buff(struct xdp_buff *xdp, struct ice_ring *xdp_ring);
int ice_xmit_xdp_ring(void *data, u16 size, struct ice_ring *xdp_ring);
Expand Down
1 change: 1 addition & 0 deletions include/linux/btf.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ u32 btf_obj_id(const struct btf *btf);
bool btf_is_kernel(const struct btf *btf);
bool btf_is_module(const struct btf *btf);
struct module *btf_try_get_module(const struct btf *btf);
s32 btf_get_type_id(const struct module *mod, char *name, u32 kind);
u32 btf_nr_types(const struct btf *btf);
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
const struct btf_member *m,
Expand Down
18 changes: 18 additions & 0 deletions include/net/xdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ struct xdp_buff {
u32 frame_sz; /* frame size to deduce data_hard_end/reserved tailroom*/
};

struct xdp_meta_generic {
// Tx part
u32 flags;
u16 free_slot;
u16 csum_off;
u16 txcvid;

// Rx part
u16 rxcvid;
u32 csum;
u32 hash;
u64 tstamp;

// BTF ID
u32 btf_id;
} __packed __aligned(8);
static_assert(sizeof(struct xdp_meta_generic) == 32);

static __always_inline void
xdp_init_buff(struct xdp_buff *xdp, u32 frame_sz, struct xdp_rxq_info *rxq)
{
Expand Down
6 changes: 6 additions & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,7 @@ enum bpf_cmd {
BPF_ITER_CREATE,
BPF_LINK_DETACH,
BPF_PROG_BIND_MAP,
BPF_BTF_VMLINUX_INFO,
};

enum bpf_map_type {
Expand Down Expand Up @@ -1396,6 +1397,11 @@ union bpf_attr {
__aligned_u64 info;
} info;

struct { /* anonymous struct used by BPF_BTF_VMLINUX_INFO */
__u32 info_len;
__aligned_u64 info;
} info_vmlinux;

struct { /* anonymous struct used by BPF_PROG_QUERY command */
__u32 target_fd; /* container object to query */
__u32 attach_type;
Expand Down
4 changes: 3 additions & 1 deletion include/uapi/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,11 +1182,13 @@ enum {
#define XDP_FLAGS_DRV_MODE (1U << 2)
#define XDP_FLAGS_HW_MODE (1U << 3)
#define XDP_FLAGS_REPLACE (1U << 4)
#define XDP_FLAGS_USE_METADATA (1U << 5)
#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \
XDP_FLAGS_DRV_MODE | \
XDP_FLAGS_HW_MODE)
#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \
XDP_FLAGS_MODES | XDP_FLAGS_REPLACE)
XDP_FLAGS_MODES | XDP_FLAGS_REPLACE | \
XDP_FLAGS_USE_METADATA)

/* These are stored into IFLA_XDP_ATTACHED on dump. */
enum {
Expand Down
37 changes: 37 additions & 0 deletions kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6152,6 +6152,43 @@ struct module *btf_try_get_module(const struct btf *btf)
return res;
}

struct btf *btf_get_from_module(const struct module *module)
{
struct btf *res = NULL;
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
struct btf_module *btf_mod, *tmp;

mutex_lock(&btf_module_mutex);
list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
if (btf_mod->module != module)
continue;

res = btf_mod->btf;

break;
}
mutex_unlock(&btf_module_mutex);
#endif

return res;
}

s32 btf_get_type_id(const struct module *mod, char *name, u32 kind)
{
struct btf *btf;

if (mod)
btf = btf_get_from_module(mod);
else
btf = bpf_get_btf_vmlinux();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing here. If both vmlinux and our module have the same struct, will this func return different IDs when called with mod and without? That might be unwanted when we will compare type IDs against each other. The flow should probably be going the way that if vmlinux has this structure, then we always return type ID from it, and a type ID from a module only if there's no such type in vmlinux.

Copy link
Collaborator Author

@walking-machine walking-machine Oct 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I know of how BTFs work, type duplication between vmlinux and any single module BTF is impossible, it's a problem only if we have 2 module BTFs. But I like the idea of looking into vmlinux first, even if we do have a mod != NULL, this would improve user experience. There is non-zero possibility that btf_find_by_name_kind() already does that (checks base btf, which is vmlinux), I need to check this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does exactly that, so functionally this piece of code is OK.


if (!btf)
return 0;

return btf_find_by_name_kind(btf, name, kind);
}
EXPORT_SYMBOL_GPL(btf_get_type_id);

BPF_CALL_4(bpf_btf_find_by_name_kind, char *, name, int, name_sz, u32, kind, int, flags)
{
struct btf *btf;
Expand Down
1 change: 1 addition & 0 deletions kernel/bpf/cpumap.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
{
struct xdp_rxq_info rxq;
struct xdp_buff xdp;
volatile struct xdp_meta_generic xdp_meta_generic;
int i, nframes = 0;

xdp_set_return_frame_no_direct();
Expand Down
22 changes: 22 additions & 0 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -4542,6 +4542,25 @@ static int bpf_prog_bind_map(union bpf_attr *attr)
return ret;
}

#define BPF_BTF_VMLINUX_INFO_LAST_FIELD info.info
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's used behind the curtains by CHECK_ATTR():

https://elixir.bootlin.com/linux/v5.15-rc7/source/kernel/bpf/syscall.c#L715

That's why I prefer to pass all needed params to macros explicitly :P

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, got it, thanks


static int bpf_btf_get_vmlinux_info(const union bpf_attr *attr,
union bpf_attr __user *uattr)
{
struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info);
u32 info_len = attr->info.info_len;
int err;

if (CHECK_ATTR(BPF_BTF_VMLINUX_INFO))
return -EINVAL;

err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(*uinfo), info_len);
if (err)
return err;

return btf_get_info_by_fd(bpf_get_btf_vmlinux(), attr, uattr);
}

static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size)
{
union bpf_attr attr;
Expand Down Expand Up @@ -4678,6 +4697,9 @@ static int __sys_bpf(int cmd, bpfptr_t uattr, unsigned int size)
case BPF_PROG_BIND_MAP:
err = bpf_prog_bind_map(&attr);
break;
case BPF_BTF_VMLINUX_INFO:
err = bpf_btf_get_vmlinux_info(&attr, uattr.user);
break;
default:
err = -EINVAL;
break;
Expand Down
8 changes: 6 additions & 2 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ tprogs-y += xdp_redirect_map_multi
tprogs-y += xdp_redirect_map
tprogs-y += xdp_redirect
tprogs-y += xdp_monitor
tprogs-y += xdp_meta

# Libbpf dependencies
LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a
Expand Down Expand Up @@ -118,6 +119,7 @@ xdp_redirect_cpu-objs := xdp_redirect_cpu_user.o $(XDP_SAMPLE)
xdp_redirect_map-objs := xdp_redirect_map_user.o $(XDP_SAMPLE)
xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE)
xdp_monitor-objs := xdp_monitor_user.o $(XDP_SAMPLE)
xdp_meta-objs := xdp_meta_user.o

# Tell kbuild to always build the programs
always-y := $(tprogs-y)
Expand Down Expand Up @@ -314,6 +316,7 @@ $(obj)/xdp_redirect_map_multi_user.o: $(obj)/xdp_redirect_map_multi.skel.h
$(obj)/xdp_redirect_map_user.o: $(obj)/xdp_redirect_map.skel.h
$(obj)/xdp_redirect_user.o: $(obj)/xdp_redirect.skel.h
$(obj)/xdp_monitor_user.o: $(obj)/xdp_monitor.skel.h
$(obj)/xdp_meta_user.o: $(obj)/xdp_meta.skel.h

$(obj)/tracex5_kern.o: $(obj)/syscall_nrs.h
$(obj)/hbm_out_kern.o: $(src)/hbm.h $(src)/hbm_kern.h
Expand Down Expand Up @@ -371,17 +374,18 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(obj)/vmlinux.h $(src)/xdp_sample.bpf.h $(src)/x
-c $(filter %.bpf.c,$^) -o $@

LINKED_SKELS := xdp_redirect_cpu.skel.h xdp_redirect_map_multi.skel.h \
xdp_redirect_map.skel.h xdp_redirect.skel.h xdp_monitor.skel.h
xdp_redirect_map.skel.h xdp_redirect.skel.h xdp_monitor.skel.h \
xdp_meta.skel.h
clean-files += $(LINKED_SKELS)

xdp_redirect_cpu.skel.h-deps := xdp_redirect_cpu.bpf.o xdp_sample.bpf.o
xdp_redirect_map_multi.skel.h-deps := xdp_redirect_map_multi.bpf.o xdp_sample.bpf.o
xdp_redirect_map.skel.h-deps := xdp_redirect_map.bpf.o xdp_sample.bpf.o
xdp_redirect.skel.h-deps := xdp_redirect.bpf.o xdp_sample.bpf.o
xdp_monitor.skel.h-deps := xdp_monitor.bpf.o xdp_sample.bpf.o
xdp_meta.skel.h-deps := xdp_meta.bpf.o

LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps)))

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops.

BPF_SRCS_LINKED := $(notdir $(wildcard $(src)/*.bpf.c))
BPF_OBJS_LINKED := $(patsubst %.bpf.c,$(obj)/%.bpf.o, $(BPF_SRCS_LINKED))
BPF_SKELS_LINKED := $(addprefix $(obj)/,$(LINKED_SKELS))
Expand Down
Loading