mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 05:02:31 +00:00
bpf-for-netdev
-----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQTFp0I1jqZrAX+hPRXbK58LschIgwUCZbIcmAAKCRDbK58LschI gw7OAP4xKTkfcHSZUWcIOWgmdCX41B1zUPdyH2w3woHVH8kKRgEApWisrUKZq30Q 7seUBxVNK1HXBS+egqqRT7Rgs4iFhQs= =iBo/ -----END PGP SIGNATURE----- Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf Daniel Borkmann says: ==================== pull-request: bpf 2024-01-25 The following pull-request contains BPF updates for your *net* tree. We've added 12 non-merge commits during the last 2 day(s) which contain a total of 13 files changed, 190 insertions(+), 91 deletions(-). The main changes are: 1) Fix bpf_xdp_adjust_tail() in context of XSK zero-copy drivers which support XDP multi-buffer. The former triggered a NULL pointer dereference upon shrinking, from Maciej Fijalkowski & Tirthendu Sarkar. 2) Fix a bug in riscv64 BPF JIT which emitted a wrong prologue and epilogue for struct_ops programs, from Pu Lehui. * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: i40e: update xdp_rxq_info::frag_size for ZC enabled Rx queue i40e: set xdp_rxq_info::frag_size xdp: reflect tail increase for MEM_TYPE_XSK_BUFF_POOL ice: update xdp_rxq_info::frag_size for ZC enabled Rx queue intel: xsk: initialize skb_frag_t::bv_offset in ZC drivers ice: remove redundant xdp_rxq_info registration i40e: handle multi-buffer packets that are shrunk by xdp prog ice: work on pre-XDP prog frag count xsk: fix usage of multi-buffer BPF helpers for ZC XDP xsk: make xsk_buff_pool responsible for clearing xdp_buff::flags xsk: recycle buffer in case Rx queue was full riscv, bpf: Fix unpredictable kernel crash about RV64 struct_ops ==================== Link: https://lore.kernel.org/r/20240125084416.10876-1-daniel@iogearbox.net Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
fdf8e6d18c
@ -795,6 +795,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
||||
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
|
||||
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
|
||||
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
|
||||
bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT;
|
||||
void *orig_call = func_addr;
|
||||
bool save_ret;
|
||||
u32 insn;
|
||||
@ -878,7 +879,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
||||
|
||||
stack_size = round_up(stack_size, 16);
|
||||
|
||||
if (func_addr) {
|
||||
if (!is_struct_ops) {
|
||||
/* For the trampoline called from function entry,
|
||||
* the frame of traced function and the frame of
|
||||
* trampoline need to be considered.
|
||||
@ -998,7 +999,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
||||
|
||||
emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx);
|
||||
|
||||
if (func_addr) {
|
||||
if (!is_struct_ops) {
|
||||
/* trampoline called from function entry */
|
||||
emit_ld(RV_REG_T0, stack_size - 8, RV_REG_SP, ctx);
|
||||
emit_ld(RV_REG_FP, stack_size - 16, RV_REG_SP, ctx);
|
||||
|
@ -3588,40 +3588,55 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
|
||||
struct i40e_hmc_obj_rxq rx_ctx;
|
||||
int err = 0;
|
||||
bool ok;
|
||||
int ret;
|
||||
|
||||
bitmap_zero(ring->state, __I40E_RING_STATE_NBITS);
|
||||
|
||||
/* clear the context structure first */
|
||||
memset(&rx_ctx, 0, sizeof(rx_ctx));
|
||||
|
||||
if (ring->vsi->type == I40E_VSI_MAIN)
|
||||
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
|
||||
ring->rx_buf_len = vsi->rx_buf_len;
|
||||
|
||||
/* XDP RX-queue info only needed for RX rings exposed to XDP */
|
||||
if (ring->vsi->type != I40E_VSI_MAIN)
|
||||
goto skip;
|
||||
|
||||
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
|
||||
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->queue_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->rx_buf_len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
ring->xsk_pool = i40e_xsk_pool(ring);
|
||||
if (ring->xsk_pool) {
|
||||
ring->rx_buf_len =
|
||||
xsk_pool_get_rx_frame_size(ring->xsk_pool);
|
||||
ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
xdp_rxq_info_unreg(&ring->xdp_rxq);
|
||||
ring->rx_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool);
|
||||
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->queue_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->rx_buf_len);
|
||||
if (err)
|
||||
return err;
|
||||
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_XSK_BUFF_POOL,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (err)
|
||||
return err;
|
||||
dev_info(&vsi->back->pdev->dev,
|
||||
"Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n",
|
||||
ring->queue_index);
|
||||
|
||||
} else {
|
||||
ring->rx_buf_len = vsi->rx_buf_len;
|
||||
if (ring->vsi->type == I40E_VSI_MAIN) {
|
||||
ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED,
|
||||
NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
skip:
|
||||
xdp_init_buff(&ring->xdp, i40e_rx_pg_size(ring) / 2, &ring->xdp_rxq);
|
||||
|
||||
rx_ctx.dbuff = DIV_ROUND_UP(ring->rx_buf_len,
|
||||
|
@ -1548,7 +1548,6 @@ void i40e_free_rx_resources(struct i40e_ring *rx_ring)
|
||||
int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring)
|
||||
{
|
||||
struct device *dev = rx_ring->dev;
|
||||
int err;
|
||||
|
||||
u64_stats_init(&rx_ring->syncp);
|
||||
|
||||
@ -1569,14 +1568,6 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring)
|
||||
rx_ring->next_to_process = 0;
|
||||
rx_ring->next_to_use = 0;
|
||||
|
||||
/* XDP RX-queue info only needed for RX rings exposed to XDP */
|
||||
if (rx_ring->vsi->type == I40E_VSI_MAIN) {
|
||||
err = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
|
||||
rx_ring->queue_index, rx_ring->q_vector->napi.napi_id);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
rx_ring->xdp_prog = rx_ring->vsi->xdp_prog;
|
||||
|
||||
rx_ring->rx_bi =
|
||||
@ -2087,7 +2078,8 @@ static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
|
||||
static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res,
|
||||
struct xdp_buff *xdp)
|
||||
{
|
||||
u32 next = rx_ring->next_to_clean;
|
||||
u32 nr_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
|
||||
u32 next = rx_ring->next_to_clean, i = 0;
|
||||
struct i40e_rx_buffer *rx_buffer;
|
||||
|
||||
xdp->flags = 0;
|
||||
@ -2100,10 +2092,10 @@ static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res,
|
||||
if (!rx_buffer->page)
|
||||
continue;
|
||||
|
||||
if (xdp_res == I40E_XDP_CONSUMED)
|
||||
rx_buffer->pagecnt_bias++;
|
||||
else
|
||||
if (xdp_res != I40E_XDP_CONSUMED)
|
||||
i40e_rx_buffer_flip(rx_buffer, xdp->frame_sz);
|
||||
else if (i++ <= nr_frags)
|
||||
rx_buffer->pagecnt_bias++;
|
||||
|
||||
/* EOP buffer will be put in i40e_clean_rx_irq() */
|
||||
if (next == rx_ring->next_to_process)
|
||||
@ -2117,20 +2109,20 @@ static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res,
|
||||
* i40e_construct_skb - Allocate skb and populate it
|
||||
* @rx_ring: rx descriptor ring to transact packets on
|
||||
* @xdp: xdp_buff pointing to the data
|
||||
* @nr_frags: number of buffers for the packet
|
||||
*
|
||||
* This function allocates an skb. It then populates it with the page
|
||||
* data from the current receive descriptor, taking care to set up the
|
||||
* skb correctly.
|
||||
*/
|
||||
static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
|
||||
struct xdp_buff *xdp,
|
||||
u32 nr_frags)
|
||||
struct xdp_buff *xdp)
|
||||
{
|
||||
unsigned int size = xdp->data_end - xdp->data;
|
||||
struct i40e_rx_buffer *rx_buffer;
|
||||
struct skb_shared_info *sinfo;
|
||||
unsigned int headlen;
|
||||
struct sk_buff *skb;
|
||||
u32 nr_frags = 0;
|
||||
|
||||
/* prefetch first cache line of first page */
|
||||
net_prefetch(xdp->data);
|
||||
@ -2168,6 +2160,10 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
|
||||
memcpy(__skb_put(skb, headlen), xdp->data,
|
||||
ALIGN(headlen, sizeof(long)));
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp))) {
|
||||
sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
nr_frags = sinfo->nr_frags;
|
||||
}
|
||||
rx_buffer = i40e_rx_bi(rx_ring, rx_ring->next_to_clean);
|
||||
/* update all of the pointers */
|
||||
size -= headlen;
|
||||
@ -2187,9 +2183,8 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
|
||||
}
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp))) {
|
||||
struct skb_shared_info *sinfo, *skinfo = skb_shinfo(skb);
|
||||
struct skb_shared_info *skinfo = skb_shinfo(skb);
|
||||
|
||||
sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
memcpy(&skinfo->frags[skinfo->nr_frags], &sinfo->frags[0],
|
||||
sizeof(skb_frag_t) * nr_frags);
|
||||
|
||||
@ -2212,17 +2207,17 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring,
|
||||
* i40e_build_skb - Build skb around an existing buffer
|
||||
* @rx_ring: Rx descriptor ring to transact packets on
|
||||
* @xdp: xdp_buff pointing to the data
|
||||
* @nr_frags: number of buffers for the packet
|
||||
*
|
||||
* This function builds an skb around an existing Rx buffer, taking care
|
||||
* to set up the skb correctly and avoid any memcpy overhead.
|
||||
*/
|
||||
static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
|
||||
struct xdp_buff *xdp,
|
||||
u32 nr_frags)
|
||||
struct xdp_buff *xdp)
|
||||
{
|
||||
unsigned int metasize = xdp->data - xdp->data_meta;
|
||||
struct skb_shared_info *sinfo;
|
||||
struct sk_buff *skb;
|
||||
u32 nr_frags;
|
||||
|
||||
/* Prefetch first cache line of first page. If xdp->data_meta
|
||||
* is unused, this points exactly as xdp->data, otherwise we
|
||||
@ -2231,6 +2226,11 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
|
||||
*/
|
||||
net_prefetch(xdp->data_meta);
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp))) {
|
||||
sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
nr_frags = sinfo->nr_frags;
|
||||
}
|
||||
|
||||
/* build an skb around the page buffer */
|
||||
skb = napi_build_skb(xdp->data_hard_start, xdp->frame_sz);
|
||||
if (unlikely(!skb))
|
||||
@ -2243,9 +2243,6 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
|
||||
skb_metadata_set(skb, metasize);
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp))) {
|
||||
struct skb_shared_info *sinfo;
|
||||
|
||||
sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
xdp_update_skb_shared_info(skb, nr_frags,
|
||||
sinfo->xdp_frags_size,
|
||||
nr_frags * xdp->frame_sz,
|
||||
@ -2589,9 +2586,9 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget,
|
||||
total_rx_bytes += size;
|
||||
} else {
|
||||
if (ring_uses_build_skb(rx_ring))
|
||||
skb = i40e_build_skb(rx_ring, xdp, nfrags);
|
||||
skb = i40e_build_skb(rx_ring, xdp);
|
||||
else
|
||||
skb = i40e_construct_skb(rx_ring, xdp, nfrags);
|
||||
skb = i40e_construct_skb(rx_ring, xdp);
|
||||
|
||||
/* drop if we failed to retrieve a buffer */
|
||||
if (!skb) {
|
||||
|
@ -414,7 +414,8 @@ i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first,
|
||||
}
|
||||
|
||||
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
|
||||
virt_to_page(xdp->data_hard_start), 0, size);
|
||||
virt_to_page(xdp->data_hard_start),
|
||||
XDP_PACKET_HEADROOM, size);
|
||||
sinfo->xdp_frags_size += size;
|
||||
xsk_buff_add_frag(xdp);
|
||||
|
||||
@ -498,7 +499,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
|
||||
xdp_res = i40e_run_xdp_zc(rx_ring, first, xdp_prog);
|
||||
i40e_handle_xdp_result_zc(rx_ring, first, rx_desc, &rx_packets,
|
||||
&rx_bytes, xdp_res, &failure);
|
||||
first->flags = 0;
|
||||
next_to_clean = next_to_process;
|
||||
if (failure)
|
||||
break;
|
||||
|
@ -547,19 +547,27 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
|
||||
ring->rx_buf_len = ring->vsi->rx_buf_len;
|
||||
|
||||
if (ring->vsi->type == ICE_VSI_PF) {
|
||||
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq))
|
||||
/* coverity[check_return] */
|
||||
__xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->q_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->vsi->rx_buf_len);
|
||||
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
|
||||
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->q_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->rx_buf_len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
ring->xsk_pool = ice_xsk_pool(ring);
|
||||
if (ring->xsk_pool) {
|
||||
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
|
||||
xdp_rxq_info_unreg(&ring->xdp_rxq);
|
||||
|
||||
ring->rx_buf_len =
|
||||
xsk_pool_get_rx_frame_size(ring->xsk_pool);
|
||||
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->q_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->rx_buf_len);
|
||||
if (err)
|
||||
return err;
|
||||
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_XSK_BUFF_POOL,
|
||||
NULL);
|
||||
@ -571,13 +579,14 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
|
||||
dev_info(dev, "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n",
|
||||
ring->q_index);
|
||||
} else {
|
||||
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq))
|
||||
/* coverity[check_return] */
|
||||
__xdp_rxq_info_reg(&ring->xdp_rxq,
|
||||
ring->netdev,
|
||||
ring->q_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->vsi->rx_buf_len);
|
||||
if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) {
|
||||
err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev,
|
||||
ring->q_index,
|
||||
ring->q_vector->napi.napi_id,
|
||||
ring->rx_buf_len);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED,
|
||||
|
@ -513,11 +513,6 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)
|
||||
if (ice_is_xdp_ena_vsi(rx_ring->vsi))
|
||||
WRITE_ONCE(rx_ring->xdp_prog, rx_ring->vsi->xdp_prog);
|
||||
|
||||
if (rx_ring->vsi->type == ICE_VSI_PF &&
|
||||
!xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
|
||||
if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
|
||||
rx_ring->q_index, rx_ring->q_vector->napi.napi_id))
|
||||
goto err;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
@ -603,9 +598,7 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
|
||||
ret = ICE_XDP_CONSUMED;
|
||||
}
|
||||
exit:
|
||||
rx_buf->act = ret;
|
||||
if (unlikely(xdp_buff_has_frags(xdp)))
|
||||
ice_set_rx_bufs_act(xdp, rx_ring, ret);
|
||||
ice_set_rx_bufs_act(xdp, rx_ring, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -893,14 +886,17 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
|
||||
}
|
||||
|
||||
if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
|
||||
if (unlikely(xdp_buff_has_frags(xdp)))
|
||||
ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED);
|
||||
ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page,
|
||||
rx_buf->page_offset, size);
|
||||
sinfo->xdp_frags_size += size;
|
||||
/* remember frag count before XDP prog execution; bpf_xdp_adjust_tail()
|
||||
* can pop off frags but driver has to handle it on its own
|
||||
*/
|
||||
rx_ring->nr_frags = sinfo->nr_frags;
|
||||
|
||||
if (page_is_pfmemalloc(rx_buf->page))
|
||||
xdp_buff_set_frag_pfmemalloc(xdp);
|
||||
@ -1251,6 +1247,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
|
||||
xdp->data = NULL;
|
||||
rx_ring->first_desc = ntc;
|
||||
rx_ring->nr_frags = 0;
|
||||
continue;
|
||||
construct_skb:
|
||||
if (likely(ice_ring_uses_build_skb(rx_ring)))
|
||||
@ -1266,10 +1263,12 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
ICE_XDP_CONSUMED);
|
||||
xdp->data = NULL;
|
||||
rx_ring->first_desc = ntc;
|
||||
rx_ring->nr_frags = 0;
|
||||
break;
|
||||
}
|
||||
xdp->data = NULL;
|
||||
rx_ring->first_desc = ntc;
|
||||
rx_ring->nr_frags = 0;
|
||||
|
||||
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S);
|
||||
if (unlikely(ice_test_staterr(rx_desc->wb.status_error0,
|
||||
|
@ -358,6 +358,7 @@ struct ice_rx_ring {
|
||||
struct ice_tx_ring *xdp_ring;
|
||||
struct ice_rx_ring *next; /* pointer to next ring in q_vector */
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
u32 nr_frags;
|
||||
dma_addr_t dma; /* physical address of ring */
|
||||
u16 rx_buf_len;
|
||||
u8 dcb_tc; /* Traffic class of ring */
|
||||
|
@ -12,26 +12,39 @@
|
||||
* act: action to store onto Rx buffers related to XDP buffer parts
|
||||
*
|
||||
* Set action that should be taken before putting Rx buffer from first frag
|
||||
* to one before last. Last one is handled by caller of this function as it
|
||||
* is the EOP frag that is currently being processed. This function is
|
||||
* supposed to be called only when XDP buffer contains frags.
|
||||
* to the last.
|
||||
*/
|
||||
static inline void
|
||||
ice_set_rx_bufs_act(struct xdp_buff *xdp, const struct ice_rx_ring *rx_ring,
|
||||
const unsigned int act)
|
||||
{
|
||||
const struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
u32 first = rx_ring->first_desc;
|
||||
u32 nr_frags = sinfo->nr_frags;
|
||||
u32 sinfo_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
|
||||
u32 nr_frags = rx_ring->nr_frags + 1;
|
||||
u32 idx = rx_ring->first_desc;
|
||||
u32 cnt = rx_ring->count;
|
||||
struct ice_rx_buf *buf;
|
||||
|
||||
for (int i = 0; i < nr_frags; i++) {
|
||||
buf = &rx_ring->rx_buf[first];
|
||||
buf = &rx_ring->rx_buf[idx];
|
||||
buf->act = act;
|
||||
|
||||
if (++first == cnt)
|
||||
first = 0;
|
||||
if (++idx == cnt)
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
/* adjust pagecnt_bias on frags freed by XDP prog */
|
||||
if (sinfo_frags < rx_ring->nr_frags && act == ICE_XDP_CONSUMED) {
|
||||
u32 delta = rx_ring->nr_frags - sinfo_frags;
|
||||
|
||||
while (delta) {
|
||||
if (idx == 0)
|
||||
idx = cnt - 1;
|
||||
else
|
||||
idx--;
|
||||
buf = &rx_ring->rx_buf[idx];
|
||||
buf->pagecnt_bias--;
|
||||
delta--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,7 +825,8 @@ ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first,
|
||||
}
|
||||
|
||||
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
|
||||
virt_to_page(xdp->data_hard_start), 0, size);
|
||||
virt_to_page(xdp->data_hard_start),
|
||||
XDP_PACKET_HEADROOM, size);
|
||||
sinfo->xdp_frags_size += size;
|
||||
xsk_buff_add_frag(xdp);
|
||||
|
||||
@ -895,7 +896,6 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
|
||||
|
||||
if (!first) {
|
||||
first = xdp;
|
||||
xdp_buff_clear_frags_flag(first);
|
||||
} else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) {
|
||||
break;
|
||||
}
|
||||
|
@ -159,11 +159,29 @@ static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void xsk_buff_del_tail(struct xdp_buff *tail)
|
||||
{
|
||||
struct xdp_buff_xsk *xskb = container_of(tail, struct xdp_buff_xsk, xdp);
|
||||
|
||||
list_del(&xskb->xskb_list_node);
|
||||
}
|
||||
|
||||
static inline struct xdp_buff *xsk_buff_get_tail(struct xdp_buff *first)
|
||||
{
|
||||
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
|
||||
struct xdp_buff_xsk *frag;
|
||||
|
||||
frag = list_last_entry(&xskb->pool->xskb_list, struct xdp_buff_xsk,
|
||||
xskb_list_node);
|
||||
return &frag->xdp;
|
||||
}
|
||||
|
||||
static inline void xsk_buff_set_size(struct xdp_buff *xdp, u32 size)
|
||||
{
|
||||
xdp->data = xdp->data_hard_start + XDP_PACKET_HEADROOM;
|
||||
xdp->data_meta = xdp->data;
|
||||
xdp->data_end = xdp->data + size;
|
||||
xdp->flags = 0;
|
||||
}
|
||||
|
||||
static inline dma_addr_t xsk_buff_raw_get_dma(struct xsk_buff_pool *pool,
|
||||
@ -350,6 +368,15 @@ static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void xsk_buff_del_tail(struct xdp_buff *tail)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct xdp_buff *xsk_buff_get_tail(struct xdp_buff *first)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void xsk_buff_set_size(struct xdp_buff *xdp, u32 size)
|
||||
{
|
||||
}
|
||||
|
@ -83,6 +83,7 @@
|
||||
#include <net/netfilter/nf_conntrack_bpf.h>
|
||||
#include <net/netkit.h>
|
||||
#include <linux/un.h>
|
||||
#include <net/xdp_sock_drv.h>
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
@ -4092,10 +4093,46 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
|
||||
memset(skb_frag_address(frag) + skb_frag_size(frag), 0, offset);
|
||||
skb_frag_size_add(frag, offset);
|
||||
sinfo->xdp_frags_size += offset;
|
||||
if (rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL)
|
||||
xsk_buff_get_tail(xdp)->data_end += offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,
|
||||
struct xdp_mem_info *mem_info, bool release)
|
||||
{
|
||||
struct xdp_buff *zc_frag = xsk_buff_get_tail(xdp);
|
||||
|
||||
if (release) {
|
||||
xsk_buff_del_tail(zc_frag);
|
||||
__xdp_return(NULL, mem_info, false, zc_frag);
|
||||
} else {
|
||||
zc_frag->data_end -= shrink;
|
||||
}
|
||||
}
|
||||
|
||||
static bool bpf_xdp_shrink_data(struct xdp_buff *xdp, skb_frag_t *frag,
|
||||
int shrink)
|
||||
{
|
||||
struct xdp_mem_info *mem_info = &xdp->rxq->mem;
|
||||
bool release = skb_frag_size(frag) == shrink;
|
||||
|
||||
if (mem_info->type == MEM_TYPE_XSK_BUFF_POOL) {
|
||||
bpf_xdp_shrink_data_zc(xdp, shrink, mem_info, release);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (release) {
|
||||
struct page *page = skb_frag_page(frag);
|
||||
|
||||
__xdp_return(page_address(page), mem_info, false, NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
return release;
|
||||
}
|
||||
|
||||
static int bpf_xdp_frags_shrink_tail(struct xdp_buff *xdp, int offset)
|
||||
{
|
||||
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
|
||||
@ -4110,12 +4147,7 @@ static int bpf_xdp_frags_shrink_tail(struct xdp_buff *xdp, int offset)
|
||||
|
||||
len_free += shrink;
|
||||
offset -= shrink;
|
||||
|
||||
if (skb_frag_size(frag) == shrink) {
|
||||
struct page *page = skb_frag_page(frag);
|
||||
|
||||
__xdp_return(page_address(page), &xdp->rxq->mem,
|
||||
false, NULL);
|
||||
if (bpf_xdp_shrink_data(xdp, frag, shrink)) {
|
||||
n_frags_free++;
|
||||
} else {
|
||||
skb_frag_size_sub(frag, shrink);
|
||||
|
@ -167,8 +167,10 @@ static int xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
|
||||
contd = XDP_PKT_CONTD;
|
||||
|
||||
err = __xsk_rcv_zc(xs, xskb, len, contd);
|
||||
if (err || likely(!frags))
|
||||
goto out;
|
||||
if (err)
|
||||
goto err;
|
||||
if (likely(!frags))
|
||||
return 0;
|
||||
|
||||
xskb_list = &xskb->pool->xskb_list;
|
||||
list_for_each_entry_safe(pos, tmp, xskb_list, xskb_list_node) {
|
||||
@ -177,11 +179,13 @@ static int xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
|
||||
len = pos->xdp.data_end - pos->xdp.data;
|
||||
err = __xsk_rcv_zc(xs, pos, len, contd);
|
||||
if (err)
|
||||
return err;
|
||||
goto err;
|
||||
list_del(&pos->xskb_list_node);
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
err:
|
||||
xsk_buff_free(xdp);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -555,6 +555,7 @@ struct xdp_buff *xp_alloc(struct xsk_buff_pool *pool)
|
||||
|
||||
xskb->xdp.data = xskb->xdp.data_hard_start + XDP_PACKET_HEADROOM;
|
||||
xskb->xdp.data_meta = xskb->xdp.data;
|
||||
xskb->xdp.flags = 0;
|
||||
|
||||
if (pool->dma_need_sync) {
|
||||
dma_sync_single_range_for_device(pool->dev, xskb->dma, 0,
|
||||
|
Loading…
Reference in New Issue
Block a user