Skip to content

Question on poll Call Position in port_rx_burst Function and sendto Usage in port_tx_burst Function in AF_XDP-forwarding/xsk_fwd.c #121

@binw666

Description

@binw666

I have a couple of questions regarding the implementation of port_rx_burst and port_tx_burst functions in the AF_XDP-forwarding/xsk_fwd.c file.

  1. poll Call Position in port_rx_burst:

    In the port_rx_burst function, I am wondering why the poll call is placed after status = xsk_ring_prod__reserve(&p->umem_fq, n_pkts, &pos); instead of after xsk_ring_prod__submit(&p->umem_fq, n_pkts);. Here is the full function for reference:

    static inline u32
    port_rx_burst(struct port *p, struct burst_rx *b)
    {
    u32 n_pkts, pos, i;
    
    /* Free buffers for FQ replenish. */
    n_pkts = ARRAY_SIZE(b->addr);
    
    n_pkts = bcache_cons_check(p->bc, n_pkts);
    if (!n_pkts)
    return 0;
    
    /* RXQ. */
    n_pkts = xsk_ring_cons__peek(&p->rxq, n_pkts, &pos);
    if (!n_pkts) {
    if (xsk_ring_prod__needs_wakeup(&p->umem_fq)) {
    	struct pollfd pollfd = {
    		.fd = xsk_socket__fd(p->xsk),
    		.events = POLLIN,
    	};
    
    	poll(&pollfd, 1, 0);
    }
    return 0;
    }
    
    for (i = 0; i < n_pkts; i++) {
    b->addr[i] = xsk_ring_cons__rx_desc(&p->rxq, pos + i)->addr;
    b->len[i] = xsk_ring_cons__rx_desc(&p->rxq, pos + i)->len;
    }
    
    xsk_ring_cons__release(&p->rxq, n_pkts);
    p->n_pkts_rx += n_pkts;
    
    /* UMEM FQ. */
    for ( ; ; ) {
    int status;
    
    status = xsk_ring_prod__reserve(&p->umem_fq, n_pkts, &pos);
    if (status == n_pkts)
    	break;
    
    if (xsk_ring_prod__needs_wakeup(&p->umem_fq)) {
    	struct pollfd pollfd = {
    		.fd = xsk_socket__fd(p->xsk),
    		.events = POLLIN,
    	};
    
    	poll(&pollfd, 1, 0);
    }
    }
    
    for (i = 0; i < n_pkts; i++)
    *xsk_ring_prod__fill_addr(&p->umem_fq, pos + i) =
    	bcache_cons(p->bc);
    
    xsk_ring_prod__submit(&p->umem_fq, n_pkts);
    
    return n_pkts;
    }

    In my understanding, poll is typically used to notify the kernel that the fill queue has been filled and is ready for packet reception. Is this understanding correct?

  2. Using poll Instead of sendto in port_tx_burst:

    In the port_tx_burst function, can poll be used instead of sendto to send a message to the kernel? If so, what would be the correct format? Here is the function for reference:

    static inline void
    port_tx_burst(struct port *p, struct burst_tx *b)
    {
    	u32 n_pkts, pos, i;
    	int status;
    
    	/* UMEM CQ. */
    	n_pkts = p->params.bp->umem_cfg.comp_size;
    
    	n_pkts = xsk_ring_cons__peek(&p->umem_cq, n_pkts, &pos);
    
    	for (i = 0; i < n_pkts; i++) {
    		u64 addr = *xsk_ring_cons__comp_addr(&p->umem_cq, pos + i);
    
    		bcache_prod(p->bc, addr);
    	}
    
    	xsk_ring_cons__release(&p->umem_cq, n_pkts);
    
    	/* TXQ. */
    	n_pkts = b->n_pkts;
    
    	for ( ; ; ) {
    		status = xsk_ring_prod__reserve(&p->txq, n_pkts, &pos);
    		if (status == n_pkts)
    			break;
    
    		if (xsk_ring_prod__needs_wakeup(&p->txq))
    			sendto(xsk_socket__fd(p->xsk), NULL, 0, MSG_DONTWAIT,
    			       NULL, 0);
    	}
    
    	for (i = 0; i < n_pkts; i++) {
    		xsk_ring_prod__tx_desc(&p->txq, pos + i)->addr = b->addr[i];
    		xsk_ring_prod__tx_desc(&p->txq, pos + i)->len = b->len[i];
    	}
    
    	xsk_ring_prod__submit(&p->txq, n_pkts);
    	if (xsk_ring_prod__needs_wakeup(&p->txq))
    		sendto(xsk_socket__fd(p->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0);
    	p->n_pkts_tx += n_pkts;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions