diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index d2441c8192919c..a73f500c9be82f 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -350,6 +351,7 @@ struct ice_vsi { 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 diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 50a3b9adc1d447..e81f2944b1ab80 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2423,11 +2423,15 @@ static void ice_xdp_rings_set_metadata(struct ice_vsi *vsi) { int i; - ice_for_each_rxq(vsi, 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++) + 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; + } } /** @@ -2646,8 +2650,10 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, } } - if (flags & XDP_FLAGS_USE_METADATA) + 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; diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 128fd49383439a..f52ab7b2e3258f 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1137,7 +1137,8 @@ int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget) xdp_prepare_buff(&xdp, hard_start, offset, size, true); if (likely(rx_ring->xdp_metadata_support)) - ice_xdp_set_meta(&xdp, rx_desc); + 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); diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index b43923ddf883cf..9419d4780acc1b 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -302,6 +302,7 @@ 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 diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h index d77bc7686b61bd..54c8acab1691b0 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h @@ -46,14 +46,24 @@ 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) +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); - xdp->data_meta = md; 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); diff --git a/include/linux/btf.h b/include/linux/btf.h index 214fde93214b97..cd26d037a2dda5 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -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, diff --git a/include/net/xdp.h b/include/net/xdp.h index 9c4d3c9ddc7de9..06d7012b438341 100644 --- a/include/net/xdp.h +++ b/include/net/xdp.h @@ -77,6 +77,9 @@ struct xdp_buff { }; struct xdp_meta_generic { + // BTF ID + u32 btf_id; + // Tx part u32 flags; u16 free_slot; @@ -88,9 +91,6 @@ struct xdp_meta_generic { u32 csum; u32 hash; u64 tstamp; - - // BTF ID - u32 btf_id; } __packed __aligned(8); static_assert(sizeof(struct xdp_meta_generic) == 32); diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index dfe61df4f974d1..10fd0405fec9da 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -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; diff --git a/samples/bpf/xdp_meta.bpf.c b/samples/bpf/xdp_meta.bpf.c index 8f49b11ab160a6..2781926cffd2ed 100644 --- a/samples/bpf/xdp_meta.bpf.c +++ b/samples/bpf/xdp_meta.bpf.c @@ -8,17 +8,18 @@ #include #include -struct xdp_meta_generic___empty { - u32 btf_id; +struct xdp_meta_generic___btf { + u32 btf_id; }; SEC("xdp") int xdp_meta_prog(struct xdp_md *ctx) { - struct xdp_meta_generic___empty *data_meta = + struct xdp_meta_generic___btf *data_meta = (void *)(long)ctx->data_meta; void *data_end = (void *)(long)ctx->data_end; void *data = (void *)(long)ctx->data; + u32 *btf_id = (void *)((long)ctx->data - 4); struct ethhdr *eth = data; u64 nh_off; int id; @@ -31,8 +32,11 @@ int xdp_meta_prog(struct xdp_md *ctx) if (data_meta + 1 > data) return XDP_DROP; - id = bpf_core_type_id_kernel(struct xdp_meta_generic___empty); - bpf_printk("id is %d\n", id); + id = bpf_core_type_id_kernel(struct xdp_meta_generic___btf); + bpf_printk("id from libbpf %d, id from hints metadata %d\n", id, data_meta->btf_id); + + if (id && id == data_meta->btf_id) + bpf_printk("hints match btf_id\n"); return XDP_PASS; }