#endif
};
+#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
+static int dpdk_vhost_user_set_vring_enable(u32 hw_if_index,
+ u8 idx, int enable);
+#endif
+
/*
* DPDK vhost-user functions
*/
}
static clib_error_t *
-dpdk_create_vhost_user_if_internal (u32 * hw_if_index, u32 if_id)
+dpdk_create_vhost_user_if_internal (u32 * hw_if_index, u32 if_id, u8 *hwaddr)
{
dpdk_main_t * dm = &dpdk_main;
vlib_main_t * vm = vlib_get_main();
clib_error_t * error;
dpdk_device_and_queue_t * dq;
int num_qpairs = 1;
+ dpdk_vu_intf_t *vui = NULL;
#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
- num_qpairs = dm->use_rss < 1 ? 1 : dm->use_rss;
+ num_qpairs = dm->use_rss < 1 ? 1 : tm->n_vlib_mains;
#endif
dpdk_device_t * xd = NULL;
xd->vu_if_id = if_id;
// reset virtqueues
+ vui = xd->vu_intf;
for (j = 0; j < num_qpairs * VIRTIO_QNUM; j++) {
memset(xd->vu_vhost_dev.virtqueue[j], 0, sizeof(struct vhost_virtqueue));
xd->vu_vhost_dev.virtqueue[j]->kickfd = -1;
xd->vu_vhost_dev.virtqueue[j]->callfd = -1;
xd->vu_vhost_dev.virtqueue[j]->backend = -1;
+ vui->vrings[j].packets = 0;
+ vui->vrings[j].bytes = 0;
}
// reset lockp
- if (xd->lockp)
- memset ((void *) xd->lockp, 0, CLIB_CACHE_LINE_BYTES);
+ dpdk_device_lock_free(xd);
+ dpdk_device_lock_init(xd);
// reset tx vectors
for (j = 0; j < tm->n_vlib_mains; j++)
xd->device_index = xd - dm->devices;
xd->per_interface_next_index = ~0;
- xd->vu_intf = NULL;
+ xd->vu_intf = clib_mem_alloc (sizeof(*(xd->vu_intf)));
xd->vu_vhost_dev.mem = clib_mem_alloc (sizeof(struct virtio_memory) +
VHOST_MEMORY_MAX_NREGIONS *
* New virtqueue structure is an array of VHOST_MAX_QUEUE_PAIRS * 2
* We need to allocate numq pairs.
*/
+ vui = xd->vu_intf;
for (j = 0; j < num_qpairs * VIRTIO_QNUM; j++) {
xd->vu_vhost_dev.virtqueue[j] = clib_mem_alloc (sizeof(struct vhost_virtqueue));
memset(xd->vu_vhost_dev.virtqueue[j], 0, sizeof(struct vhost_virtqueue));
xd->vu_vhost_dev.virtqueue[j]->kickfd = -1;
xd->vu_vhost_dev.virtqueue[j]->callfd = -1;
xd->vu_vhost_dev.virtqueue[j]->backend = -1;
+ vui->vrings[j].packets = 0;
+ vui->vrings[j].bytes = 0;
}
- xd->lockp = NULL;
- if (xd->tx_q_used < dm->input_cpu_count) {
- xd->lockp = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
- CLIB_CACHE_LINE_BYTES);
- memset ((void *) xd->lockp, 0, CLIB_CACHE_LINE_BYTES);
- }
+ dpdk_device_lock_init(xd);
DBG_SOCK("tm->n_vlib_mains: %d. TX %d, RX: %d, num_qpairs: %d, Lock: %p",
tm->n_vlib_mains, xd->tx_q_used, xd->rx_q_used, num_qpairs, xd->lockp);
/*
* Generate random MAC address for the interface
*/
+ if (hwaddr) {
+ memcpy(addr, hwaddr, sizeof(addr));
+ } else {
f64 now = vlib_time_now(vm);
u32 rnd;
rnd = (u32) (now * 1e6);
memcpy (addr+2, &rnd, sizeof(rnd));
addr[0] = 2;
addr[1] = 0xfe;
+ }
error = ethernet_register_interface
(dm->vnet_main,
sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->vlib_hw_if_index);
xd->vlib_sw_if_index = sw->sw_if_index;
- if (!xd->vu_intf)
- xd->vu_intf = clib_mem_alloc (sizeof(*(xd->vu_intf)));
-
*hw_if_index = xd->vlib_hw_if_index;
DBG_SOCK("xd->device_index: %d, dm->input_cpu_count: %d, "
int numqs = VIRTIO_QNUM;
u8 idx;
#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
+ int prot_feature = features &
+ (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
#endif
- for (idx = 0; idx < numqs; idx++)
+ for (idx = 0; idx < numqs; idx++) {
xd->vu_vhost_dev.virtqueue[idx]->vhost_hlen = hdr_len;
+#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
+ /*
+ * Spec says, if F_PROTOCOL_FEATURE is not set by the
+ * slave, then all the vrings should start off as
+ * enabled. If slave negotiates F_PROTOCOL_FEATURE, then
+ * slave is responsible to enable it.
+ */
+ if (! prot_feature)
+ dpdk_vhost_user_set_vring_enable(hw_if_index, idx, 1);
+#endif
+ }
return 0;
}
mem->regions[i].userspace_address = vum->regions[i].userspace_addr;
mapped_size = mem->regions[i].memory_size + vum->regions[i].mmap_offset;
- mapped_address = (uint64_t)(uintptr_t)mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0);
+ mapped_address = pointer_to_uword(mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0));
- if ((void *)mapped_address == MAP_FAILED)
+ if (uword_to_pointer(mapped_address, void*) == MAP_FAILED)
{
clib_warning("mmap error");
return 0;
* on the descriptor specified by VHOST_USER_SET_VRING_KICK,
* and stop ring upon receiving VHOST_USER_GET_VRING_BASE.
*/
- dpdk_vu_intf_t *vui = xd->vu_intf;
DBG_SOCK("Stopping vring Q %u of device %d", idx, hw_if_index);
#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
+ dpdk_vu_intf_t *vui = xd->vu_intf;
vui->vrings[idx].enabled = 0; /* Reset local copy */
vui->vrings[idx].callfd = -1; /* Reset FD */
vq->enabled = 0;
{
dpdk_main_t * dm = &dpdk_main;
dpdk_device_t * xd;
+#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
dpdk_vu_vring *vring;
+#endif
struct vhost_virtqueue *vq0, *vq1, *vq;
int index, vu_is_running = 0;
return 0;
}
- vring = &xd->vu_intf->vrings[idx];
vq = xd->vu_vhost_dev.virtqueue[idx];
vq->kickfd = fd;
#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
+ vring = &xd->vu_intf->vrings[idx];
vq->enabled = (vq->desc && vq->avail && vq->used && vring->enabled) ? 1 : 0;
#endif
}
#if RTE_VERSION >= RTE_VERSION_NUM(2, 2, 0, 0)
-int dpdk_vhost_user_set_vring_enable(u32 hw_if_index, u8 idx, int enable)
+static int
+dpdk_vhost_user_set_vring_enable(u32 hw_if_index, u8 idx, int enable)
{
dpdk_device_t * xd;
struct vhost_virtqueue *vq;
*/
vui->vrings[idx].enabled = enable; /* Save local copy */
+ int numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
+ while (numqs--) {
+ if (! vui->vrings[numqs].enabled)
+ break;
+ }
+
+ if (numqs == -1) /* All Qs are enabled */
+ xd->need_txlock = 0;
+ else
+ xd->need_txlock = 1;
+
vq = xd->vu_vhost_dev.virtqueue[idx];
if (vq->desc && vq->avail && vq->used)
xd->vu_vhost_dev.virtqueue[idx]->enabled = enable;
u8 is_server,
u32 * sw_if_index,
u64 feature_mask,
- u8 renumber, u32 custom_dev_instance)
+ u8 renumber, u32 custom_dev_instance,
+ u8 *hwaddr)
{
dpdk_main_t * dm = &dpdk_main;
dpdk_device_t *xd;
// using virtio vhost user?
if (dm->use_virtio_vhost) {
return vhost_user_create_if(vnm, vm, sock_filename, is_server,
- sw_if_index, feature_mask, renumber, custom_dev_instance);
+ sw_if_index, feature_mask, renumber, custom_dev_instance, hwaddr);
}
if (is_server) {
if (custom_dev_instance >= dm->next_vu_if_id)
dm->next_vu_if_id = custom_dev_instance + 1;
- dpdk_create_vhost_user_if_internal(&hw_if_idx, custom_dev_instance);
+ dpdk_create_vhost_user_if_internal(&hw_if_idx, custom_dev_instance, hwaddr);
} else
- dpdk_create_vhost_user_if_internal(&hw_if_idx, (u32)~0);
+ dpdk_create_vhost_user_if_internal(&hw_if_idx, (u32)~0, hwaddr);
DBG_SOCK("dpdk vhost-user interface created hw_if_index %d", hw_if_idx);
xd = dpdk_vhost_user_device_from_hw_if_index(hw_if_idx);
u64 feature_mask = (u64)~0;
u8 renumber = 0;
u32 custom_dev_instance = ~0;
+ u8 hwaddr[6];
+ u8 *hw = NULL;
if (dm->use_virtio_vhost) {
return vhost_user_connect_command_fn(vm, input, cmd);
is_server = 1;
else if (unformat (line_input, "feature-mask 0x%llx", &feature_mask))
;
+ else if (unformat (line_input, "hwaddr %U", unformat_ethernet_address, hwaddr))
+ hw = hwaddr;
else if (unformat (line_input, "renumber %d", &custom_dev_instance)) {
renumber = 1;
}
dpdk_vhost_user_create_if(vnm, vm, (char *)sock_filename,
is_server, &sw_if_index, feature_mask,
- renumber, custom_dev_instance);
+ renumber, custom_dev_instance, hw);
vec_free(sock_filename);
return 0;
.short_help = "show vhost-user interface",
.function = show_dpdk_vhost_user_command_fn,
};
-