From 36335fefe63a4da6a1ff4f2a57e338217df64c46 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Thu, 23 Sep 2021 18:40:43 -0400 Subject: [PATCH] btf: ice: implement finding BTF type id Function btf_get_type_id is needed to get correct BTF id to fill metadata by driver. BTF id is obtained while loading XDP program and saved in ring structure to be available in irq. Calling btf_get_type_id with null pointer as module will result in searching for BTF id in vmlinux. Also cleanup sample code to print id from metadata and from libbpf. Moving btf_id in generic metadata structure is temporary solution. Signed-off-by: Ederson de Souza Signed-off-by: Michal Swiatkowski --- drivers/net/ethernet/intel/ice/ice.h | 2 + drivers/net/ethernet/intel/ice/ice_main.c | 12 ++++-- drivers/net/ethernet/intel/ice/ice_txrx.c | 3 +- drivers/net/ethernet/intel/ice/ice_txrx.h | 1 + drivers/net/ethernet/intel/ice/ice_txrx_lib.h | 14 ++++++- include/linux/btf.h | 1 + include/net/xdp.h | 6 +-- kernel/bpf/btf.c | 37 +++++++++++++++++++ samples/bpf/xdp_meta.bpf.c | 14 ++++--- 9 files changed, 76 insertions(+), 14 deletions(-) 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; }