#include <rte_ethdev_vdev.h>
#include <rte_bus_vdev.h>
#include <rte_alarm.h>
+#include <rte_cycles.h>
#include "virtio_ethdev.h"
#include "virtio_logs.h"
#define virtio_user_get_dev(hw) \
((struct virtio_user_dev *)(hw)->virtio_user_dev)
+static void
+virtio_user_reset_queues_packed(struct rte_eth_dev *dev)
+{
+ struct virtio_hw *hw = dev->data->dev_private;
+ struct virtnet_rx *rxvq;
+ struct virtnet_tx *txvq;
+ uint16_t i;
+
+ /* Add lock to avoid queue contention. */
+ rte_spinlock_lock(&hw->state_lock);
+ hw->started = 0;
+
+ /*
+ * Waitting for datapath to complete before resetting queues.
+ * 1 ms should be enough for the ongoing Tx/Rx function to finish.
+ */
+ rte_delay_ms(1);
+
+ /* Vring reset for each Tx queue and Rx queue. */
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxvq = dev->data->rx_queues[i];
+ virtqueue_rxvq_reset_packed(rxvq->vq);
+ virtio_dev_rx_queue_setup_finish(dev, i);
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ txvq = dev->data->tx_queues[i];
+ virtqueue_txvq_reset_packed(txvq->vq);
+ }
+
+ hw->started = 1;
+ rte_spinlock_unlock(&hw->state_lock);
+}
+
+
static int
virtio_user_server_reconnect(struct virtio_user_dev *dev)
{
int ret;
int connectfd;
struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
+ struct virtio_hw *hw = eth_dev->data->dev_private;
connectfd = accept(dev->listenfd, NULL, NULL);
if (connectfd < 0)
dev->features &= dev->device_features;
+ /* For packed ring, resetting queues is required in reconnection. */
+ if (vtpci_packed_queue(hw)) {
+ PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped"
+ " when packed ring reconnecting.");
+ virtio_user_reset_queues_packed(eth_dev);
+ }
+
ret = virtio_user_start_device(dev);
if (ret < 0)
return -1;
VIRTIO_USER_ARG_IN_ORDER,
#define VIRTIO_USER_ARG_PACKED_VQ "packed_vq"
VIRTIO_USER_ARG_PACKED_VQ,
+#define VIRTIO_USER_ARG_SPEED "speed"
+ VIRTIO_USER_ARG_SPEED,
NULL
};
get_integer_arg(const char *key __rte_unused,
const char *value, void *extra_args)
{
+ uint64_t integer = 0;
if (!value || !extra_args)
return -EINVAL;
-
- *(uint64_t *)extra_args = strtoull(value, NULL, 0);
-
- return 0;
+ errno = 0;
+ integer = strtoull(value, NULL, 0);
+ /* extra_args keeps default value, it should be replaced
+ * only in case of successful parsing of the 'value' arg
+ */
+ if (errno == 0)
+ *(uint64_t *)extra_args = integer;
+ return -errno;
}
static struct rte_eth_dev *
*/
hw->use_msix = 1;
hw->modern = 0;
- hw->use_simple_rx = 0;
+ hw->use_vec_rx = 0;
hw->use_inorder_rx = 0;
hw->use_inorder_tx = 0;
hw->virtio_user_dev = dev;
const char *name = rte_vdev_device_name(dev);
eth_dev = rte_eth_dev_attach_secondary(name);
if (!eth_dev) {
- RTE_LOG(ERR, PMD, "Failed to probe %s\n", name);
+ PMD_INIT_LOG(ERR, "Failed to probe %s", name);
return -1;
}
"server=<0|1> "
"mrg_rxbuf=<0|1> "
"in_order=<0|1> "
- "packed_vq=<0|1>");
+ "packed_vq=<0|1> "
+ "speed=<int>");