net/xdp/xsk_buff_pool.c

Source file repositories/reference/linux-study-clean/net/xdp/xsk_buff_pool.c

File Facts

System
Linux kernel
Corpus path
net/xdp/xsk_buff_pool.c
Extension
.c
Size
17490 bytes
Lines
781
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (segs == 1) {
			err = -EOPNOTSUPP;
			goto err_unreg_pool;
		}
	} else {
		segs = 1;
	}

	/* open-code xsk_pool_get_rx_frame_size() as pool->dev is not
	 * set yet at this point; we are before getting down to driver
	 */
	frame_size = __xsk_pool_get_rx_frame_size(pool) -
		     xsk_pool_get_tailroom(mbuf);
	frame_size = ALIGN_DOWN(frame_size, 128);

	if (needed > frame_size * segs) {
		err = -EINVAL;
		goto err_unreg_pool;
	}

	if (dev_get_min_mp_channel_count(netdev)) {
		err = -EBUSY;
		goto err_unreg_pool;
	}

	bpf.command = XDP_SETUP_XSK_POOL;
	bpf.xsk.pool = pool;
	bpf.xsk.queue_id = queue_id;

	netdev_assert_locked_ops_compat(netdev);
	err = netdev->netdev_ops->ndo_bpf(netdev, &bpf);
	if (err)
		goto err_unreg_pool;

	if (!pool->dma_pages) {
		WARN(1, "Driver did not DMA map zero-copy buffers");
		err = -EINVAL;
		goto err_unreg_xsk;
	}
	pool->umem->zc = true;
	pool->xdp_zc_max_segs = netdev->xdp_zc_max_segs;
	return 0;

err_unreg_xsk:
	xp_disable_drv_zc(pool);
err_unreg_pool:
	if (!force_zc)
		err = 0; /* fallback to copy mode */
	if (err) {
		xsk_clear_pool_at_qid(netdev, queue_id);
		dev_put(netdev);
	}
	return err;
}

int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs,
			 struct net_device *dev, u16 queue_id)
{
	u16 flags;
	struct xdp_umem *umem = umem_xs->umem;

	flags = umem->zc ? XDP_ZEROCOPY : XDP_COPY;

	if (umem->flags & XDP_UMEM_SG_FLAG)
		flags |= XDP_USE_SG;

	if (umem_xs->pool->uses_need_wakeup)
		flags |= XDP_USE_NEED_WAKEUP;

	return xp_assign_dev(pool, dev, queue_id, flags);
}

void xp_clear_dev(struct xsk_buff_pool *pool)
{
	struct net_device *netdev = pool->netdev;

	if (!pool->netdev)
		return;

	netdev_lock_ops(netdev);
	xp_disable_drv_zc(pool);
	xsk_clear_pool_at_qid(pool->netdev, pool->queue_id);
	pool->netdev = NULL;
	netdev_unlock_ops(netdev);
	dev_put(netdev);
}

static void xp_release_deferred(struct work_struct *work)
{
	struct xsk_buff_pool *pool = container_of(work, struct xsk_buff_pool,

Annotation

Implementation Notes