/* Size of buffers used for snprintfs. */
#define MAX_PRINT_BUFF 6072
-/* Maximum character device basename size. */
-#define MAX_BASENAME_SZ 10
-
/* Maximum long option length for option parsing. */
#define MAX_LONG_OPT_SZ 64
/* Disable TSO offload */
static uint32_t enable_tso;
+static int client_mode;
+
/* Specify timeout (in useconds) between retries on RX. */
static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
/* Specify the number of retries on RX. */
static uint32_t burst_rx_retry_num = BURST_RX_RETRIES;
-/* Character device basename. Can be set by user. */
-static char dev_basename[MAX_BASENAME_SZ] = "vhost-net";
+/* Socket file path. Can be set by user */
+static char socket_file[PATH_MAX] = "vhost-net";
/* empty vmdq configuration structure. Filled in programatically */
static struct rte_eth_conf vmdq_conf_default = {
if (enable_tso == 0) {
rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
+ rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
+ rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
}
rx_rings = (uint16_t)dev_info.max_rx_queues;
/* Configure ethernet device. */
retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
- if (retval != 0)
+ if (retval != 0) {
+ RTE_LOG(ERR, VHOST_PORT, "Failed to configure port %u: %s.\n",
+ port, strerror(-retval));
return retval;
+ }
/* Setup the queues. */
for (q = 0; q < rx_rings; q ++) {
rte_eth_dev_socket_id(port),
rxconf,
mbuf_pool);
- if (retval < 0)
+ if (retval < 0) {
+ RTE_LOG(ERR, VHOST_PORT,
+ "Failed to setup rx queue %u of port %u: %s.\n",
+ q, port, strerror(-retval));
return retval;
+ }
}
for (q = 0; q < tx_rings; q ++) {
retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
rte_eth_dev_socket_id(port),
txconf);
- if (retval < 0)
+ if (retval < 0) {
+ RTE_LOG(ERR, VHOST_PORT,
+ "Failed to setup tx queue %u of port %u: %s.\n",
+ q, port, strerror(-retval));
return retval;
+ }
}
/* Start the device. */
retval = rte_eth_dev_start(port);
if (retval < 0) {
- RTE_LOG(ERR, VHOST_DATA, "Failed to start the device.\n");
+ RTE_LOG(ERR, VHOST_PORT, "Failed to start port %u: %s\n",
+ port, strerror(-retval));
return retval;
}
}
/*
- * Set character device basename.
+ * Set socket file path.
*/
static int
-us_vhost_parse_basename(const char *q_arg)
+us_vhost_parse_socket_path(const char *q_arg)
{
/* parse number string */
- if (strnlen(q_arg, MAX_BASENAME_SZ) > MAX_BASENAME_SZ)
+ if (strnlen(q_arg, PATH_MAX) > PATH_MAX)
return -1;
else
- snprintf((char*)&dev_basename, MAX_BASENAME_SZ, "%s", q_arg);
+ snprintf((char *)&socket_file, PATH_MAX, "%s", q_arg);
return 0;
}
RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK\n"
" --vm2vm [0|1|2]\n"
" --rx_retry [0|1] --mergeable [0|1] --stats [0-N]\n"
- " --dev-basename <name>\n"
+ " --socket-file <path>\n"
" --nb-devices ND\n"
" -p PORTMASK: Set mask for ports to be used by application\n"
" --vm2vm [0|1|2]: disable/software(default)/hardware vm2vm comms\n"
" --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n"
" --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n"
" --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n"
- " --dev-basename: The basename to be used for the character device.\n"
+ " --socket-file: The path of the socket file.\n"
" --tx-csum [0|1] disable/enable TX checksum offload.\n"
- " --tso [0|1] disable/enable TCP segment offload.\n",
+ " --tso [0|1] disable/enable TCP segment offload.\n"
+ " --client register a vhost-user socket as client mode.\n",
prgname);
}
{"mergeable", required_argument, NULL, 0},
{"vlan-strip", required_argument, NULL, 0},
{"stats", required_argument, NULL, 0},
- {"dev-basename", required_argument, NULL, 0},
+ {"socket-file", required_argument, NULL, 0},
{"tx-csum", required_argument, NULL, 0},
{"tso", required_argument, NULL, 0},
+ {"client", no_argument, &client_mode, 1},
{NULL, 0, 0, 0},
};
if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) {
ret = parse_num_opt(optarg, INT32_MAX);
if (ret == -1) {
- RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n");
+ RTE_LOG(INFO, VHOST_CONFIG,
+ "Invalid argument for stats [0..N]\n");
us_vhost_usage(prgname);
return -1;
} else {
}
}
- /* Set character device basename. */
- if (!strncmp(long_option[option_index].name, "dev-basename", MAX_LONG_OPT_SZ)) {
- if (us_vhost_parse_basename(optarg) == -1) {
- RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for character device basename (Max %d characters)\n", MAX_BASENAME_SZ);
+ /* Set socket file path. */
+ if (!strncmp(long_option[option_index].name,
+ "socket-file", MAX_LONG_OPT_SZ)) {
+ if (us_vhost_parse_socket_path(optarg) == -1) {
+ RTE_LOG(INFO, VHOST_CONFIG,
+ "Invalid argument for socket name (Max %d characters)\n",
+ PATH_MAX);
us_vhost_usage(prgname);
return -1;
}
if (find_vhost_dev(&pkt_hdr->s_addr)) {
RTE_LOG(ERR, VHOST_DATA,
"(%d) device is using a registered MAC!\n",
- vdev->device_fh);
+ vdev->vid);
return -1;
}
vdev->mac_address.addr_bytes[i] = pkt_hdr->s_addr.addr_bytes[i];
/* vlan_tag currently uses the device_id. */
- vdev->vlan_tag = vlan_tags[vdev->device_fh];
+ vdev->vlan_tag = vlan_tags[vdev->vid];
/* Print out VMDQ registration info. */
RTE_LOG(INFO, VHOST_DATA,
"(%d) mac %02x:%02x:%02x:%02x:%02x:%02x and vlan %d registered\n",
- vdev->device_fh,
+ vdev->vid,
vdev->mac_address.addr_bytes[0], vdev->mac_address.addr_bytes[1],
vdev->mac_address.addr_bytes[2], vdev->mac_address.addr_bytes[3],
vdev->mac_address.addr_bytes[4], vdev->mac_address.addr_bytes[5],
/* Register the MAC address. */
ret = rte_eth_dev_mac_addr_add(ports[0], &vdev->mac_address,
- (uint32_t)vdev->device_fh + vmdq_pool_base);
+ (uint32_t)vdev->vid + vmdq_pool_base);
if (ret)
RTE_LOG(ERR, VHOST_DATA,
"(%d) failed to add device MAC address to VMDQ\n",
- vdev->device_fh);
+ vdev->vid);
/* Enable stripping of the vlan tag as we handle routing. */
if (vlan_strip)
{
uint16_t ret;
- ret = rte_vhost_enqueue_burst(dst_vdev->dev, VIRTIO_RXQ, &m, 1);
+ ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
if (enable_stats) {
rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
if (!dst_vdev)
return -1;
- if (vdev->device_fh == dst_vdev->device_fh) {
+ if (vdev->vid == dst_vdev->vid) {
RTE_LOG(DEBUG, VHOST_DATA,
"(%d) TX: src and dst MAC is same. Dropping packet.\n",
- vdev->device_fh);
+ vdev->vid);
return 0;
}
RTE_LOG(DEBUG, VHOST_DATA,
- "(%d) TX: MAC address is local\n", dst_vdev->device_fh);
+ "(%d) TX: MAC address is local\n", dst_vdev->vid);
if (unlikely(dst_vdev->remove)) {
RTE_LOG(DEBUG, VHOST_DATA,
- "(%d) device is marked for removal\n", dst_vdev->device_fh);
+ "(%d) device is marked for removal\n", dst_vdev->vid);
return 0;
}
if (!dst_vdev)
return 0;
- if (vdev->device_fh == dst_vdev->device_fh) {
+ if (vdev->vid == dst_vdev->vid) {
RTE_LOG(DEBUG, VHOST_DATA,
"(%d) TX: src and dst MAC is same. Dropping packet.\n",
- vdev->device_fh);
+ vdev->vid);
return -1;
}
* the packet length by plus it.
*/
*offset = VLAN_HLEN;
- *vlan_tag = vlan_tags[vdev->device_fh];
+ *vlan_tag = vlan_tags[vdev->vid];
RTE_LOG(DEBUG, VHOST_DATA,
"(%d) TX: pkt to local VM device id: (%d), vlan tag: %u.\n",
- vdev->device_fh, dst_vdev->device_fh, *vlan_tag);
+ vdev->vid, dst_vdev->vid, *vlan_tag);
return 0;
}
}
RTE_LOG(DEBUG, VHOST_DATA,
- "(%d) TX: MAC address is external\n", vdev->device_fh);
+ "(%d) TX: MAC address is external\n", vdev->vid);
queue2nic:
drain_eth_rx(struct vhost_dev *vdev)
{
uint16_t rx_count, enqueue_count;
- struct virtio_net *dev = vdev->dev;
struct rte_mbuf *pkts[MAX_PKT_BURST];
rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q,
* to diminish packet loss.
*/
if (enable_retry &&
- unlikely(rx_count > rte_vring_available_entries(dev,
+ unlikely(rx_count > rte_vhost_avail_entries(vdev->vid,
VIRTIO_RXQ))) {
uint32_t retry;
for (retry = 0; retry < burst_rx_retry_num; retry++) {
rte_delay_us(burst_rx_delay_time);
- if (rx_count <= rte_vring_available_entries(dev,
+ if (rx_count <= rte_vhost_avail_entries(vdev->vid,
VIRTIO_RXQ))
break;
}
}
- enqueue_count = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ,
+ enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
pkts, rx_count);
if (enable_stats) {
rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
uint16_t count;
uint16_t i;
- count = rte_vhost_dequeue_burst(vdev->dev, VIRTIO_TXQ, mbuf_pool,
+ count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
pkts, MAX_PKT_BURST);
/* setup VMDq for the first packet */
}
for (i = 0; i < count; ++i)
- virtio_tx_route(vdev, pkts[i], vlan_tags[vdev->device_fh]);
+ virtio_tx_route(vdev, pkts[i], vlan_tags[vdev->vid]);
}
/*
* of dev->remove=1 which can cause an infinite loop in the rte_pause loop.
*/
static void
-destroy_device (volatile struct virtio_net *dev)
+destroy_device(int vid)
{
- struct vhost_dev *vdev;
+ struct vhost_dev *vdev = NULL;
int lcore;
- vdev = (struct vhost_dev *)dev->priv;
+ TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
+ if (vdev->vid == vid)
+ break;
+ }
+ if (!vdev)
+ return;
/*set the remove flag. */
vdev->remove = 1;
while(vdev->ready != DEVICE_SAFE_REMOVE) {
RTE_LOG(INFO, VHOST_DATA,
"(%d) device has been removed from data core\n",
- vdev->device_fh);
+ vdev->vid);
rte_free(vdev);
}
* and the allocated to a specific data core.
*/
static int
-new_device (struct virtio_net *dev)
+new_device(int vid)
{
int lcore, core_add = 0;
uint32_t device_num_min = num_devices;
struct vhost_dev *vdev;
- int device_fh = dev->device_fh;
vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE);
if (vdev == NULL) {
RTE_LOG(INFO, VHOST_DATA,
"(%d) couldn't allocate memory for vhost dev\n",
- device_fh);
+ vid);
return -1;
}
- vdev->dev = dev;
- dev->priv = vdev;
- vdev->device_fh = device_fh;
+ vdev->vid = vid;
TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
- vdev->vmdq_rx_q = device_fh * queues_per_pool + vmdq_queue_base;
+ vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
/*reset ready flag*/
vdev->ready = DEVICE_MAC_LEARNING;
lcore_info[vdev->coreid].device_num++;
/* Disable notifications. */
- rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0);
- rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_RXQ, 0);
+ rte_vhost_enable_guest_notification(vid, VIRTIO_TXQ, 0);
RTE_LOG(INFO, VHOST_DATA,
"(%d) device has been added to data core %d\n",
- device_fh, vdev->coreid);
+ vid, vdev->coreid);
return 0;
}
"RX total: %" PRIu64 "\n"
"RX dropped: %" PRIu64 "\n"
"RX successful: %" PRIu64 "\n",
- vdev->dev->device_fh,
+ vdev->vid,
tx_total, tx_dropped, tx,
rx_total, rx_dropped, rx);
}
sigint_handler(__rte_unused int signum)
{
/* Unregister vhost driver. */
- int ret = rte_vhost_driver_unregister((char *)&dev_basename);
+ int ret = rte_vhost_driver_unregister((char *)&socket_file);
if (ret != 0)
rte_exit(EXIT_FAILURE, "vhost driver unregister failure.\n");
exit(0);
uint8_t portid;
static pthread_t tid;
char thread_name[RTE_MAX_THREAD_NAME_LEN];
+ uint64_t flags = 0;
signal(SIGINT, sigint_handler);
if (mergeable == 0)
rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
- /* Register vhost(cuse or user) driver to handle vhost messages. */
- ret = rte_vhost_driver_register((char *)&dev_basename);
+ if (client_mode)
+ flags |= RTE_VHOST_USER_CLIENT;
+
+ /* Register vhost user driver to handle vhost messages. */
+ ret = rte_vhost_driver_register(socket_file, flags);
if (ret != 0)
rte_exit(EXIT_FAILURE, "vhost driver register failure.\n");