[PATCH bpf-next 2/2] net: xdp: add xdp_update_skb_shared_info utility routine
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: 2021-07-09 11:10:55
Also in:
bpf
Subsystem:
marvell mvneta ethernet driver, networking drivers, networking [general], the rest, xdp (express data path) · Maintainers:
Marcin Wojtas, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend
Introduce xdp_update_skb_shared_info routine to update frags array metadata from a given xdp_buffer/xdp_frame. We do not need to reset frags array since it is already initialized by the driver. Rely on xdp_update_skb_shared_info in mvneta driver. Suggested-by: Alexander Duyck <redacted> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> --- drivers/net/ethernet/marvell/mvneta.c | 29 +++++++++++++++------------ include/net/xdp.h | 3 +++ net/core/xdp.c | 27 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 361bc4fbe20b..abf2e50880e0 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c@@ -2294,18 +2294,29 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp, rx_desc->buf_phys_addr = 0; if (data_len > 0 && xdp_sinfo->nr_frags < MAX_SKB_FRAGS) { - skb_frag_t *frag = &xdp_sinfo->frags[xdp_sinfo->nr_frags++]; + skb_frag_t *frag = &xdp_sinfo->frags[xdp_sinfo->nr_frags]; skb_frag_off_set(frag, pp->rx_offset_correction); skb_frag_size_set(frag, data_len); __skb_frag_set_page(frag, page); + /* We don't need to reset pp_recycle here. It's already set, so + * just mark fragments for recycling. + */ + page_pool_store_mem_info(page, rxq->page_pool); + + /* first fragment */ + if (!xdp_sinfo->nr_frags) + xdp_sinfo->gso_type = *size; + xdp_sinfo->nr_frags++; /* last fragment */ if (len == *size) { struct skb_shared_info *sinfo; sinfo = xdp_get_shared_info_from_buff(xdp); + sinfo->xdp_frags_tsize = xdp_sinfo->nr_frags * PAGE_SIZE; sinfo->nr_frags = xdp_sinfo->nr_frags; + sinfo->gso_type = xdp_sinfo->gso_type; memcpy(sinfo->frags, xdp_sinfo->frags, sinfo->nr_frags * sizeof(skb_frag_t)); }
@@ -2320,7 +2331,7 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool, struct xdp_buff *xdp, u32 desc_status) { struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); - int i, num_frags = sinfo->nr_frags; + int num_frags = sinfo->nr_frags, size = sinfo->gso_type; struct sk_buff *skb; skb = build_skb(xdp->data_hard_start, PAGE_SIZE);
@@ -2333,17 +2344,9 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool, skb_put(skb, xdp->data_end - xdp->data); skb->ip_summed = mvneta_rx_csum(pp, desc_status); - for (i = 0; i < num_frags; i++) { - skb_frag_t *frag = &sinfo->frags[i]; - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, - skb_frag_page(frag), skb_frag_off(frag), - skb_frag_size(frag), PAGE_SIZE); - /* We don't need to reset pp_recycle here. It's already set, so - * just mark fragments for recycling. - */ - page_pool_store_mem_info(skb_frag_page(frag), pool); - } + if (num_frags) + xdp_update_skb_shared_info(skb, num_frags, size, + sinfo->xdp_frags_tsize, sinfo); return skb; }
diff --git a/include/net/xdp.h b/include/net/xdp.h
index ad5b02dcb6f4..08d151ea8400 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h@@ -164,6 +164,9 @@ void xdp_warn(const char *msg, const char *func, const int line); #define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__) struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp); +void xdp_update_skb_shared_info(struct sk_buff *skb, int nr_frags, + int size, int truesize, + struct skb_shared_info *sinfo); struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf, struct sk_buff *skb, struct net_device *dev);
diff --git a/net/core/xdp.c b/net/core/xdp.c
index cc92ccb38432..3f44c69e1f56 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c@@ -527,6 +527,33 @@ int xdp_alloc_skb_bulk(void **skbs, int n_skb, gfp_t gfp) } EXPORT_SYMBOL_GPL(xdp_alloc_skb_bulk); +void xdp_update_skb_shared_info(struct sk_buff *skb, int nr_frags, + int size, int truesize, + struct skb_shared_info *sinfo) +{ + int i; + + skb_shinfo(skb)->nr_frags = nr_frags; + + skb->len += size; + skb->data_len += size; + skb->truesize += truesize; + + if (skb->pfmemalloc) + return; + + for (i = 0; i < nr_frags; i++) { + struct page *page = skb_frag_page(&sinfo->frags[i]); + + page = compound_head(page); + if (page_is_pfmemalloc(page)) { + skb->pfmemalloc = true; + break; + } + } +} +EXPORT_SYMBOL_GPL(xdp_update_skb_shared_info); + struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf, struct sk_buff *skb, struct net_device *dev)
--
2.31.1