summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Scheurich <jan.scheurich@ericsson.com>2018-04-19 19:40:44 +0200
committerIan Stokes <ian.stokes@intel.com>2018-05-11 08:08:24 +0100
commit8492adc270fd9b1774683064764cdf56df995b99 (patch)
tree903ac545e94ff87e3457b9953b9473e70a60a77c
parent65a87968f4cfd9cf7a433a3156d98118078f9e4e (diff)
downloadopenvswitch-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.c2
-rw-r--r--lib/netdev-bsd.c8
-rw-r--r--lib/netdev-dpdk.c41
-rw-r--r--lib/netdev-dummy.c8
-rw-r--r--lib/netdev-linux.c7
-rw-r--r--lib/netdev-provider.h8
-rw-r--r--lib/netdev.c5
-rw-r--r--lib/netdev.h3
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 *);