21 #include <sys/ioctl.h> 22 #include <sys/socket.h> 25 #include <sys/types.h> 27 #include <netinet/in.h> 30 #include <linux/if_arp.h> 31 #include <linux/if_tun.h> 44 #define VHOST_USER_DEBUG_SOCKET 0 45 #define VHOST_USER_DEBUG_VQ 0 49 #define VHOST_USER_COPY_TX_HDR 0 51 #if VHOST_USER_DEBUG_SOCKET == 1 52 #define DBG_SOCK(args...) clib_warning(args); 54 #define DBG_SOCK(args...) 57 #if VHOST_USER_DEBUG_VQ == 1 58 #define DBG_VQ(args...) clib_warning(args); 60 #define DBG_VQ(args...) 65 #define foreach_vhost_user_tx_func_error \ 67 _(NOT_READY, "vhost user state error") \ 68 _(PKT_DROP_NOBUF, "tx packet drops (no available descriptors)") \ 69 _(PKT_DROP_NOMRG, "tx packet drops (cannot merge descriptors)") \ 70 _(MMAP_FAIL, "mmap failure") \ 71 _(INDIRECT_OVERFLOW, "indirect descriptor table overflow") 75 #define _(f,s) VHOST_USER_TX_FUNC_ERROR_##f, 87 #define foreach_vhost_user_input_func_error \ 88 _(NO_ERROR, "no error") \ 89 _(NO_BUFFER, "no available buffer") \ 90 _(MMAP_FAIL, "mmap failure") \ 91 _(INDIRECT_OVERFLOW, "indirect descriptor overflows table") \ 92 _(UNDERSIZED_FRAME, "undersized ethernet frame received (< 14 bytes)") \ 93 _(FULL_RX_QUEUE, "full rx queue (possible driver tx drop)") 97 #define _(f,s) VHOST_USER_INPUT_FUNC_ERROR_##f, 115 .name =
"vhost-user",
123 u32 show_dev_instance = ~0;
129 if (show_dev_instance != ~0)
130 i = show_dev_instance;
132 s =
format (s,
"VirtualEthernet0/0/%d", i);
147 DBG_SOCK (
"renumbered vhost-user interface dev_instance %d to %d",
165 __m128i rl, rh, al, ah, r;
166 al = _mm_set1_epi64x (addr + 1);
167 ah = _mm_set1_epi64x (addr);
170 rl = _mm_cmpgt_epi64 (al, rl);
172 rh = _mm_cmpgt_epi64 (rh, ah);
173 r = _mm_and_si128 (rl, rh);
176 rl = _mm_cmpgt_epi64 (al, rl);
178 rh = _mm_cmpgt_epi64 (rh, ah);
179 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x22);
182 rl = _mm_cmpgt_epi64 (al, rl);
184 rh = _mm_cmpgt_epi64 (rh, ah);
185 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x44);
188 rl = _mm_cmpgt_epi64 (al, rl);
190 rh = _mm_cmpgt_epi64 (rh, ah);
191 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x88);
193 r = _mm_shuffle_epi8 (r, _mm_set_epi64x (0, 0x0e060c040a020800));
194 i = __builtin_ctzll (_mm_movemask_epi8 (r));
196 if (i < vui->nregions)
216 DBG_VQ (
"failed to map guest mem addr %llx", addr);
259 page_sz) & ~(page_sz - 1);
266 (
"unmap memory region %d addr 0x%lx len 0x%lx page_sz 0x%x", i,
273 clib_warning (
"failed to unmap memory region (errno %d)",
286 __attribute__ ((unused))
int n;
338 #define VHOST_LOG_PAGE 0x1000 343 || !(vui->
features & (1 << FEAT_VHOST_F_LOG_ALL))))
349 DBG_SOCK (
"vhost_user_log_dirty_pages(): out of range\n");
362 #define vhost_user_log_dirty_ring(vui, vq, member) \ 363 if (PREDICT_FALSE(vq->log_used)) { \ 364 vhost_user_log_dirty_pages(vui, vq->log_guest_addr + STRUCT_OFFSET_OF(vring_used_t, member), \ 365 sizeof(vq->used->member)); \ 372 int fd, number_of_fds = 0;
374 vhost_user_msg_t msg;
379 struct cmsghdr *cmsg;
385 p =
hash_get (vum->vhost_user_interface_index_by_sock_fd,
397 memset (&mh, 0,
sizeof (mh));
398 memset (control, 0,
sizeof (control));
404 iov[0].iov_base = (
void *) &msg;
409 mh.msg_control = control;
410 mh.msg_controllen =
sizeof (control);
417 if (mh.msg_flags & MSG_CTRUNC)
422 cmsg = CMSG_FIRSTHDR (&mh);
424 if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
425 (cmsg->cmsg_type == SCM_RIGHTS) &&
426 (cmsg->cmsg_len - CMSG_LEN (0) <=
427 VHOST_MEMORY_MAX_NREGIONS *
sizeof (
int)))
429 number_of_fds = (cmsg->cmsg_len - CMSG_LEN (0)) /
sizeof (
int);
430 clib_memcpy (fds, CMSG_DATA (cmsg), number_of_fds *
sizeof (
int));
434 if ((msg.flags & 7) != 1)
436 DBG_SOCK (
"malformed message received. closing socket");
441 int rv __attribute__ ((unused));
452 msg.u64 = (1 << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
453 (1 << FEAT_VIRTIO_F_ANY_LAYOUT) |
454 (1 << FEAT_VIRTIO_F_INDIRECT_DESC) |
455 (1 << FEAT_VHOST_F_LOG_ALL) |
456 (1 << FEAT_VIRTIO_NET_F_GUEST_ANNOUNCE) |
457 (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES) |
458 (1UL << FEAT_VIRTIO_F_VERSION_1);
461 msg.size =
sizeof (msg.u64);
465 DBG_SOCK (
"if %d msg VHOST_USER_SET_FEATURES features 0x%016llx",
470 if (vui->
features & (1 << FEAT_VIRTIO_NET_F_MRG_RXBUF))
476 (vui->
features & (1 << FEAT_VIRTIO_F_ANY_LAYOUT)) ? 1 : 0;
482 for (q = 0; q < 2; q++)
496 DBG_SOCK (
"if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
499 if ((msg.memory.nregions < 1) ||
500 (msg.memory.nregions > VHOST_MEMORY_MAX_NREGIONS))
503 DBG_SOCK (
"number of mem regions must be between 1 and %i",
504 VHOST_MEMORY_MAX_NREGIONS);
509 if (msg.memory.nregions != number_of_fds)
511 DBG_SOCK (
"each memory region must have FD");
515 for (i = 0; i < msg.memory.nregions; i++)
525 page_sz) & ~(page_sz - 1);
528 MAP_SHARED, fds[i], 0);
534 (
"map memory region %d addr 0 len 0x%lx fd %d mapped 0x%lx " 540 clib_warning (
"failed to map memory. errno is %d", errno);
546 vui->
nregions = msg.memory.nregions;
550 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
553 if ((msg.state.num > 32768) ||
554 (msg.state.num == 0) ||
557 vui->
vrings[msg.state.index].
qsz = msg.state.num;
561 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
564 vui->
vrings[msg.state.index].
desc = (vring_desc_t *)
566 vui->
vrings[msg.state.index].
used = (vring_used_t *)
568 vui->
vrings[msg.state.index].
avail = (vring_avail_t *)
575 DBG_SOCK (
"failed to map user memory for hw_if_index %d",
587 if (!(vui->
features & (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES)))
597 vui->
vrings[msg.state.index].
used->flags |= 1;
609 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_CALL u64 %d",
612 q = (
u8) (msg.u64 & 0xFF);
614 if (!(msg.u64 & 0x100))
616 if (number_of_fds != 1)
628 template.file_descriptor = fds[0];
636 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_KICK u64 %d",
639 q = (
u8) (msg.u64 & 0xFF);
641 if (!(msg.u64 & 0x100))
643 if (number_of_fds != 1)
656 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ERR u64 %d",
659 q = (
u8) (msg.u64 & 0xFF);
661 if (!(msg.u64 & 0x100))
663 if (number_of_fds != 1)
675 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_BASE idx %d num %d",
682 DBG_SOCK (
"if %d msg VHOST_USER_GET_VRING_BASE idx %d num %d",
690 msg.size =
sizeof (msg.state);
702 if (msg.size != sizeof (msg.log))
705 (
"invalid msg size for VHOST_USER_SET_LOG_BASE: %d instead of %d",
706 msg.size, sizeof (msg.log));
714 (
"VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but VHOST_USER_SET_LOG_BASE received");
722 (msg.log.size + msg.log.offset + page_sz) & ~(page_sz - 1);
724 vui->
log_base_addr = mmap (0, map_sz, PROT_READ | PROT_WRITE,
728 (
"map log region addr 0 len 0x%lx off 0x%lx fd %d mapped 0x%lx",
733 clib_warning (
"failed to map memory. errno is %d", errno);
741 msg.size =
sizeof (msg.u64);
752 DBG_SOCK (
"if %d msg VHOST_USER_GET_PROTOCOL_FEATURES",
757 msg.size =
sizeof (msg.u64);
761 DBG_SOCK (
"if %d msg VHOST_USER_SET_PROTOCOL_FEATURES features 0x%lx",
769 DBG_SOCK (
"if %d VHOST_USER_SET_VRING_ENABLE, enable: %d",
775 DBG_SOCK (
"unknown vhost-user message %d received. closing socket",
834 int client_fd, client_len;
835 struct sockaddr_un client;
851 client_len =
sizeof (client);
853 (
struct sockaddr *) &client,
854 (socklen_t *) & client_len);
861 template.file_descriptor = client_fd;
902 if (tr && tr->
count > 0)
926 #if VHOST_USER_COPY_TX_HDR == 1 927 virtio_net_hdr_t hdr;
944 #if VHOST_USER_COPY_TX_HDR == 1 948 s =
format (s,
"%U virtqueue %d",
951 #if VHOST_USER_COPY_TX_HDR == 1 952 s =
format (s,
"\n%Uvirtio_net_hdr flags 0x%02x gso_type %u hdr_len %u",
954 t->hdr.flags, t->hdr.gso_type, t->hdr.hdr_len);
987 #if VHOST_USER_COPY_TX_HDR == 1 1000 int rv __attribute__ ((unused));
1002 rv = write (vq->
callfd, &x, sizeof (x));
1015 uword n_rx_packets = 0, n_rx_bytes = 0;
1017 u32 n_left_to_next, *to_next;
1022 u32 cpu_index, rx_len, drops, flush;
1024 u32 map_guest_hint_desc = 0;
1025 u32 map_guest_hint_indirect = 0;
1026 u32 *map_guest_hint_p = &map_guest_hint_desc;
1056 VHOST_USER_INPUT_FUNC_ERROR_FULL_RX_QUEUE, 1);
1070 qsz_mask = txvq->
qsz - 1;
1104 flush = n_left - _vec_len (vum->
rx_buffers[cpu_index]);
1113 VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER, flush);
1116 u16 desc_chain_head =
1134 while (n_left > 0 && n_left_to_next > 0)
1137 u32 bi_head, bi_current;
1138 u16 desc_chain_head, desc_current;
1139 u8 error = VHOST_USER_INPUT_FUNC_ERROR_NO_ERROR;
1147 &map_guest_hint_desc);
1156 desc_chain_head = desc_current =
1158 bi_head = bi_current = vum->
rx_buffers[cpu_index][--rx_len];
1173 offset = txvq->
desc[desc_current].len;
1176 vring_desc_t *desc_table = txvq->
desc;
1177 u32 desc_index = desc_current;
1178 map_guest_hint_p = &map_guest_hint_desc;
1180 if (txvq->
desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT)
1183 &map_guest_hint_desc);
1185 map_guest_hint_p = &map_guest_hint_indirect;
1188 error = VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL;
1200 error = VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL;
1205 (desc_table[desc_index].
flags & VIRTQ_DESC_F_NEXT))
1208 sizeof (vring_desc_t), STORE);
1211 #if VHOST_USER_COPY_TX_HDR == 1 1213 clib_memcpy (b->pre_data, buffer_addr, sizeof (virtio_net_hdr_t));
1216 if (desc_table[desc_index].len > offset)
1218 u16 len = desc_table[desc_index].len -
offset;
1229 error = VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER;
1236 if ((desc_table[desc_index].
flags & VIRTQ_DESC_F_NEXT))
1237 desc_index = desc_table[desc_index].next;
1258 error == VHOST_USER_INPUT_FUNC_ERROR_NO_ERROR))
1259 error = VHOST_USER_INPUT_FUNC_ERROR_UNDERSIZED_FRAME;
1284 to_next[0] = bi_head;
1293 to_next, n_left_to_next,
1303 _vec_len (vum->
rx_buffers[cpu_index]) = rx_len;
1318 if ((txvq->
callfd > -1) && !(txvq->
avail->flags & 1))
1340 return n_rx_packets;
1350 uword n_rx_packets = 0;
1363 return n_rx_packets;
1370 .name =
"vhost-user-input",
1373 .state = VLIB_NODE_STATE_DISABLED,
1395 uword n_packets = 0;
1401 u8 error = VHOST_USER_TX_FUNC_ERROR_NONE;
1404 u32 map_guest_hint_desc = 0;
1405 u32 map_guest_hint_indirect = 0;
1406 u32 *map_guest_hint_p = &map_guest_hint_desc;
1414 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
1420 while (__sync_lock_test_and_set (vui->lockp, 1))
1428 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
1434 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1438 qsz_mask = rxvq->
qsz - 1;
1443 u16 desc_head, desc_index, desc_len;
1444 vring_desc_t *desc_table;
1453 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1457 desc_table = rxvq->
desc;
1458 map_guest_hint_p = &map_guest_hint_desc;
1459 desc_head = desc_index =
1464 (rxvq->
desc[desc_head].len < sizeof (vring_desc_t)))
1466 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
1472 &map_guest_hint_desc))))
1474 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1478 map_guest_hint_p = &map_guest_hint_indirect;
1481 desc_len = vui->virtio_net_hdr_sz;
1486 map_guest_hint_p))))
1488 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1491 buffer_len = desc_table[desc_index].len;
1495 virtio_net_hdr_mrg_rxbuf_t *hdr =
1496 (virtio_net_hdr_mrg_rxbuf_t *) buffer_addr;
1498 hdr->hdr.gso_type = 0;
1499 if (vui->virtio_net_hdr_sz == 12)
1500 hdr->num_buffers = 1;
1503 vui->virtio_net_hdr_sz);
1506 buffer_addr += vui->virtio_net_hdr_sz;
1507 buffer_len -= vui->virtio_net_hdr_sz;
1525 if (buffer_len == 0)
1530 desc_index = desc_table[desc_index].next;
1534 map_guest_hint_p))))
1538 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1541 buffer_len = desc_table[desc_index].len;
1543 else if (vui->virtio_net_hdr_sz == 12)
1563 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1567 desc_table = rxvq->
desc;
1568 map_guest_hint_p = &map_guest_hint_desc;
1569 desc_head = desc_index =
1572 (rxvq->
desc[desc_head].flags & VIRTQ_DESC_F_INDIRECT))
1577 (rxvq->
desc[desc_head].len < sizeof (vring_desc_t)))
1579 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
1585 rxvq->
desc[desc_index].addr,
1586 &map_guest_hint_desc))))
1588 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1592 map_guest_hint_p = &map_guest_hint_indirect;
1598 map_guest_hint_p))))
1600 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1603 buffer_len = desc_table[desc_index].len;
1608 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOMRG;
1613 u16 bytes_to_copy = bytes_left;
1615 (bytes_to_copy > buffer_len) ? buffer_len : bytes_to_copy;
1622 desc_table[desc_index].addr +
1623 desc_table[desc_index].len -
1624 bytes_left - bytes_to_copy,
1627 bytes_left -= bytes_to_copy;
1628 buffer_len -= bytes_to_copy;
1629 buffer_addr += bytes_to_copy;
1630 desc_len += bytes_to_copy;
1651 if ((rxvq->
callfd > -1) && !(rxvq->
avail->flags & 1))
1664 if (
PREDICT_FALSE (n_left && error != VHOST_USER_TX_FUNC_ERROR_NONE))
1698 .name =
"vhost-user",
1705 .no_flatten_output_chains = 1,
1718 struct sockaddr_un sun;
1721 f64 timeout = 3153600000.0 ;
1722 uword *event_data = 0;
1724 sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
1725 sun.sun_family = AF_UNIX;
1752 sizeof (sun.sun_path) - 1);
1755 (sockfd, (
struct sockaddr *) &sun,
1756 sizeof (
struct sockaddr_un)) == 0)
1760 template.file_descriptor = sockfd;
1765 sockfd = socket (AF_UNIX, SOCK_STREAM, 0);
1778 socklen_t len =
sizeof (error);
1780 getsockopt (vui->
unix_fd, SOL_SOCKET, SO_ERROR, &error, &len);
1792 .function = vhost_user_process,
1794 .name =
"vhost-user-process",
1809 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1828 DBG_SOCK (
"deleted (deactivated) vhost-user interface instance %d", p[0]);
1838 struct sockaddr_un un = { };
1841 fd = socket (AF_UNIX, SOCK_STREAM, 0);
1845 return VNET_API_ERROR_SYSCALL_ERROR_1;
1848 un.sun_family = AF_UNIX;
1849 strncpy ((
char *) un.sun_path, (
char *) sock_filename,
1850 sizeof (un.sun_path) - 1);
1853 unlink ((
char *) sock_filename);
1855 if (bind (fd, (
struct sockaddr *) &un,
sizeof (un)) == -1)
1857 rv = VNET_API_ERROR_SYSCALL_ERROR_2;
1861 if (listen (fd, 1) == -1)
1863 rv = VNET_API_ERROR_SYSCALL_ERROR_3;
1869 template.file_descriptor = fd;
1887 if (inactive_cnt > 0)
1895 DBG_SOCK (
"reusing inactive vhost-user interface index %d",
1926 rnd = (
u32) (now * 1e6);
1936 vhost_user_dev_class.index,
1951 const char *sock_filename,
1952 u8 is_server,
u64 feature_mask,
u32 * sw_if_index)
1972 for (q = 0; q < 2; q++)
2011 VLIB_NODE_STATE_POLLING);
2014 VLIB_NODE_STATE_POLLING);
2022 const char *sock_filename,
2026 u8 renumber,
u32 custom_dev_instance,
u8 * hwaddr)
2046 feature_mask, &sw_if_idx);
2056 *sw_if_index = sw_if_idx;
2063 const char *sock_filename,
2066 u64 feature_mask,
u8 renumber,
u32 custom_dev_instance)
2078 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
2099 feature_mask, &sw_if_idx);
2117 u8 *sock_filename =
NULL;
2120 u64 feature_mask = (
u64) ~ 0;
2122 u32 custom_dev_instance = ~0;
2132 if (
unformat (line_input,
"socket %s", &sock_filename))
2134 else if (
unformat (line_input,
"server"))
2136 else if (
unformat (line_input,
"feature-mask 0x%llx", &feature_mask))
2142 else if (
unformat (line_input,
"renumber %d", &custom_dev_instance))
2156 is_server, &sw_if_index, feature_mask,
2157 renumber, custom_dev_instance, hw)))
2175 u32 sw_if_index = ~0;
2183 if (
unformat (line_input,
"sw_if_index %d", &sw_if_index))
2207 u32 *hw_if_indices = 0;
2221 for (i = 0; i <
vec_len (hw_if_indices); i++)
2238 strncpy ((
char *) vuid->
if_name, (
char *) s,
2246 *out_vuids = r_vuids;
2260 u32 hw_if_index, *hw_if_indices = 0;
2269 struct feat_struct *feat_entry;
2271 static struct feat_struct feat_array[] = {
2272 #define _(s,b) { .str = #s, .bit = b, }, 2283 vec_add1 (hw_if_indices, hw_if_index);
2295 if (
vec_len (hw_if_indices) == 0)
2307 for (i = 0; i <
vec_len (hw_if_indices); i++)
2312 hi->
name, hw_if_indices[i]);
2317 feat_entry = (
struct feat_struct *) &feat_array;
2318 while (feat_entry->str)
2320 if (vui->
features & (1 << feat_entry->bit))
2339 " region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr\n");
2341 " ====== ===== ================== ================== ================== ================== ==================\n");
2343 for (j = 0; j < vui->
nregions; j++)
2346 " %d %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
2359 " qsz %d last_avail_idx %d last_used_idx %d\n",
2365 " avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
2379 " id addr len flags next user_addr\n");
2381 " ===== ================== ===== ====== ===== ==================\n");
2382 for (j = 0; j < vui->
vrings[q].
qsz; j++)
2386 " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
2411 .path =
"create vhost-user",
2412 .short_help =
"create vhost-user socket <socket-filename> [server] [feature-mask <hex>] [renumber <dev_instance>]",
2417 .path =
"delete vhost-user",
2418 .short_help =
"delete vhost-user sw_if_index <nn>",
2423 .path =
"show vhost-user",
2424 .short_help =
"show vhost-user interface",
2440 else if (
unformat (input,
"dont-dump-memory"))
unformat_function_t unformat_vnet_hw_interface
static clib_error_t * vhost_user_init(vlib_main_t *vm)
static void vhost_user_vui_init(vnet_main_t *vnm, vhost_user_intf_t *vui, int sockfd, const char *sock_filename, u8 is_server, u64 feature_mask, u32 *sw_if_index)
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
Increment a simple counter.
static void vhost_user_if_disconnect(vhost_user_intf_t *vui)
#define hash_set(h, key, value)
static uword vhost_user_intfc_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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)
static u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
unix_file_function_t * read_function
#define hash_unset(h, key)
static void vhost_user_create_ethernet(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_intf_t *vui, u8 *hwaddress)
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
static clib_error_t * vhost_user_socket_error(unix_file_t *uf)
u64 region_guest_addr_hi[VHOST_MEMORY_MAX_NREGIONS]
uword * vhost_user_interface_index_by_sock_fd
vnet_interface_main_t interface_main
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
static vhost_user_intf_t * vhost_user_vui_new()
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Allocate buffers from specific freelist into supplied array.
static f64 vlib_time_now(vlib_main_t *vm)
static uword vhost_user_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
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)
static u32 vhost_user_if_input(vlib_main_t *vm, vhost_user_main_t *vum, vhost_user_intf_t *vui, vlib_node_runtime_t *node)
static u8 * format_vhost_user_input_trace(u8 *s, va_list *va)
struct _vlib_node_registration vlib_node_registration_t
#define VHOST_USER_MSG_HDR_SZ
static clib_error_t * vhost_user_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
static void vhost_user_vui_register(vlib_main_t *vm, vhost_user_intf_t *vui)
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
clib_error_t * show_vhost_user_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define clib_error_report(e)
#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)
static char * vhost_user_input_func_error_strings[]
static char * vhost_user_tx_func_error_strings[]
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
format_function_t format_vnet_sw_if_index_name
static uword unix_file_add(unix_main_t *um, unix_file_t *template)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static int vhost_user_name_renumber(vnet_hw_interface_t *hi, u32 new_dev_instance)
static vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)
static void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
#define VHOST_VRING_F_LOG
vnet_main_t * vnet_get_main(void)
vhost_user_vring_t vrings[2]
VNET_DEVICE_CLASS(vhost_user_dev_class, static)
static u8 * format_vhost_user_interface_name(u8 *s, va_list *args)
#define static_always_inline
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
#define VLIB_INIT_FUNCTION(x)
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
vlib_combined_counter_main_t * combined_sw_if_counters
static_always_inline void vnet_feature_device_input_redirect_x1(vlib_node_runtime_t *node, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0, u16 buffer_advanced0)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
void vhost_user_rx_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vhost_user_intf_t *vui, i16 virtqueue)
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
vhost_user_tx_func_error_t
#define clib_warning(format, args...)
static void unmap_all_mem_regions(vhost_user_intf_t *vui)
VLIB_DEVICE_TX_FUNCTION_MULTIARCH(vhost_user_dev_class, vhost_user_intfc_tx)
vhost_user_input_func_error_t
#define vlib_call_init_function(vm, x)
static clib_error_t * vhost_user_socket_read(unix_file_t *uf)
static uword pointer_to_uword(const void *p)
#define VLIB_BUFFER_NEXT_PRESENT
vlib_main_t ** vlib_mains
#define VLIB_BUFFER_PRE_DATA_SIZE
static void unix_file_del(unix_main_t *um, unix_file_t *f)
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
u16 current_length
Nbytes between current data and the end of this buffer.
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
int vhost_user_delete_if(vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index)
static void * map_user_mem(vhost_user_intf_t *vui, uword addr)
uword os_get_cpu_number(void)
#define VIRTQ_DESC_F_INDIRECT
#define clib_error_return_unix(e, args...)
#define VLIB_CONFIG_FUNCTION(x, n,...)
#define vhost_user_log_dirty_ring(vui, vq, member)
static vlib_node_registration_t vhost_user_process_node
(constructor) VLIB_REGISTER_NODE (vhost_user_process_node)
void vhost_user_unmap_all(void)
#define VNET_DEVICE_INPUT_NEXT_NODES
vlib_simple_counter_main_t * sw_if_counters
u32 region_mmap_fd[VHOST_MEMORY_MAX_NREGIONS]
static void vhost_user_send_call(vlib_main_t *vm, vhost_user_vring_t *vq)
vhost_user_memory_region_t regions[VHOST_MEMORY_MAX_NREGIONS]
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
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)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static void vhost_user_log_dirty_pages(vhost_user_intf_t *vui, u64 addr, u64 len)
static void vlib_buffer_chain_init(vlib_buffer_t *first)
static clib_error_t * vhost_user_exit(vlib_main_t *vm)
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
u32 * show_dev_instance_by_real_dev_instance
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)
vhost_user_intf_t * vhost_user_interfaces
#define CLIB_PREFETCH(addr, size, type)
#define vec_free(V)
Free vector's memory (no header).
static vlib_thread_main_t * vlib_get_thread_main()
#define VLIB_MAIN_LOOP_EXIT_FUNCTION(x)
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
static_always_inline void * map_guest_mem(vhost_user_intf_t *vui, uword addr, u32 *hint)
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD
#define VLIB_CLI_COMMAND(x,...)
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
u32 * vhost_user_inactive_interfaces_index
#define hash_create(elts, value_bytes)
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Increment a combined counter.
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
static long get_huge_page_size(int fd)
u32 next_buffer
Next buffer for this linked-list of buffers.
clib_error_t * vhost_user_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 vlib_buffer_chain_append_data_with_alloc(vlib_main_t *vm, u32 free_list_index, vlib_buffer_t *first, vlib_buffer_t **last, void *data, u16 data_len)
#define VIRTQ_DESC_F_NEXT
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_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
uword * thread_registrations_by_name
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
#define foreach_vhost_user_tx_func_error
void * region_mmap_addr[VHOST_MEMORY_MAX_NREGIONS]
static clib_error_t * vhost_user_socksvr_accept_ready(unix_file_t *uf)
static clib_error_t * vhost_user_config(vlib_main_t *vm, unformat_input_t *input)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static int vhost_user_init_server_sock(const char *sock_filename, int *sockfd)
u32 input_cpu_first_index
#define VHOST_NET_VRING_IDX_RX
uword * vhost_user_interface_index_by_listener_fd
vlib_node_registration_t vhost_user_input_node
(constructor) VLIB_REGISTER_NODE (vhost_user_input_node)
#define DBG_SOCK(args...)
#define hash_get_mem(h, key)
struct clib_bihash_value offset
template key/value backing page structure
static vhost_user_main_t vhost_user_main
static void * clib_mem_alloc_aligned(uword size, uword align)
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
static u32 random_u32(u32 *seed)
32-bit random number generator
#define VHOST_NET_VRING_IDX_TX
#define VLIB_REGISTER_NODE(x,...)
u64 region_guest_addr_lo[VHOST_MEMORY_MAX_NREGIONS]
static clib_error_t * vhost_user_callfd_read_ready(unix_file_t *uf)
#define vec_foreach(var, vec)
Vector iterator.
#define foreach_vhost_user_input_func_error
#define CLIB_MEMORY_BARRIER()
#define clib_error_return(e, args...)
static void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
#define CLIB_CACHE_LINE_BYTES
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
uword * vhost_user_interface_index_by_sw_if_index
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
clib_error_t * vhost_user_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
VNET_HW_INTERFACE_CLASS(vhost_interface_class, static)
int dont_dump_vhost_user_memory