Skip to content
Closed
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
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();

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
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)))

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
53 changes: 53 additions & 0 deletions samples/bpf/xdp_meta.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#include "vmlinux.h"

#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>

SEC("xdp")
int xdp_meta_prog(struct xdp_md *ctx)
{
struct xdp_meta_generic *data_meta =
(void *)(long)ctx->data_meta;
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
struct ethhdr *eth = data;
u64 nh_off;
u32 btf_id_libbpf;
u32 btf_id_meta;
u16 rxcvid;
u32 hash;
long *value;

nh_off = sizeof(*eth);
if (data + nh_off > data_end)
return XDP_DROP;


if (data_meta + 1 > data)
return XDP_DROP;

btf_id_libbpf = bpf_core_type_id_kernel(struct xdp_meta_generic);
bpf_probe_read_kernel(&btf_id_meta, sizeof(btf_id_meta), (void*)data - 4);

bpf_printk("id from libbpf %d, id from hints metadata %d\n",
btf_id_libbpf, btf_id_meta);

if (btf_id_libbpf == btf_id_meta)
bpf_printk("Received meta is generic\n");
else
bpf_printk("Received meta type is unknown\n");


hash = BPF_CORE_READ(data_meta, hash);
rxcvid = BPF_CORE_READ(data_meta, rxcvid);
bpf_printk("Metadata. Hash: 0x%x, VID: %d\n", hash, rxcvid);

return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";
Loading