16 #include <sys/socket.h> 34 #define VHOST_USER_DEBUG_SOCKET 0 36 #if VHOST_USER_DEBUG_SOCKET == 1 37 #define DBG_SOCK(args...) clib_warning(args); 39 #define DBG_SOCK(args...) 45 static const char *vhost_message_str[] __attribute__ ((unused)) =
69 static int dpdk_vhost_user_set_vring_enable (
u32 hw_if_index,
111 qva_to_vva (
struct virtio_net *dev,
uword qemu_va)
113 struct virtio_memory_regions *region;
118 for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++)
120 region = &dev->mem->regions[regionidx];
121 if ((qemu_va >= region->userspace_address) &&
122 (qemu_va <= region->userspace_address + region->memory_size))
124 vhost_va = qemu_va + region->guest_phys_address +
125 region->address_offset - region->userspace_address;
133 dpdk_vhost_user_device_from_hw_if_index (
u32 hw_if_index)
147 dpdk_vhost_user_device_from_sw_if_index (
u32 sw_if_index)
153 return dpdk_vhost_user_device_from_hw_if_index (sw->
hw_if_index);
157 stop_processing_packets (
u32 hw_if_index,
u8 idx)
159 dpdk_device_t *xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index);
161 xd->vu_vhost_dev.virtqueue[idx]->enabled = 0;
168 int numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
169 for (idx = 0; idx < numqs; idx++)
170 xd->vu_vhost_dev.virtqueue[idx]->enabled = 0;
172 xd->vu_is_running = 0;
178 dpdk_vu_intf_t *vui = xd->vu_intf;
179 struct virtio_memory *mem = xd->vu_vhost_dev.mem;
181 for (i = 0; i < mem->nregions; i++)
183 if ((mem->regions[i].guest_phys_address <= addr) &&
184 ((mem->regions[i].guest_phys_address +
185 mem->regions[i].memory_size) > addr))
187 return (
void *) ((
uword) vui->region_addr[i] + addr -
188 (
uword) mem->regions[
i].guest_phys_address);
191 DBG_SOCK (
"failed to map guest mem addr %lx", addr);
196 dpdk_create_vhost_user_if_internal (
u32 * hw_if_index,
u32 if_id,
u8 * hwaddr)
205 dpdk_vu_intf_t *vui =
NULL;
217 if (inactive_cnt > 0)
227 (
"reusing inactive vhost-user interface sw_if_index %d",
233 (
"error: inactive vhost-user interface sw_if_index %d not VHOST_USER type!",
246 if (if_id != (
u32) ~ 0)
247 xd->vu_if_id = if_id;
251 for (j = 0; j < num_qpairs * VIRTIO_QNUM; j++)
253 memset (xd->vu_vhost_dev.virtqueue[j], 0,
254 sizeof (
struct vhost_virtqueue));
255 xd->vu_vhost_dev.virtqueue[j]->kickfd = -1;
256 xd->vu_vhost_dev.virtqueue[j]->callfd = -1;
257 xd->vu_vhost_dev.virtqueue[j]->backend = -1;
258 vui->vrings[j].packets = 0;
259 vui->vrings[j].bytes = 0;
289 xd->vu_vhost_dev.virt_qp_nb = num_qpairs;
294 if (if_id == (
u32) ~ 0)
297 xd->vu_if_id = if_id;
303 xd->vu_vhost_dev.mem =
clib_mem_alloc (
sizeof (
struct virtio_memory) +
306 virtio_memory_regions));
309 xd->vu_vhost_dev.mem->nregions = 0;
316 for (j = 0; j < num_qpairs * VIRTIO_QNUM; j++)
318 xd->vu_vhost_dev.virtqueue[j] =
320 memset (xd->vu_vhost_dev.virtqueue[j], 0,
321 sizeof (
struct vhost_virtqueue));
322 xd->vu_vhost_dev.virtqueue[j]->kickfd = -1;
323 xd->vu_vhost_dev.virtqueue[j]->callfd = -1;
324 xd->vu_vhost_dev.virtqueue[j]->backend = -1;
325 vui->vrings[j].packets = 0;
326 vui->vrings[j].bytes = 0;
332 (
"tm->n_vlib_mains: %d. TX %d, RX: %d, num_qpairs: %d, Lock: %p",
366 rnd = (
u32) (now * 1e6);
387 DBG_SOCK (
"xd->device_index: %d, dm->input_cpu_count: %d, " 392 for (q = 0; q < num_qpairs; q++)
409 VLIB_NODE_STATE_POLLING);
413 VLIB_NODE_STATE_POLLING);
421 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 432 dpdk_vhost_user_set_protocol_features (
u32 hw_if_index,
u64 prot_features)
435 xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index);
437 xd->vu_vhost_dev.protocol_features = prot_features;
442 dpdk_vhost_user_get_features (
u32 hw_if_index,
u64 * features)
444 *features = rte_vhost_feature_get ();
446 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 447 #define OFFLOAD_FEATURES ((1ULL << VIRTIO_NET_F_HOST_TSO4) | \ 448 (1ULL << VIRTIO_NET_F_HOST_TSO6) | \ 449 (1ULL << VIRTIO_NET_F_CSUM) | \ 450 (1ULL << VIRTIO_NET_F_GUEST_CSUM) | \ 451 (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ 452 (1ULL << VIRTIO_NET_F_GUEST_TSO6)) 458 *features &= (~OFFLOAD_FEATURES);
461 DBG_SOCK (
"supported features: 0x%lx", *features);
466 dpdk_vhost_user_set_features (
u32 hw_if_index,
u64 features)
469 u16 hdr_len =
sizeof (
struct virtio_net_hdr);
472 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
478 xd->vu_vhost_dev.features = features;
480 if (xd->vu_vhost_dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))
481 hdr_len =
sizeof (
struct virtio_net_hdr_mrg_rxbuf);
483 int numqs = VIRTIO_QNUM;
486 numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
487 for (idx = 0; idx < numqs; idx++)
489 xd->vu_vhost_dev.virtqueue[idx]->vhost_hlen = hdr_len;
497 dpdk_vhost_user_set_vring_enable (hw_if_index, idx, 1);
507 struct virtio_memory *mem;
512 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
519 mem = xd->vu_vhost_dev.mem;
523 for (i = 0; i < mem->nregions; i++)
525 u64 mapped_size, mapped_address;
528 mem->regions[
i].guest_phys_address_end =
536 (
NULL, mapped_size, PROT_READ | PROT_WRITE,
537 MAP_SHARED, fd[i], 0));
546 vui->region_addr[
i] = mapped_address;
547 vui->region_fd[
i] = fd[
i];
549 mem->regions[
i].address_offset =
550 mapped_address - mem->regions[
i].guest_phys_address;
552 DBG_SOCK (
"map memory region %d addr 0x%lx off 0x%lx len 0x%lx",
553 i, vui->region_addr[i], vui->region_offset[i], mapped_size);
558 mem->mapped_address = mem->regions[
i].address_offset;
562 disable_interface (xd);
567 dpdk_vhost_user_set_vring_num (
u32 hw_if_index,
u8 idx,
u32 num)
570 struct vhost_virtqueue *vq;
572 DBG_SOCK (
"idx %u num %u", idx, num);
574 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
579 vq = xd->vu_vhost_dev.virtqueue[idx];
582 stop_processing_packets (hw_if_index, idx);
588 dpdk_vhost_user_set_vring_addr (
u32 hw_if_index,
u8 idx,
uword desc,
592 struct vhost_virtqueue *vq;
594 DBG_SOCK (
"idx %u desc 0x%lx used 0x%lx avail 0x%lx log 0x%lx",
595 idx, desc, used, avail, log);
597 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
602 vq = xd->vu_vhost_dev.virtqueue[idx];
604 vq->desc = (
struct vring_desc *) qva_to_vva (&xd->vu_vhost_dev, desc);
605 vq->used = (
struct vring_used *) qva_to_vva (&xd->vu_vhost_dev, used);
606 vq->avail = (
struct vring_avail *) qva_to_vva (&xd->vu_vhost_dev, avail);
607 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 608 vq->log_guest_addr =
log;
611 if (!(vq->desc && vq->used && vq->avail))
616 if (vq->last_used_idx != vq->used->idx)
618 clib_warning (
"last_used_idx (%u) and vq->used->idx (%u) mismatches; " 619 "some packets maybe resent for Tx and dropped for Rx",
620 vq->last_used_idx, vq->used->idx);
621 vq->last_used_idx = vq->used->idx;
622 vq->last_used_idx_res = vq->used->idx;
633 rte_vhost_enable_guest_notification (&xd->vu_vhost_dev, idx, 0);
634 stop_processing_packets (hw_if_index, idx);
640 dpdk_vhost_user_get_vring_base (
u32 hw_if_index,
u8 idx,
u32 * num)
643 struct vhost_virtqueue *vq;
645 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
651 vq = xd->vu_vhost_dev.virtqueue[idx];
652 *num = vq->last_used_idx;
661 DBG_SOCK (
"Stopping vring Q %u of device %d", idx, hw_if_index);
662 dpdk_vu_intf_t *vui = xd->vu_intf;
663 vui->vrings[idx].enabled = 0;
664 vui->vrings[idx].callfd = -1;
669 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 670 vq->log_guest_addr = 0;
674 int numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
675 for (idx = 0; idx < numqs; idx++)
677 if (xd->vu_vhost_dev.virtqueue[idx]->enabled)
684 DBG_SOCK (
"Device %d disabled", hw_if_index);
685 xd->vu_is_running = 0;
692 dpdk_vhost_user_set_vring_base (
u32 hw_if_index,
u8 idx,
u32 num)
695 struct vhost_virtqueue *vq;
697 DBG_SOCK (
"idx %u num %u", idx, num);
699 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
705 vq = xd->vu_vhost_dev.virtqueue[idx];
706 vq->last_used_idx = num;
707 vq->last_used_idx_res = num;
709 stop_processing_packets (hw_if_index, idx);
715 dpdk_vhost_user_set_vring_kick (
u32 hw_if_index,
u8 idx,
int fd)
719 dpdk_vu_vring *vring;
720 struct vhost_virtqueue *vq0, *vq1, *vq;
721 int index, vu_is_running = 0;
723 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
729 vq = xd->vu_vhost_dev.virtqueue[idx];
732 vring = &xd->vu_intf->vrings[idx];
733 vq->enabled = (vq->desc && vq->avail && vq->used && vring->enabled) ? 1 : 0;
739 int numqs = VIRTIO_QNUM;
740 numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
742 for (index = 0; index < numqs; index += 2)
744 vq0 = xd->vu_vhost_dev.virtqueue[index];
745 vq1 = xd->vu_vhost_dev.virtqueue[index + 1];
746 if (vq0->enabled && vq1->enabled)
752 DBG_SOCK (
"SET_VRING_KICK - idx %d, running %d, fd: %d",
753 idx, vu_is_running, fd);
755 xd->vu_is_running = vu_is_running;
756 if (xd->vu_is_running && xd->
admin_up)
761 ETH_LINK_FULL_DUPLEX);
768 dpdk_vhost_user_set_vring_enable (
u32 hw_if_index,
u8 idx,
int enable)
771 struct vhost_virtqueue *vq;
774 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
788 vui->vrings[idx].enabled = enable;
790 int numqs = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
793 if (!vui->vrings[numqs].enabled)
802 vq = xd->vu_vhost_dev.virtqueue[idx];
803 if (vq->desc && vq->avail && vq->used)
804 xd->vu_vhost_dev.virtqueue[idx]->enabled = enable;
810 dpdk_vhost_user_callfd_read_ready (
unix_file_t * uf)
812 __attribute__ ((unused))
int n;
819 dpdk_vhost_user_set_vring_call (
u32 hw_if_index,
u8 idx,
int fd)
822 struct vhost_virtqueue *vq;
825 DBG_SOCK (
"SET_VRING_CALL - idx %d, fd %d", idx, fd);
827 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_index)))
833 dpdk_vu_intf_t *vui = xd->vu_intf;
836 if (vui->vrings[idx].callfd > 0)
839 vui->vrings[idx].callfd_idx);
842 vui->vrings[idx].callfd = fd;
843 template.read_function = dpdk_vhost_user_callfd_read_ready;
844 template.file_descriptor = fd;
847 vq = xd->vu_vhost_dev.virtqueue[idx];
856 dpdk_vu_intf_t *vui = xd->vu_intf;
862 dpdk_vu_vring *vring = &(vui->vrings[idx]);
863 struct vhost_virtqueue *vq = xd->vu_vhost_dev.virtqueue[idx];
866 return (vring->callfd > 0)
867 && !(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
874 dpdk_vu_intf_t *vui = xd->vu_intf;
880 dpdk_vu_vring *vring = &(vui->vrings[idx]);
881 struct vhost_virtqueue *vq = xd->vu_vhost_dev.virtqueue[idx];
884 if ((vring->callfd > 0) && !(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
886 eventfd_write (vring->callfd, (eventfd_t) 1);
887 vring->n_since_last_int = 0;
888 vring->int_deadline =
901 const char *sock_filename,
902 u8 is_server,
u64 feature_mask,
u32 * sw_if_index)
904 dpdk_vu_intf_t *vui = xd->vu_intf;
905 memset (vui, 0,
sizeof (*vui));
907 vui->unix_fd = sockfd;
908 vui->num_vrings = xd->vu_vhost_dev.virt_qp_nb * VIRTIO_QNUM;
909 DBG_SOCK (
"dpdk_vhost_user_vui_init VRINGS: %d", vui->num_vrings);
910 vui->sock_is_server = is_server;
911 strncpy (vui->sock_filename, sock_filename,
915 vui->feature_mask = feature_mask;
917 vui->unix_file_index = ~0;
930 dpdk_vu_intf_t *vui = xd->vu_intf;
940 dpdk_vu_intf_t *vui = xd->vu_intf;
941 struct virtio_memory *mem = xd->vu_vhost_dev.mem;
943 for (i = 0; i < mem->nregions; i++)
945 if (vui->region_addr[i] != -1)
950 ssize_t map_sz = RTE_ALIGN_CEIL (mem->regions[i].memory_size +
951 vui->region_offset[i], page_sz);
954 munmap ((
void *) (vui->region_addr[i] - vui->region_offset[i]),
958 (
"unmap memory region %d addr 0x%lx off 0x%lx len 0x%lx page_sz 0x%x",
959 i, vui->region_addr[i], vui->region_offset[i], map_sz, page_sz);
961 vui->region_addr[
i] = -1;
967 close (vui->region_fd[i]);
976 dpdk_vu_intf_t *vui = xd->vu_intf;
979 struct vhost_virtqueue *vq;
985 if (vui->unix_file_index != ~0)
988 vui->unix_file_index = ~0;
993 close (vui->unix_fd);
997 for (q = 0; q < vui->num_vrings; q++)
999 vq = xd->vu_vhost_dev.virtqueue[q];
1000 vui->vrings[q].enabled = 0;
1001 vui->vrings[q].callfd = -1;
1003 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 1004 vq->log_guest_addr = 0;
1010 xd->vu_is_running = 0;
1012 dpdk_unmap_all_mem_regions (xd);
1020 int fd, number_of_fds = 0;
1022 vhost_user_msg_t msg;
1024 struct iovec iov[1];
1027 dpdk_vu_intf_t *vui;
1028 struct cmsghdr *cmsg;
1040 xd = dpdk_vhost_user_device_from_sw_if_index (p[0]);
1047 memset (&mh, 0,
sizeof (mh));
1048 memset (control, 0,
sizeof (control));
1051 iov[0].iov_base = (
void *) &msg;
1056 mh.msg_control = control;
1057 mh.msg_controllen =
sizeof (control);
1064 if (mh.msg_flags & MSG_CTRUNC)
1069 cmsg = CMSG_FIRSTHDR (&mh);
1071 if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
1072 (cmsg->cmsg_type == SCM_RIGHTS) &&
1073 (cmsg->cmsg_len - CMSG_LEN (0) <=
1076 number_of_fds = (cmsg->cmsg_len - CMSG_LEN (0)) /
sizeof (
int);
1077 clib_memcpy (fds, CMSG_DATA (cmsg), number_of_fds *
sizeof (
int));
1081 if ((msg.flags & 7) != 1)
1083 DBG_SOCK (
"malformed message received. closing socket");
1088 int rv __attribute__ ((unused));
1093 DBG_SOCK (
"VPP VHOST message %s", vhost_message_str[msg.request]);
1094 switch (msg.request)
1102 msg.u64 &= vui->feature_mask;
1103 msg.size =
sizeof (msg.u64);
1107 DBG_SOCK (
"if %d msg VHOST_USER_SET_FEATURES features 0x%016lx",
1114 DBG_SOCK (
"if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
1117 if ((msg.memory.nregions < 1) ||
1121 DBG_SOCK (
"number of mem regions must be between 1 and %i",
1127 if (msg.memory.nregions != number_of_fds)
1129 DBG_SOCK (
"each memory region must have FD");
1134 dpdk_unmap_all_mem_regions (xd);
1140 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
1143 if ((msg.state.num > 32768) ||
1144 (msg.state.num == 0) ||
1145 (msg.state.num % 2))
1153 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
1157 msg.addr.desc_user_addr,
1158 msg.addr.used_user_addr,
1159 msg.addr.avail_user_addr,
1160 msg.addr.log_guest_addr);
1172 q = (
u8) (msg.u64 & 0xFF);
1174 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_CALL u64 %lx, idx: %d",
1177 if (!(msg.u64 & 0x100))
1179 if (number_of_fds != 1)
1193 q = (
u8) (msg.u64 & 0xFF);
1195 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_KICK u64 %lx, idx: %d",
1198 if (!(msg.u64 & 0x100))
1200 if (number_of_fds != 1)
1203 vui->vrings[q].kickfd = fds[0];
1206 vui->vrings[q].kickfd = -1;
1209 vui->vrings[q].kickfd);
1214 q = (
u8) (msg.u64 & 0xFF);
1216 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ERR u64 %lx, idx: %d",
1219 if (!(msg.u64 & 0x100))
1221 if (number_of_fds != 1)
1229 vui->vrings[q].errfd = fd;
1233 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_BASE idx %d num %d",
1241 DBG_SOCK (
"if %d msg VHOST_USER_GET_VRING_BASE idx %d num %d",
1245 msg.size =
sizeof (msg.state);
1256 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0) 1259 if (msg.size != sizeof (msg.log))
1262 (
"invalid msg size for VHOST_USER_SET_LOG_BASE: %u instead of %lu",
1263 msg.size, sizeof (msg.log));
1268 (xd->vu_vhost_dev.protocol_features & (1 <<
1272 (
"VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but VHOST_USER_SET_LOG_BASE received");
1280 RTE_ALIGN_CEIL (msg.log.size + msg.log.offset, page_sz);
1282 void *addr = mmap (0, map_sz, PROT_READ | PROT_WRITE,
1285 DBG_SOCK (
"map log region addr 0 len 0x%lx off 0x%lx fd %d mapped %p",
1286 map_sz, msg.log.offset, fd, addr);
1288 if (addr == MAP_FAILED)
1290 clib_warning (
"failed to map memory. errno is %d", errno);
1295 xd->vu_vhost_dev.log_size = msg.log.size;
1297 msg.size =
sizeof (msg.u64);
1299 DBG_SOCK (
"if %d msg VHOST_USER_SET_LOG_BASE Not-Implemented",
1309 DBG_SOCK (
"if %d msg VHOST_USER_GET_PROTOCOL_FEATURES",
1314 DBG_SOCK (
"VHOST_USER_PROTOCOL_FEATURES: %llx",
1316 msg.size =
sizeof (msg.u64);
1320 DBG_SOCK (
"if %d msg VHOST_USER_SET_PROTOCOL_FEATURES",
1323 DBG_SOCK (
"VHOST_USER_SET_PROTOCOL_FEATURES: 0x%lx", msg.u64);
1328 DBG_SOCK (
"%d VPP VHOST_USER_SET_VRING_ENABLE IDX: %d, Enable: %d",
1330 dpdk_vhost_user_set_vring_enable
1338 msg.u64 = xd->vu_vhost_dev.virt_qp_nb;
1339 msg.size =
sizeof (msg.u64);
1343 DBG_SOCK (
"unknown vhost-user message %d received. closing socket",
1375 dpdk_vhost_user_if_disconnect (xd);
1393 xd = dpdk_vhost_user_device_from_sw_if_index (p[0]);
1395 dpdk_vhost_user_if_disconnect (xd);
1400 dpdk_vhost_user_socksvr_accept_ready (
unix_file_t * uf)
1402 int client_fd, client_len;
1403 struct sockaddr_un client;
1407 dpdk_vu_intf_t *vui;
1417 xd = dpdk_vhost_user_device_from_sw_if_index (p[0]);
1421 client_len =
sizeof (client);
1423 (
struct sockaddr *) &client,
1424 (socklen_t *) & client_len);
1429 template.read_function = dpdk_vhost_user_socket_read;
1430 template.error_function = dpdk_vhost_user_socket_error;
1431 template.file_descriptor = client_fd;
1434 vui->client_fd = client_fd;
1443 dpdk_vhost_user_init_server_sock (
const char *sock_filename,
int *sockfd)
1446 struct sockaddr_un un = { };
1449 fd = socket (AF_UNIX, SOCK_STREAM, 0);
1453 return VNET_API_ERROR_SYSCALL_ERROR_1;
1456 un.sun_family = AF_UNIX;
1457 strcpy ((
char *) un.sun_path, (
char *) sock_filename);
1460 unlink ((
char *) sock_filename);
1462 if (bind (fd, (
struct sockaddr *) &un,
sizeof (un)) == -1)
1464 rv = VNET_API_ERROR_SYSCALL_ERROR_2;
1468 if (listen (fd, 1) == -1)
1470 rv = VNET_API_ERROR_SYSCALL_ERROR_3;
1475 template.
read_function = dpdk_vhost_user_socksvr_accept_ready;
1476 template.file_descriptor = fd;
1492 const char *sock_filename,
1496 u8 renumber,
u32 custom_dev_instance,
u8 * hwaddr)
1508 sw_if_index, feature_mask, renumber,
1509 custom_dev_instance, hwaddr);
1515 dpdk_vhost_user_init_server_sock (sock_filename, &sockfd)) != 0)
1527 dpdk_create_vhost_user_if_internal (&hw_if_idx, custom_dev_instance,
1531 dpdk_create_vhost_user_if_internal (&hw_if_idx, (
u32) ~ 0, hwaddr);
1532 DBG_SOCK (
"dpdk vhost-user interface created hw_if_index %d", hw_if_idx);
1534 xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_idx);
1537 dpdk_vhost_user_vui_init (vnm, xd, sockfd, sock_filename, is_server,
1538 feature_mask, sw_if_index);
1540 dpdk_vhost_user_vui_register (vm, xd);
1546 const char *sock_filename,
1550 u8 renumber,
u32 custom_dev_instance)
1554 dpdk_vu_intf_t *vui =
NULL;
1563 sw_if_index, feature_mask, renumber,
1564 custom_dev_instance);
1567 xd = dpdk_vhost_user_device_from_sw_if_index (sw_if_index);
1570 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1577 dpdk_vhost_user_if_disconnect (xd);
1582 dpdk_vhost_user_init_server_sock (sock_filename, &sockfd)) != 0)
1588 dpdk_vhost_user_vui_init (vnm, xd, sockfd, sock_filename, is_server,
1589 feature_mask, &sw_if_idx);
1596 dpdk_vhost_user_vui_register (vm, xd);
1607 dpdk_vu_intf_t *vui;
1616 xd = dpdk_vhost_user_device_from_sw_if_index (sw_if_index);
1619 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1626 dpdk_vhost_user_if_disconnect (xd);
1631 DBG_SOCK (
"deleted (deactivated) vhost-user interface sw_if_index %d",
1644 dpdk_vu_intf_t *vui;
1645 struct virtio_net *vhost_dev;
1648 u32 *hw_if_indices = 0;
1668 for (i = 0; i <
vec_len (hw_if_indices); i++)
1671 xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_indices[i]);
1674 clib_warning (
"invalid vhost-user interface hw_if_index %d",
1681 vhost_dev = &xd->vu_vhost_dev;
1682 u32 virtio_net_hdr_sz = (vui->num_vrings > 0 ?
1683 vhost_dev->virtqueue[0]->vhost_hlen : 0);
1688 vuid->
features = vhost_dev->features;
1691 (vhost_dev->mem !=
NULL ? vhost_dev->mem->nregions : 0);
1693 strncpy ((
char *) vuid->
sock_filename, (
char *) vui->sock_filename,
1698 strncpy ((
char *) vuid->
if_name, (
char *) s,
1706 *out_vuids = r_vuids;
1717 struct sockaddr_un sun;
1721 } dpdk_vu_process_state;
1724 dpdk_vhost_user_process_init (
void **ctx)
1726 dpdk_vu_process_state *
state =
1728 memset (state, 0,
sizeof (*state));
1729 state->sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
1730 state->sun.sun_family = AF_UNIX;
1731 state->template.read_function = dpdk_vhost_user_socket_read;
1732 state->template.error_function = dpdk_vhost_user_socket_error;
1733 state->event_data = 0;
1738 dpdk_vhost_user_process_cleanup (
void *ctx)
1747 dpdk_vu_process_state *
state = (dpdk_vu_process_state *) ctx;
1748 dpdk_vu_intf_t *vui = xd->vu_intf;
1750 if (vui->sock_is_server || !vui->active)
1753 if (vui->unix_fd == -1)
1756 strncpy (state->sun.sun_path, (
char *) vui->sock_filename,
1757 sizeof (state->sun.sun_path) - 1);
1760 (state->sockfd, (
struct sockaddr *) &(state->sun),
1761 sizeof (
struct sockaddr_un)) == 0)
1763 vui->sock_errno = 0;
1764 vui->unix_fd = state->sockfd;
1765 state->template.file_descriptor = state->sockfd;
1766 vui->unix_file_index =
1771 state->sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
1772 if (state->sockfd < 0)
1777 vui->sock_errno = errno;
1784 socklen_t len =
sizeof (error);
1786 getsockopt (vui->unix_fd, SOL_SOCKET, SO_ERROR, &error, &len);
1789 dpdk_vhost_user_if_disconnect (xd);
1807 u8 *sock_filename =
NULL;
1810 u64 feature_mask = (
u64) ~ 0;
1812 u32 custom_dev_instance = ~0;
1829 if (
unformat (line_input,
"socket %s", &sock_filename))
1831 else if (
unformat (line_input,
"server"))
1833 else if (
unformat (line_input,
"feature-mask 0x%llx", &feature_mask))
1839 else if (
unformat (line_input,
"renumber %d", &custom_dev_instance))
1850 if (sock_filename ==
NULL)
1853 dpdk_vhost_user_create_if (vnm, vm, (
char *) sock_filename,
1854 is_server, &sw_if_index, feature_mask,
1855 renumber, custom_dev_instance, hw);
1866 .path =
"create vhost-user",
1867 .short_help =
"create vhost-user socket <socket-filename> [server] [feature-mask <hex>] [renumber <dev_instance>]",
1880 u32 sw_if_index = ~0;
1893 if (
unformat (line_input,
"sw_if_index %d", &sw_if_index))
1901 if (sw_if_index == ~0)
1911 dpdk_vhost_user_delete_if (vnm, vm, sw_if_index);
1921 .path =
"delete vhost-user",
1922 .short_help =
"delete vhost-user sw_if_index <nn>",
1927 #define foreach_dpdk_vhost_feature \ 1928 _ (VIRTIO_NET_F_MRG_RXBUF) \ 1929 _ (VIRTIO_NET_F_CTRL_VQ) \ 1930 _ (VIRTIO_NET_F_CTRL_RX) 1942 dpdk_vu_intf_t *vui;
1943 struct virtio_net *vhost_dev;
1944 u32 hw_if_index, *hw_if_indices = 0;
1948 struct virtio_memory *mem;
1954 struct feat_struct *feat_entry;
1956 static struct feat_struct feat_array[] = {
1957 #define _(f) { .str = #f, .bit = f, }, 1975 vec_add1 (hw_if_indices, hw_if_index);
1987 if (
vec_len (hw_if_indices) == 0)
2001 for (i = 0; i <
vec_len (hw_if_indices); i++)
2005 if (!(xd = dpdk_vhost_user_device_from_hw_if_index (hw_if_indices[i])))
2012 vhost_dev = &xd->vu_vhost_dev;
2013 mem = vhost_dev->mem;
2014 u32 virtio_net_hdr_sz = (vui->num_vrings > 0 ?
2015 vhost_dev->virtqueue[0]->vhost_hlen : 0);
2018 hi->
name, hw_if_indices[i]);
2021 virtio_net_hdr_sz, xd->vu_vhost_dev.features);
2023 feat_entry = (
struct feat_struct *) &feat_array;
2024 while (feat_entry->str)
2026 if (xd->vu_vhost_dev.features & (1 << feat_entry->bit))
2036 vui->sock_is_server ?
"server" :
"client",
2037 strerror (vui->sock_errno));
2044 " region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr\n");
2046 " ====== ===== ================== ================== ================== ================== ==================\n");
2048 for (j = 0; j < mem->nregions; j++)
2051 " %d %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
2052 j, vui->region_fd[j],
2053 mem->regions[j].guest_phys_address,
2054 mem->regions[j].memory_size,
2055 mem->regions[j].userspace_address,
2056 mem->regions[j].address_offset,
2057 vui->region_addr[j]);
2059 for (q = 0; q < vui->num_vrings; q++)
2061 struct vhost_virtqueue *vq = vhost_dev->virtqueue[q];
2062 const char *qtype = (q & 1) ?
"TX" :
"RX";
2067 " qsz %d last_used_idx %d last_used_idx_res %d\n",
2068 vq->size, vq->last_used_idx,
2069 vq->last_used_idx_res);
2071 if (vq->avail && vq->used)
2073 " avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
2074 vq->avail->flags, vq->avail->idx,
2075 vq->used->flags, vq->used->idx);
2078 vq->kickfd, vq->callfd, vui->vrings[q].errfd,
2081 if (show_descr && vq->enabled)
2085 " id addr len flags next user_addr\n");
2087 " ===== ================== ===== ====== ===== ==================\n");
2088 for (j = 0; j < vq->size; j++)
2091 " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
2092 j, vq->desc[j].addr, vq->desc[j].len,
2093 vq->desc[j].flags, vq->desc[j].next,
2095 (xd, vq->desc[j].addr)));
2109 .path =
"show vhost-user",
2110 .short_help =
"show vhost-user interface",
unformat_function_t unformat_vnet_hw_interface
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void dpdk_device_lock_free(dpdk_device_t *xd)
#define hash_set(h, key, value)
sll srl srl sll sra u16x4 i
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
unix_file_function_t * read_function
#define hash_unset(h, key)
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
static vlib_main_t * vlib_get_main(void)
static void * map_guest_mem(vhost_user_intf_t *vui, uword addr)
vnet_device_class_t dpdk_device_class
u32 vhost_coalesce_frames
static f64 vlib_time_now(vlib_main_t *vm)
#define vec_add2_aligned(V, P, N, A)
Add N elements to end of vector V, return pointer to new elements in P.
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
int vnet_interface_name_renumber(u32 sw_if_index, u32 new_show_dev_instance)
#define VHOST_USER_MSG_HDR_SZ
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
u32 per_interface_next_index
vlib_worker_thread_t * vlib_worker_threads
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
#define VHOST_USER_PROTOCOL_FEATURES
clib_error_t * show_vhost_user_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
format_function_t format_vnet_sw_if_index_name
static uword unix_file_add(unix_main_t *um, unix_file_t *template)
#define VHOST_USER_REPLY_MASK
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_main_t * vnet_get_main(void)
struct rte_mbuf *** tx_vectors
vlib_node_registration_t dpdk_input_node
(constructor) VLIB_REGISTER_NODE (dpdk_input_node)
int input_cpu_first_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define foreach_dpdk_vhost_feature
#define clib_warning(format, args...)
static uword pointer_to_uword(const void *p)
vlib_main_t ** vlib_mains
static void unix_file_del(unix_main_t *um, unix_file_t *f)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
dpdk_device_and_queue_t ** devices_by_cpu
int vhost_user_delete_if(vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index)
#define clib_error_return_unix(e, args...)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
int vhost_user_dump_ifs(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_intf_details_t **out_vuids)
#define uword_to_pointer(u, type)
int vhost_user_create_if(vnet_main_t *vnm, vlib_main_t *vm, const char *sock_filename, u8 is_server, u32 *sw_if_index, u64 feature_mask, u8 renumber, u32 custom_dev_instance, u8 *hwaddr)
u16 * cpu_socket_id_by_queue
#define vec_free(V)
Free vector's memory (no header).
vhost_user_memory_region_t regions[VHOST_MEMORY_MAX_NREGIONS]
static vlib_thread_main_t * vlib_get_thread_main()
struct rte_mbuf *** rx_vectors
int vhost_user_modify_if(vnet_main_t *vnm, vlib_main_t *vm, const char *sock_filename, u8 is_server, u32 sw_if_index, u64 feature_mask, u8 renumber, u32 custom_dev_instance)
#define clib_memcpy(a, b, c)
#define VHOST_MEMORY_MAX_NREGIONS
#define clib_unix_warning(format, args...)
static clib_error_t * dpdk_vhost_user_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
static clib_error_t * show_dpdk_vhost_user_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD
#define vec_validate_ha(V, I, H, A)
Make sure vector is long enough for given index (general version).
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
#define DPDK_TX_RING_SIZE
u32 * vu_inactive_interfaces_device_index
static long get_huge_page_size(int fd)
vhost_vring_state_t state
clib_error_t * vhost_user_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static void clib_mem_free(void *p)
void dpdk_device_lock_init(dpdk_device_t *xd)
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
static void * clib_mem_alloc(uword size)
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
dpdk_device_type_t dev_type
#define VHOST_NET_VRING_IDX_RX
#define VHOST_USER_F_PROTOCOL_FEATURES
static u32 random_u32(u32 *seed)
32-bit random number generator
#define VHOST_NET_VRING_IDX_TX
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
vnet_sw_interface_type_t type
#define vec_foreach(var, vec)
Vector iterator.
#define clib_error_return(e, args...)
#define CLIB_CACHE_LINE_BYTES
static clib_error_t * dpdk_vhost_user_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
clib_error_t * vhost_user_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define DBG_SOCK(args...)
uword * vu_sw_if_index_by_listener_fd
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
dpdk_config_main_t * conf
uword * vu_sw_if_index_by_sock_fd