diff options
author | Jan Scheurich <jan.scheurich@ericsson.com> | 2018-04-19 19:40:44 +0200 |
---|---|---|
committer | Ian Stokes <ian.stokes@intel.com> | 2018-05-11 08:08:24 +0100 |
commit | 8492adc270fd9b1774683064764cdf56df995b99 (patch) | |
tree | 903ac545e94ff87e3457b9953b9473e70a60a77c | |
parent | 65a87968f4cfd9cf7a433a3156d98118078f9e4e (diff) | |
download | openvswitch-8492adc270fd9b1774683064764cdf56df995b99.tar.gz |
netdev: Add optional qfill output parameter to rxq_recv()
If the caller provides a non-NULL qfill pointer and the netdev
implemementation supports reading the rx queue fill level, the rxq_recv()
function returns the remaining number of packets in the rx queue after
reception of the packet burst to the caller. If the implementation does
not support this, it returns -ENOTSUP instead. Reading the remaining queue
fill level should not substantilly slow down the recv() operation.
A first implementation is provided for ethernet and vhostuser DPDK ports
in netdev-dpdk.c.
This output parameter will be used in the upcoming commit for PMD
performance metrics to supervise the rx queue fill level for DPDK
vhostuser ports.
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Acked-by: Billy O'Mahony <billy.o.mahony@intel.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
-rw-r--r-- | lib/dpif-netdev.c | 2 | ||||
-rw-r--r-- | lib/netdev-bsd.c | 8 | ||||
-rw-r--r-- | lib/netdev-dpdk.c | 41 | ||||
-rw-r--r-- | lib/netdev-dummy.c | 8 | ||||
-rw-r--r-- | lib/netdev-linux.c | 7 | ||||
-rw-r--r-- | lib/netdev-provider.h | 8 | ||||
-rw-r--r-- | lib/netdev.c | 5 | ||||
-rw-r--r-- | lib/netdev.h | 3 |
8 files changed, 69 insertions, 13 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index be31fd092..7ce394354 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -3277,7 +3277,7 @@ dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd, pmd->ctx.last_rxq = rxq; dp_packet_batch_init(&batch); - error = netdev_rxq_recv(rxq->rx, &batch); + error = netdev_rxq_recv(rxq->rx, &batch, NULL); if (!error) { /* At least one packet received. */ *recirc_depth_get() = 0; diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c index 05974c100..b70f327e4 100644 --- a/lib/netdev-bsd.c +++ b/lib/netdev-bsd.c @@ -618,7 +618,8 @@ netdev_rxq_bsd_recv_tap(struct netdev_rxq_bsd *rxq, struct dp_packet *buffer) } static int -netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) +netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch, + int *qfill) { struct netdev_rxq_bsd *rxq = netdev_rxq_bsd_cast(rxq_); struct netdev *netdev = rxq->up.netdev; @@ -643,6 +644,11 @@ netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) batch->packets[0] = packet; batch->count = 1; } + + if (qfill) { + *qfill = -ENOTSUP; + } + return retval; } diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index b16bf20d6..c9ef4886e 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -1896,13 +1896,13 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats, */ static int netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq, - struct dp_packet_batch *batch) + struct dp_packet_batch *batch, int *qfill) { struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev); struct ingress_policer *policer = netdev_dpdk_get_ingress_policer(dev); uint16_t nb_rx = 0; uint16_t dropped = 0; - int qid = rxq->queue_id; + int qid = rxq->queue_id * VIRTIO_QNUM + VIRTIO_TXQ; int vid = netdev_dpdk_get_vid(dev); if (OVS_UNLIKELY(vid < 0 || !dev->vhost_reconfigured @@ -1910,14 +1910,23 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq, return EAGAIN; } - nb_rx = rte_vhost_dequeue_burst(vid, qid * VIRTIO_QNUM + VIRTIO_TXQ, - dev->mp, + nb_rx = rte_vhost_dequeue_burst(vid, qid, dev->mp, (struct rte_mbuf **) batch->packets, NETDEV_MAX_BURST); if (!nb_rx) { return EAGAIN; } + if (qfill) { + if (nb_rx == NETDEV_MAX_BURST) { + /* The DPDK API returns a uint32_t which often has invalid bits in + * the upper 16-bits. Need to restrict the value to uint16_t. */ + *qfill = rte_vhost_rx_queue_count(vid, qid) & UINT16_MAX; + } else { + *qfill = 0; + } + } + if (policer) { dropped = nb_rx; nb_rx = ingress_policer_run(policer, @@ -1938,7 +1947,8 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq, } static int -netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet_batch *batch) +netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet_batch *batch, + int *qfill) { struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq); struct netdev_dpdk *dev = netdev_dpdk_cast(rxq->netdev); @@ -1975,6 +1985,14 @@ netdev_dpdk_rxq_recv(struct netdev_rxq *rxq, struct dp_packet_batch *batch) batch->count = nb_rx; dp_packet_batch_init_packet_fields(batch); + if (qfill) { + if (nb_rx == NETDEV_MAX_BURST) { + *qfill = rte_eth_rx_queue_count(rx->port_id, rxq->queue_id); + } else { + *qfill = 0; + } + } + return 0; } @@ -3256,6 +3274,19 @@ vring_state_changed(int vid, uint16_t queue_id, int enable) return 0; } +/* + * Retrieve the DPDK virtio device ID (vid) associated with a vhostuser + * or vhostuserclient netdev. + * + * Returns a value greater or equal to zero for a valid vid or '-1' if + * there is no valid vid associated. A vid of '-1' must not be used in + * rte_vhost_ APi calls. + * + * Once obtained and validated, a vid can be used by a PMD for multiple + * subsequent rte_vhost API calls until the PMD quiesces. A PMD should + * not fetch the vid again for each of a series of API calls. + */ + int netdev_dpdk_get_vid(const struct netdev_dpdk *dev) { diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 8af9e1a03..13bc580db 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -992,7 +992,8 @@ netdev_dummy_rxq_dealloc(struct netdev_rxq *rxq_) } static int -netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) +netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch, + int *qfill) { struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_); struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev); @@ -1037,6 +1038,11 @@ netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) batch->packets[0] = packet; batch->count = 1; + + if (qfill) { + *qfill = -ENOTSUP; + } + return 0; } diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index afa4de047..d19bd86ac 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -1196,7 +1196,8 @@ netdev_linux_rxq_recv_tap(int fd, struct dp_packet *buffer) } static int -netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) +netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch, + int *qfill) { struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_); struct netdev *netdev = rx->up.netdev; @@ -1225,6 +1226,10 @@ netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch) dp_packet_batch_init_packet(batch, buffer); } + if (qfill) { + *qfill = -ENOTSUP; + } + return retval; } diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h index 25bd671c1..6e8ae4f42 100644 --- a/lib/netdev-provider.h +++ b/lib/netdev-provider.h @@ -789,9 +789,15 @@ struct netdev_class { * Implementations should allocate buffers with DP_NETDEV_HEADROOM bytes of * headroom. * + * If the caller provides a non-NULL qfill pointer, the implementation + * should return the number (zero or more) of remaining packets in the + * queue after the reception the current batch, if it supports that, + * or -ENOTSUP otherwise. + * * Returns EAGAIN immediately if no packet is ready to be received or * another positive errno value if an error was encountered. */ - int (*rxq_recv)(struct netdev_rxq *rx, struct dp_packet_batch *batch); + int (*rxq_recv)(struct netdev_rxq *rx, struct dp_packet_batch *batch, + int *qfill); /* Registers with the poll loop to wake up from the next call to * poll_block() when a packet is ready to be received with diff --git a/lib/netdev.c b/lib/netdev.c index 8f0900445..a1ac1b5b2 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -696,11 +696,12 @@ netdev_rxq_close(struct netdev_rxq *rx) * Returns EAGAIN immediately if no packet is ready to be received or another * positive errno value if an error was encountered. */ int -netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch) +netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch, + int *qfill) { int retval; - retval = rx->netdev->netdev_class->rxq_recv(rx, batch); + retval = rx->netdev->netdev_class->rxq_recv(rx, batch, qfill); if (!retval) { COVERAGE_INC(netdev_received); } else { diff --git a/lib/netdev.h b/lib/netdev.h index 441e53dae..bd6f45abb 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -175,7 +175,8 @@ void netdev_rxq_close(struct netdev_rxq *); const char *netdev_rxq_get_name(const struct netdev_rxq *); int netdev_rxq_get_queue_id(const struct netdev_rxq *); -int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *); +int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *, + int *qfill); void netdev_rxq_wait(struct netdev_rxq *); int netdev_rxq_drain(struct netdev_rxq *); |