Skip to content

Commit b1eac30

Browse files
committed
Merge branch 'enetc-bug-fixes-for-bpf_xdp_adjust_head-and-bpf_xdp_adjust_tail'
Vladimir Oltean says: ==================== ENETC bug fixes for bpf_xdp_adjust_head() and bpf_xdp_adjust_tail() It has been reported that on the ENETC driver, bpf_xdp_adjust_head() and bpf_xdp_adjust_tail() are broken in combination with the XDP_PASS verdict. I have constructed a series a simple XDP programs and tested with various packet sizes and confirmed that this is the case. Patch 3/3 fixes the core issue, which is that the sk_buff created on XDP_PASS is created by the driver as if XDP never ran, but in fact the geometry needs to be adjusted according to the delta applied by the program on the original xdp_buff. It depends on commit 539c1fb ("xdp: add generic xdp_build_skb_from_buff()") which is not available in "stable" but perhaps should be. Patch 2/3 is a small refactor necessary for 3/3. Patch 1/3 fixes a related issue I noticed, which is that bpf_xdp_adjust_tail() with a positive offset works for linear XDP buffers, but returns an error for non-linear ones, even if there is plenty of space in the final page fragment. ==================== Link: https://patch.msgid.link/20250417120005.3288549-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents cc3628d + 020f0c8 commit b1eac30

File tree

1 file changed

+28
-17
lines changed
  • drivers/net/ethernet/freescale/enetc

1 file changed

+28
-17
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,6 +1850,16 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first,
18501850
}
18511851
}
18521852

1853+
static void enetc_bulk_flip_buff(struct enetc_bdr *rx_ring, int rx_ring_first,
1854+
int rx_ring_last)
1855+
{
1856+
while (rx_ring_first != rx_ring_last) {
1857+
enetc_flip_rx_buff(rx_ring,
1858+
&rx_ring->rx_swbd[rx_ring_first]);
1859+
enetc_bdr_idx_inc(rx_ring, &rx_ring_first);
1860+
}
1861+
}
1862+
18531863
static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
18541864
struct napi_struct *napi, int work_limit,
18551865
struct bpf_prog *prog)
@@ -1868,11 +1878,10 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
18681878

18691879
while (likely(rx_frm_cnt < work_limit)) {
18701880
union enetc_rx_bd *rxbd, *orig_rxbd;
1871-
int orig_i, orig_cleaned_cnt;
18721881
struct xdp_buff xdp_buff;
18731882
struct sk_buff *skb;
1883+
int orig_i, err;
18741884
u32 bd_status;
1875-
int err;
18761885

18771886
rxbd = enetc_rxbd(rx_ring, i);
18781887
bd_status = le32_to_cpu(rxbd->r.lstatus);
@@ -1887,7 +1896,6 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
18871896
break;
18881897

18891898
orig_rxbd = rxbd;
1890-
orig_cleaned_cnt = cleaned_cnt;
18911899
orig_i = i;
18921900

18931901
enetc_build_xdp_buff(rx_ring, bd_status, &rxbd, &i,
@@ -1915,15 +1923,21 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
19151923
rx_ring->stats.xdp_drops++;
19161924
break;
19171925
case XDP_PASS:
1918-
rxbd = orig_rxbd;
1919-
cleaned_cnt = orig_cleaned_cnt;
1920-
i = orig_i;
1921-
1922-
skb = enetc_build_skb(rx_ring, bd_status, &rxbd,
1923-
&i, &cleaned_cnt,
1924-
ENETC_RXB_DMA_SIZE_XDP);
1925-
if (unlikely(!skb))
1926+
skb = xdp_build_skb_from_buff(&xdp_buff);
1927+
/* Probably under memory pressure, stop NAPI */
1928+
if (unlikely(!skb)) {
1929+
enetc_xdp_drop(rx_ring, orig_i, i);
1930+
rx_ring->stats.xdp_drops++;
19261931
goto out;
1932+
}
1933+
1934+
enetc_get_offloads(rx_ring, orig_rxbd, skb);
1935+
1936+
/* These buffers are about to be owned by the stack.
1937+
* Update our buffer cache (the rx_swbd array elements)
1938+
* with their other page halves.
1939+
*/
1940+
enetc_bulk_flip_buff(rx_ring, orig_i, i);
19271941

19281942
napi_gro_receive(napi, skb);
19291943
break;
@@ -1965,11 +1979,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
19651979
enetc_xdp_drop(rx_ring, orig_i, i);
19661980
rx_ring->stats.xdp_redirect_failures++;
19671981
} else {
1968-
while (orig_i != i) {
1969-
enetc_flip_rx_buff(rx_ring,
1970-
&rx_ring->rx_swbd[orig_i]);
1971-
enetc_bdr_idx_inc(rx_ring, &orig_i);
1972-
}
1982+
enetc_bulk_flip_buff(rx_ring, orig_i, i);
19731983
xdp_redirect_frm_cnt++;
19741984
rx_ring->stats.xdp_redirect++;
19751985
}
@@ -3362,7 +3372,8 @@ static int enetc_int_vector_init(struct enetc_ndev_priv *priv, int i,
33623372
bdr->buffer_offset = ENETC_RXB_PAD;
33633373
priv->rx_ring[i] = bdr;
33643374

3365-
err = xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0);
3375+
err = __xdp_rxq_info_reg(&bdr->xdp.rxq, priv->ndev, i, 0,
3376+
ENETC_RXB_DMA_SIZE_XDP);
33663377
if (err)
33673378
goto free_vector;
33683379

0 commit comments

Comments
 (0)