Commit 76a67694 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Alexei Starovoitov
Browse files

net: mvneta: update frags bit before passing the xdp buffer to eBPF layer



Update frags bit (XDP_FLAGS_HAS_FRAGS) in xdp_buff to notify
XDP/eBPF layer and XDP remote drivers if this is a "non-linear"
XDP buffer. Access skb_shared_info only if XDP_FLAGS_HAS_FRAGS flag
is set in order to avoid possible cache-misses.

Acked-by: default avatarToke Hoiland-Jorgensen <toke@redhat.com>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/r/c00a73097f8a35860d50dae4a36e6cc9ef7e172f.1642758637.git.lorenzo@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 2e88d4ff
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -2065,9 +2065,14 @@ mvneta_xdp_put_buff(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
{
	int i;

	if (likely(!xdp_buff_has_frags(xdp)))
		goto out;

	for (i = 0; i < sinfo->nr_frags; i++)
		page_pool_put_full_page(rxq->page_pool,
					skb_frag_page(&sinfo->frags[i]), true);

out:
	page_pool_put_page(rxq->page_pool, virt_to_head_page(xdp->data),
			   sync_len, true);
}
@@ -2269,7 +2274,6 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,
	int data_len = -MVNETA_MH_SIZE, len;
	struct net_device *dev = pp->dev;
	enum dma_data_direction dma_dir;
	struct skb_shared_info *sinfo;

	if (*size > MVNETA_MAX_RX_BUF_SIZE) {
		len = MVNETA_MAX_RX_BUF_SIZE;
@@ -2289,11 +2293,9 @@ mvneta_swbm_rx_frame(struct mvneta_port *pp,

	/* Prefetch header */
	prefetch(data);
	xdp_buff_clear_frags_flag(xdp);
	xdp_prepare_buff(xdp, data, pp->rx_offset_correction + MVNETA_MH_SIZE,
			 data_len, false);

	sinfo = xdp_get_shared_info_from_buff(xdp);
	sinfo->nr_frags = 0;
}

static void
@@ -2327,6 +2329,9 @@ mvneta_swbm_add_rx_fragment(struct mvneta_port *pp,
		skb_frag_off_set(frag, pp->rx_offset_correction);
		skb_frag_size_set(frag, data_len);
		__skb_frag_set_page(frag, page);

		if (!xdp_buff_has_frags(xdp))
			xdp_buff_set_frags_flag(xdp);
	} else {
		page_pool_put_full_page(rxq->page_pool, page, true);
	}
@@ -2348,8 +2353,12 @@ 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;
	struct sk_buff *skb;
	u8 num_frags;
	int i;

	if (unlikely(xdp_buff_has_frags(xdp)))
		num_frags = sinfo->nr_frags;

	skb = build_skb(xdp->data_hard_start, PAGE_SIZE);
	if (!skb)
@@ -2361,6 +2370,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);

	if (likely(!xdp_buff_has_frags(xdp)))
		goto out;

	for (i = 0; i < num_frags; i++) {
		skb_frag_t *frag = &sinfo->frags[i];

@@ -2369,6 +2381,7 @@ mvneta_swbm_build_skb(struct mvneta_port *pp, struct page_pool *pool,
				skb_frag_size(frag), PAGE_SIZE);
	}

out:
	return skb;
}