#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <poll.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/socket.h>
rte_log(RTE_LOG_ ## level, af_xdp_logtype, \
"%s(): " fmt, __func__, ##args)
-#define ETH_AF_XDP_FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE
+#define ETH_AF_XDP_FRAME_SIZE 2048
#define ETH_AF_XDP_NUM_BUFFERS 4096
#define ETH_AF_XDP_DATA_HEADROOM 0
#define ETH_AF_XDP_DFLT_NUM_DESCS XSK_RING_CONS__DEFAULT_NUM_DESCS
struct rx_stats stats;
struct pkt_tx_queue *pair;
+ struct pollfd fds[1];
int xsk_queue_idx;
};
struct tx_stats {
uint64_t tx_pkts;
- uint64_t err_pkts;
uint64_t tx_bytes;
};
int pmd_zc;
struct rte_ether_addr eth_addr;
- struct rte_mempool *mb_pool_share;
struct pkt_rx_queue *rx_queues;
struct pkt_tx_queue *tx_queues;
return 0;
rcvd = xsk_ring_cons__peek(rx, nb_pkts, &idx_rx);
- if (rcvd == 0)
+ if (rcvd == 0) {
+#if defined(XDP_USE_NEED_WAKEUP)
+ if (xsk_ring_prod__needs_wakeup(fq))
+ (void)poll(rxq->fds, 1, 1000);
+#endif
+
goto out;
+ }
if (xsk_prod_nb_free(fq, free_thresh) >= free_thresh)
(void)reserve_fill_queue(umem, ETH_AF_XDP_RX_BATCH_SIZE);
{
struct xsk_umem_info *umem = txq->pair->umem;
- while (send(xsk_socket__fd(txq->pair->xsk), NULL,
- 0, MSG_DONTWAIT) < 0) {
- /* some thing unexpected */
- if (errno != EBUSY && errno != EAGAIN && errno != EINTR)
- break;
-
- /* pull from completion queue to leave more space */
- if (errno == EAGAIN)
- pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
- }
+#if defined(XDP_USE_NEED_WAKEUP)
+ if (xsk_ring_prod__needs_wakeup(&txq->tx))
+#endif
+ while (send(xsk_socket__fd(txq->pair->xsk), NULL,
+ 0, MSG_DONTWAIT) < 0) {
+ /* some thing unexpected */
+ if (errno != EBUSY && errno != EAGAIN && errno != EINTR)
+ break;
+
+ /* pull from completion queue to leave more space */
+ if (errno == EAGAIN)
+ pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
+ }
pull_umem_cq(umem, ETH_AF_XDP_TX_BATCH_SIZE);
}
return 0;
}
-static void
+static int
eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
{
struct pmd_internals *internals = dev->data->dev_private;
dev_info->default_txportconf.nb_queues = 1;
dev_info->default_rxportconf.ring_size = ETH_AF_XDP_DFLT_NUM_DESCS;
dev_info->default_txportconf.ring_size = ETH_AF_XDP_DFLT_NUM_DESCS;
+
+ return 0;
}
static int
stats->imissed += xdp_stats.rx_dropped;
stats->opackets += stats->q_opackets[i];
- stats->oerrors += txq->stats.err_pkts;
stats->obytes += stats->q_obytes[i];
}
return 0;
}
-static void
+static int
eth_stats_reset(struct rte_eth_dev *dev)
{
struct pmd_internals *internals = dev->data->dev_private;
memset(&internals->tx_queues[i].stats, 0,
sizeof(struct tx_stats));
}
+
+ return 0;
}
static void
cfg.libbpf_flags = 0;
cfg.xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
cfg.bind_flags = 0;
+
+#if defined(XDP_USE_NEED_WAKEUP)
+ cfg.bind_flags |= XDP_USE_NEED_WAKEUP;
+#endif
+
ret = xsk_socket__create(&rxq->xsk, internals->if_name,
rxq->xsk_queue_idx, rxq->umem->umem, &rxq->rx,
&txq->tx, &cfg);
goto err;
}
+ rxq->fds[0].fd = xsk_socket__fd(rxq->xsk);
+ rxq->fds[0].events = POLLIN;
+
rxq->umem->pmd_zc = internals->pmd_zc;
dev->data->rx_queues[rx_queue_id] = rxq;
return (ret < 0) ? -errno : 0;
}
-static void
+static int
eth_dev_change_flags(char *if_name, uint32_t flags, uint32_t mask)
{
struct ifreq ifr;
+ int ret = 0;
int s;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
- return;
+ return -errno;
strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
- if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+ ret = -errno;
goto out;
+ }
ifr.ifr_flags &= mask;
ifr.ifr_flags |= flags;
- if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
+ if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+ ret = -errno;
goto out;
+ }
out:
close(s);
+ return ret;
}
-static void
+static int
eth_dev_promiscuous_enable(struct rte_eth_dev *dev)
{
struct pmd_internals *internals = dev->data->dev_private;
- eth_dev_change_flags(internals->if_name, IFF_PROMISC, ~0);
+ return eth_dev_change_flags(internals->if_name, IFF_PROMISC, ~0);
}
-static void
+static int
eth_dev_promiscuous_disable(struct rte_eth_dev *dev)
{
struct pmd_internals *internals = dev->data->dev_private;
- eth_dev_change_flags(internals->if_name, 0, ~IFF_PROMISC);
+ return eth_dev_change_flags(internals->if_name, 0, ~IFF_PROMISC);
}
static const struct eth_dev_ops ops = {
ifr.ifr_data = (void *)&channels;
strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
ret = ioctl(fd, SIOCETHTOOL, &ifr);
- if (ret && errno != EOPNOTSUPP) {
- ret = -errno;
- goto out;
+ if (ret) {
+ if (errno == EOPNOTSUPP) {
+ ret = 0;
+ } else {
+ ret = -errno;
+ goto out;
+ }
}
if (channels.max_combined == 0 || errno == EOPNOTSUPP) {