Re: AF_XDP only releasing from FQ in batches

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On 21 Jun 2019, at 21:20, Rafael Vargas wrote:

Hi,

I'm trying to use AF_XDP and I'm using the xdpsock sample
implementation as a guide.

I've noticed that the Fill Queue slots are released in batches of 16
(kernel 5.1)

The xdpsock (rx_drop) implementation will lock waiting for the space in the FQ.
This seems it will work fine when receiving lots of packets, but will
loop indefinetely if traffic stops.

Yes I was running into the same problem, and you should not wait wait for the free slots, as that will put you in a loop waiting, and not processing packets until 16 are received.

This is how I solved it:


static void rx_pkts(struct xsk_socket_info *xsk)
{
  	unsigned int rcvd, stock_frames, i;
  	uint32_t idx_rx = 0, idx_fq = 0;
  	int ret;

  	rcvd = xsk_ring_cons__peek(&xsk->rx, RX_BATCH_SIZE, &idx_rx);
  	if (!rcvd)
  		return;

	/* Stuff the ring with as much frames as possible */
	stock_frames = xsk_ring_prod__free(&xsk->umem->fq);
	stock_frames = MIN(stock_frames, xsk_umem_free_frames(xsk));

	if (stock_frames > 0) {

		ret = xsk_ring_prod__reserve(&xsk->umem->fq, stock_frames,
					     &idx_fq);
		while (ret != stock_frames)
			ret = xsk_ring_prod__reserve(&xsk->umem->fq, rcvd,
						     &idx_fq);

		for (i = 0; i < stock_frames; i++)
			*xsk_ring_prod__fill_addr(&xsk->umem->fq, idx_fq++) =
				xsk_alloc_umem_frame(xsk);

		xsk_ring_prod__submit(&xsk->umem->fq, stock_frames);
	}

	/* Process received packets */
  	for (i = 0; i < rcvd; i++) {
  		uint64_t addr = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx)->addr;
  		uint32_t len = xsk_ring_cons__rx_desc(&xsk->rx, idx_rx++)->len;
  		char *pkt = xsk_umem__get_data(xsk->umem->buffer, addr);

  		// Handle packet

		xsk_free_umem_frame(xsk, addr);
  	}

  	xsk_ring_cons__release(&xsk->rx, rcvd);
	xsk->stats.rx_packets += rcvd;
  }


Where xsk_ring_prod__free() is as follows (sent patch upstream for adding it as an API):

static inline __u32 xsk_ring_prod__free(struct xsk_ring_prod *r)
{
  	r->cached_cons = *r->consumer + r->size;
	return r->cached_cons - r->cached_prod;
}

And the following is an API around my UMEM frame handling:

xsk_umem_free_frames() -> How many buffers do I have available on my stack

xsk_free_umem_frame()  -> return a buffer to my buffer stack

xsk_alloc_umem_frame() -> Get a buffer from my buffer stack

This is the expected behavior for the FQ?
Should I keep the FQ always with free slots in order to avoid blocking
when waiting for more packets?

Rafael Vargas



[Index of Archives]     [Linux Networking Development]     [Fedora Linux Users]     [Linux SCTP]     [DCCP]     [Gimp]     [Yosemite Campsites]

  Powered by Linux