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> 52 #define VHOST_DEBUG_VQ 0 54 #define DBG_SOCK(args...) \ 56 vhost_user_main_t *_vum = &vhost_user_main; \ 61 #if VHOST_DEBUG_VQ == 1 62 #define DBG_VQ(args...) clib_warning(args); 64 #define DBG_VQ(args...) 72 #define VHOST_USER_DOWN_DISCARD_COUNT 256 78 #define VHOST_USER_RX_BUFFER_STARVATION 32 88 #define VHOST_USER_RX_COPY_THRESHOLD 64 98 #define VHOST_USER_TX_COPY_THRESHOLD (VHOST_USER_COPY_ARRAY_N - 40) 100 #define UNIX_GET_FD(unixfd_idx) ({ \ 101 typeof(unixfd_idx) __unixfd_idx = (unixfd_idx); \ 102 (__unixfd_idx != ~0) ? \ 103 pool_elt_at_index (file_main.file_pool, \ 104 __unixfd_idx)->file_descriptor : -1; }) 106 #define foreach_virtio_trace_flags \ 107 _ (SIMPLE_CHAINED, 0, "Simple descriptor chaining") \ 108 _ (SINGLE_DESC, 1, "Single descriptor packet") \ 109 _ (INDIRECT, 2, "Indirect descriptor") \ 110 _ (MAP_ERROR, 4, "Memory mapping error") 114 #define _(n,i,s) VIRTIO_TRACE_F_##n, 121 #define foreach_vhost_user_tx_func_error \ 122 _(NONE, "no error") \ 123 _(NOT_READY, "vhost vring not ready") \ 124 _(DOWN, "vhost interface is down") \ 125 _(PKT_DROP_NOBUF, "tx packet drops (no available descriptors)") \ 126 _(PKT_DROP_NOMRG, "tx packet drops (cannot merge descriptors)") \ 127 _(MMAP_FAIL, "mmap failure") \ 128 _(INDIRECT_OVERFLOW, "indirect descriptor table overflow") 132 #define _(f,s) VHOST_USER_TX_FUNC_ERROR_##f, 144 #define foreach_vhost_user_input_func_error \ 145 _(NO_ERROR, "no error") \ 146 _(NO_BUFFER, "no available buffer") \ 147 _(MMAP_FAIL, "mmap failure") \ 148 _(INDIRECT_OVERFLOW, "indirect descriptor overflows table") \ 149 _(UNDERSIZED_FRAME, "undersized ethernet frame received (< 14 bytes)") \ 150 _(FULL_RX_QUEUE, "full rx queue (possible driver tx drop)") 154 #define _(f,s) VHOST_USER_INPUT_FUNC_ERROR_##f, 172 .name =
"vhost-user",
180 u32 show_dev_instance = ~0;
186 if (show_dev_instance != ~0)
187 i = show_dev_instance;
189 s =
format (s,
"VirtualEthernet0/0/%d", i);
204 DBG_SOCK (
"renumbered vhost-user interface dev_instance %d to %d",
215 ((vui->
regions[i].guest_phys_addr +
216 vui->
regions[i].memory_size) > addr)))
222 __m128i rl, rh, al, ah, r;
223 al = _mm_set1_epi64x (addr + 1);
224 ah = _mm_set1_epi64x (addr);
227 rl = _mm_cmpgt_epi64 (al, rl);
229 rh = _mm_cmpgt_epi64 (rh, ah);
230 r = _mm_and_si128 (rl, rh);
233 rl = _mm_cmpgt_epi64 (al, rl);
235 rh = _mm_cmpgt_epi64 (rh, ah);
236 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x22);
239 rl = _mm_cmpgt_epi64 (al, rl);
241 rh = _mm_cmpgt_epi64 (rh, ah);
242 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x44);
245 rl = _mm_cmpgt_epi64 (al, rl);
247 rh = _mm_cmpgt_epi64 (rh, ah);
248 r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x88);
250 r = _mm_shuffle_epi8 (r, _mm_set_epi64x (0, 0x0e060c040a020800));
251 i = __builtin_ctzll (_mm_movemask_epi8 (r) |
260 #elif __aarch64__ && __ARM_NEON 261 uint64x2_t al, ah, rl, rh, r;
264 al = vdupq_n_u64 (addr + 1);
265 ah = vdupq_n_u64 (addr);
269 rl = vcgtq_u64 (al, rl);
271 rh = vcgtq_u64 (rh, ah);
272 r = vandq_u64 (rl, rh);
273 u32 |= (vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1);
274 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 1);
278 i = __builtin_ctzll (u32);
279 goto vhost_map_guest_mem_done;
284 rl = vcgtq_u64 (al, rl);
286 rh = vcgtq_u64 (rh, ah);
287 r = vandq_u64 (rl, rh);
288 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 2);
289 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 3);
293 i = __builtin_ctzll (u32);
294 goto vhost_map_guest_mem_done;
299 rl = vcgtq_u64 (al, rl);
301 rh = vcgtq_u64 (rh, ah);
302 r = vandq_u64 (rl, rh);
303 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 4);
304 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 5);
308 i = __builtin_ctzll (u32);
309 goto vhost_map_guest_mem_done;
314 rl = vcgtq_u64 (al, rl);
316 rh = vcgtq_u64 (rh, ah);
317 r = vandq_u64 (rl, rh);
318 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 0) & 0x1) << 6);
319 u32 |= ((vgetq_lane_u8 (vreinterpretq_u8_u64 (r), 8) & 0x1) << 7);
323 vhost_map_guest_mem_done:
324 if (i < vui->nregions)
333 if ((vui->
regions[i].guest_phys_addr <= addr) &&
343 DBG_VQ (
"failed to map guest mem addr %llx", addr);
354 if ((vui->
regions[i].userspace_addr <= addr) &&
384 ssize_t map_sz = (vui->
regions[
i].memory_size +
386 page_sz - 1) & ~(page_sz - 1);
393 (
"unmap memory region %d addr 0x%lx len 0x%lx page_sz 0x%x", i,
400 clib_warning (
"failed to unmap memory region (errno %d)",
414 u32 thread_index = 0;
431 if (thread_index == 0)
434 for (thread_index = 0;
463 vec_foreach (queue, vui->rx_queues)
465 rv = vnet_hw_interface_unassign_rx_thread (vnm, vui->hw_if_index,
468 clib_warning (
"Warning: unable to unassign interface %d, " 469 "queue %d: rc=%d", vui->hw_if_index, *queue, rv);
478 for (qid = 0; qid < VHOST_VRING_MAX_N / 2; qid++)
480 txvq = &vui->vrings[VHOST_VRING_IDX_TX (qid)];
483 if (txvq->mode == VNET_HW_INTERFACE_RX_MODE_UNKNOWN)
485 txvq->mode = VNET_HW_INTERFACE_RX_MODE_POLLING;
486 vec_add1 (vui->rx_queues, qid);
495 vnet_hw_interface_set_input_node (vnm, vui->hw_if_index,
496 vhost_user_input_node.index);
497 vec_foreach (queue, vui->rx_queues)
499 vnet_hw_interface_assign_rx_thread (vnm, vui->hw_if_index, *queue,
501 txvq = &vui->vrings[VHOST_VRING_IDX_TX (*queue)];
502 rv = vnet_hw_interface_set_rx_mode (vnm, vui->hw_if_index, *queue,
505 clib_warning (
"Warning: unable to set rx mode for interface %d, " 506 "queue %d: rc=%d", vui->hw_if_index, *queue, rv);
516 int i, found[2] = { };
522 return found[0] && found[1];
530 if (is_up != vui->
is_up)
533 is_up ?
"ready" :
"down");
562 __attribute__ ((unused))
int n;
573 __attribute__ ((unused))
int n;
602 return __sync_lock_test_and_set (vui->
vring_locks[qid], 1);
628 memset (vring, 0,
sizeof (*vring));
642 if (qid == 0 || qid == 1)
664 if (vring->
errfd != -1)
666 close (vring->
errfd);
695 #define VHOST_LOG_PAGE 0x1000 701 || !(vui->
features & (1 << FEAT_VHOST_F_LOG_ALL))))
711 DBG_SOCK (
"vhost_user_log_dirty_pages(): out of range\n");
730 #define vhost_user_log_dirty_ring(vui, vq, member) \ 731 if (PREDICT_FALSE(vq->log_used)) { \ 732 vhost_user_log_dirty_pages(vui, vq->log_guest_addr + STRUCT_OFFSET_OF(vring_used_t, member), \ 733 sizeof(vq->used->member)); \ 740 int fd, number_of_fds = 0;
742 vhost_user_msg_t msg;
747 struct cmsghdr *cmsg;
756 memset (&mh, 0,
sizeof (mh));
757 memset (control, 0,
sizeof (control));
763 iov[0].iov_base = (
void *) &msg;
768 mh.msg_control = control;
769 mh.msg_controllen =
sizeof (control);
780 DBG_SOCK (
"recvmsg returned error %d %s", errno, strerror (errno));
784 DBG_SOCK (
"n (%d) != VHOST_USER_MSG_HDR_SZ (%d)",
790 if (mh.msg_flags & MSG_CTRUNC)
796 cmsg = CMSG_FIRSTHDR (&mh);
798 if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
799 (cmsg->cmsg_type == SCM_RIGHTS) &&
800 (cmsg->cmsg_len - CMSG_LEN (0) <=
801 VHOST_MEMORY_MAX_NREGIONS *
sizeof (
int)))
803 number_of_fds = (cmsg->cmsg_len - CMSG_LEN (0)) /
sizeof (
int);
804 clib_memcpy (fds, CMSG_DATA (cmsg), number_of_fds *
sizeof (
int));
808 if ((msg.flags & 7) != 1)
810 DBG_SOCK (
"malformed message received. closing socket");
821 DBG_SOCK (
"read failed %s", strerror (errno));
824 else if (rv != msg.size)
826 DBG_SOCK (
"message too short (read %dB should be %dB)", rv, msg.size);
835 msg.u64 = (1ULL << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
836 (1ULL << FEAT_VIRTIO_NET_F_CTRL_VQ) |
837 (1ULL << FEAT_VIRTIO_F_ANY_LAYOUT) |
838 (1ULL << FEAT_VIRTIO_F_INDIRECT_DESC) |
839 (1ULL << FEAT_VHOST_F_LOG_ALL) |
840 (1ULL << FEAT_VIRTIO_NET_F_GUEST_ANNOUNCE) |
841 (1ULL << FEAT_VIRTIO_NET_F_MQ) |
842 (1ULL << FEAT_VHOST_USER_F_PROTOCOL_FEATURES) |
843 (1ULL << FEAT_VIRTIO_F_VERSION_1);
845 msg.size =
sizeof (msg.u64);
846 DBG_SOCK (
"if %d msg VHOST_USER_GET_FEATURES - reply 0x%016llx",
851 DBG_SOCK (
"if %d msg VHOST_USER_SET_FEATURES features 0x%016llx",
857 ((1 << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
858 (1ULL << FEAT_VIRTIO_F_VERSION_1)))
864 (vui->
features & (1 << FEAT_VIRTIO_F_ANY_LAYOUT)) ? 1 : 0;
876 DBG_SOCK (
"if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
879 if ((msg.memory.nregions < 1) ||
880 (msg.memory.nregions > VHOST_MEMORY_MAX_NREGIONS))
883 DBG_SOCK (
"number of mem regions must be between 1 and %i",
884 VHOST_MEMORY_MAX_NREGIONS);
889 if (msg.memory.nregions != number_of_fds)
891 DBG_SOCK (
"each memory region must have FD");
895 for (i = 0; i < msg.memory.nregions; i++)
898 sizeof (vhost_user_memory_region_t));
903 ssize_t map_sz = (vui->
regions[
i].memory_size +
905 page_sz - 1) & ~(page_sz - 1);
908 MAP_SHARED, fds[i], 0);
914 (
"map memory region %d addr 0 len 0x%lx fd %d mapped 0x%lx " 920 clib_warning (
"failed to map memory. errno is %d", errno);
931 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
934 if ((msg.state.num > 32768) ||
935 (msg.state.num == 0) ||
936 ((msg.state.num - 1) & msg.state.num))
942 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
947 DBG_SOCK (
"invalid vring index VHOST_USER_SET_VRING_ADDR:" 952 if (msg.size < sizeof (msg.addr))
954 DBG_SOCK (
"vhost message is too short (%d < %d)",
955 msg.size, sizeof (msg.addr));
959 vui->
vrings[msg.state.index].
desc = (vring_desc_t *)
961 vui->
vrings[msg.state.index].
used = (vring_used_t *)
963 vui->
vrings[msg.state.index].
avail = (vring_avail_t *)
970 DBG_SOCK (
"failed to map user memory for hw_if_index %d",
981 if (!(vui->
features & (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES)))
1003 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_CALL %d",
1006 q = (
u8) (msg.u64 & 0xFF);
1019 if (number_of_fds != 1)
1021 DBG_SOCK (
"More than one fd received !");
1026 template.file_descriptor = fds[0];
1027 template.private_data =
1036 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_KICK %d",
1039 q = (
u8) (msg.u64 & 0xFF);
1051 if (number_of_fds != 1)
1053 DBG_SOCK (
"More than one fd received !");
1058 template.file_descriptor = fds[0];
1059 template.private_data =
1074 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_ERR %d",
1077 q = (
u8) (msg.u64 & 0xFF);
1084 if (number_of_fds != 1)
1095 DBG_SOCK (
"if %d msg VHOST_USER_SET_VRING_BASE idx %d num %d",
1096 vui->
hw_if_index, msg.state.index, msg.state.num);
1104 DBG_SOCK (
"invalid vring index VHOST_USER_GET_VRING_BASE:" 1115 msg.size =
sizeof (msg.state);
1119 DBG_SOCK (
"if %d msg VHOST_USER_GET_VRING_BASE idx %d num %d",
1120 vui->
hw_if_index, msg.state.index, msg.state.num);
1132 if (msg.size != sizeof (msg.log))
1135 (
"invalid msg size for VHOST_USER_SET_LOG_BASE: %d instead of %d",
1136 msg.size, sizeof (msg.log));
1144 (
"VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but VHOST_USER_SET_LOG_BASE received");
1152 (msg.log.size + msg.log.offset + page_sz - 1) & ~(page_sz - 1);
1154 vui->
log_base_addr = mmap (0, map_sz, PROT_READ | PROT_WRITE,
1158 (
"map log region addr 0 len 0x%lx off 0x%lx fd %d mapped 0x%lx",
1163 clib_warning (
"failed to map memory. errno is %d", errno);
1171 msg.size =
sizeof (msg.u64);
1185 msg.size =
sizeof (msg.u64);
1187 (
"if %d msg VHOST_USER_GET_PROTOCOL_FEATURES - reply 0x%016llx",
1193 (
"if %d msg VHOST_USER_SET_PROTOCOL_FEATURES features 0x%016llx",
1203 msg.size =
sizeof (msg.u64);
1204 DBG_SOCK (
"if %d msg VHOST_USER_GET_QUEUE_NUM - reply %d",
1209 DBG_SOCK (
"if %d VHOST_USER_SET_VRING_ENABLE: %s queue %d",
1210 vui->
hw_if_index, msg.state.num ?
"enable" :
"disable",
1214 DBG_SOCK (
"invalid vring index VHOST_USER_SET_VRING_ENABLE:" 1223 DBG_SOCK (
"unknown vhost-user message %d received. closing socket",
1235 DBG_SOCK (
"could not send message response");
1270 int client_fd, client_len;
1271 struct sockaddr_un client;
1278 client_len =
sizeof (client);
1280 (
struct sockaddr *) &client,
1281 (socklen_t *) & client_len);
1288 DBG_SOCK (
"Close client socket for vhost interface %d, fd %d",
1293 DBG_SOCK (
"New client socket for vhost interface %d, fd %d",
1297 template.file_descriptor = client_fd;
1356 if (t->virtio_ring_flags & (1 << VIRTIO_TRACE_F_##n)) \ 1357 s = format (s, "%U %s %s\n", format_white_space, indent, #n, st); 1360 s =
format (s,
"%U virtio_net_hdr first_desc_len %u\n",
1363 s =
format (s,
"%U flags 0x%02x gso_type %u\n",
1365 t->
hdr.hdr.flags, t->
hdr.hdr.gso_type);
1368 s =
format (s,
"%U num_buff %u",
1382 vring_desc_t *hdr_desc = 0;
1383 virtio_net_hdr_mrg_rxbuf_t *hdr;
1386 memset (t, 0,
sizeof (*t));
1390 hdr_desc = &txvq->
desc[desc_current];
1401 if (!(txvq->
desc[desc_current].flags & VIRTQ_DESC_F_NEXT) &&
1402 !(txvq->
desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT))
1409 if (!hdr_desc || !(hdr =
map_guest_mem (vui, hdr_desc->addr, &hint)))
1416 memcpy (&t->
hdr, hdr, len > hdr_desc->len ? hdr_desc->len : len);
1428 rv = write (fd, &x,
sizeof (x));
1432 (
"Error: Could not write to unix socket for callfd %d", fd);
1442 u16 copy_len,
u32 * map_hint)
1444 void *src0, *src1, *src2, *src3;
1467 clib_memcpy ((
void *) cpy[0].dst, src0, cpy[0].len);
1468 clib_memcpy ((
void *) cpy[1].dst, src1, cpy[1].len);
1498 u32 discarded_packets = 0;
1500 while (discarded_packets != discard_max)
1505 u16 desc_chain_head =
1514 discarded_packets++;
1521 return discarded_packets;
1534 b_current->
flags = 0;
1535 while (b_current != b_head)
1541 b_current->
flags = 0;
1554 u16 n_rx_packets = 0;
1557 u32 n_left_to_next, *to_next;
1590 txvq->
used->flags = 0;
1626 VHOST_USER_INPUT_FUNC_ERROR_FULL_RX_QUEUE, 1);
1663 interface_main.sw_if_counters +
1669 VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER, flush);
1677 while (n_left > 0 && n_left_to_next > 0)
1682 u32 desc_data_offset;
1683 vring_desc_t *desc_table = txvq->
desc;
1701 to_next[0] = bi_current;
1707 cpus[thread_index].rx_buffers)
1708 [vum->
cpus[thread_index].
1709 rx_buffers_len - 1], LOAD);
1721 b_head->
flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
1746 VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1760 desc_data_offset = desc_table[desc_current].len;
1766 if (desc_data_offset == desc_table[desc_current].len)
1771 desc_current = desc_table[desc_current].next;
1772 desc_data_offset = 0;
1812 b_current->
flags |= VLIB_BUFFER_NEXT_PRESENT;
1813 bi_current = bi_next;
1821 desc_table[desc_current].
len - desc_data_offset;
1823 cpy->
len = (cpy->
len > desc_data_l) ? desc_data_l : cpy->
len;
1826 cpy->
src = desc_table[desc_current].addr + desc_data_offset;
1828 desc_data_offset += cpy->
len;
1860 u32 bi = to_next[-1];
1862 to_next, n_left_to_next,
1877 copy_len, &map_hint)))
1880 VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1897 copy_len, &map_hint)))
1900 VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL, 1);
1926 return n_rx_packets;
1934 uword n_rx_packets = 0;
1943 (node->
state == VLIB_NODE_STATE_POLLING))
1952 return n_rx_packets;
1959 .name =
"vhost-user-input",
1960 .sibling_of =
"device-input",
1963 .state = VLIB_NODE_STATE_DISABLED,
1984 vring_desc_t *hdr_desc = 0;
1987 memset (t, 0,
sizeof (*t));
1991 hdr_desc = &rxvq->
desc[desc_current];
2002 if (!(rxvq->
desc[desc_current].flags & VIRTQ_DESC_F_NEXT) &&
2003 !(rxvq->
desc[desc_current].flags & VIRTQ_DESC_F_INDIRECT))
2013 u16 copy_len,
u32 * map_hint)
2015 void *dst0, *dst1, *dst2, *dst3;
2037 clib_memcpy (dst0, (
void *) cpy[0].src, cpy[0].len);
2038 clib_memcpy (dst1, (
void *) cpy[1].src, cpy[1].len);
2080 error = VHOST_USER_TX_FUNC_ERROR_DOWN;
2086 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
2092 (vui->per_cpu_tx_qid, thread_index));
2093 rxvq = &vui->vrings[qid];
2098 error = VHOST_USER_TX_FUNC_ERROR_NONE;
2104 u16 desc_head, desc_index, desc_len;
2105 vring_desc_t *desc_table;
2106 uword buffer_map_addr;
2121 vui, qid / 2, b0, rxvq);
2126 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
2130 desc_table = rxvq->
desc;
2131 desc_head = desc_index =
2139 (rxvq->
desc[desc_head].len < sizeof (vring_desc_t)))
2141 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
2149 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
2155 desc_len = vui->virtio_net_hdr_sz;
2156 buffer_map_addr = desc_table[desc_index].addr;
2157 buffer_len = desc_table[desc_index].len;
2161 virtio_net_hdr_mrg_rxbuf_t *hdr =
2165 hdr->hdr.gso_type = 0;
2166 hdr->num_buffers = 1;
2171 cpy->
len = vui->virtio_net_hdr_sz;
2172 cpy->
dst = buffer_map_addr;
2176 buffer_map_addr += vui->virtio_net_hdr_sz;
2177 buffer_len -= vui->virtio_net_hdr_sz;
2182 if (buffer_len == 0)
2187 desc_index = desc_table[desc_index].next;
2188 buffer_map_addr = desc_table[desc_index].addr;
2189 buffer_len = desc_table[desc_index].len;
2191 else if (vui->virtio_net_hdr_sz == 12)
2193 virtio_net_hdr_mrg_rxbuf_t *hdr =
2216 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
2220 desc_table = rxvq->
desc;
2221 desc_head = desc_index =
2224 (rxvq->
desc[desc_head].flags & VIRTQ_DESC_F_INDIRECT))
2229 (rxvq->
desc[desc_head].len < sizeof (vring_desc_t)))
2231 error = VHOST_USER_TX_FUNC_ERROR_INDIRECT_OVERFLOW;
2237 rxvq->
desc[desc_index].addr,
2240 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
2245 buffer_map_addr = desc_table[desc_index].addr;
2246 buffer_len = desc_table[desc_index].len;
2250 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOMRG;
2258 cpy->
len = bytes_left;
2259 cpy->
len = (cpy->
len > buffer_len) ? buffer_len : cpy->
len;
2260 cpy->
dst = buffer_map_addr;
2264 bytes_left -= cpy->
len;
2265 buffer_len -= cpy->
len;
2266 buffer_map_addr += cpy->
len;
2267 desc_len += cpy->
len;
2276 (current_b0->
flags & VLIB_BUFFER_NEXT_PRESENT))
2313 copy_len, &map_hint)))
2316 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
2332 copy_len, &map_hint)))
2335 VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL, 1);
2354 if (n_left && (error == VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF) && retry)
2373 if (
PREDICT_FALSE (n_left && error != VHOST_USER_TX_FUNC_ERROR_NONE))
2379 thread_index, vui->sw_if_index, n_left);
2391 f64 timeout = 3153600000.0 ;
2392 uword event_type, *event_data = 0;
2395 f64 now, poll_time_remaining;
2401 poll_time_remaining =
2410 timeout = poll_time_remaining;
2431 next_timeout = timeout;
2432 vec_foreach (queue, vui->rx_queues)
2434 vhost_user_vring_t *rxvq =
2435 &vui->vrings[VHOST_VRING_IDX_RX (*queue)];
2436 vhost_user_vring_t *txvq =
2437 &vui->vrings[VHOST_VRING_IDX_TX (*queue)];
2439 if (txvq->n_since_last_int)
2441 if (now >= txvq->int_deadline)
2442 vhost_user_send_call (vm, txvq);
2444 next_timeout = txvq->int_deadline - now;
2447 if (rxvq->n_since_last_int)
2449 if (now >= rxvq->int_deadline)
2450 vhost_user_send_call (vm, rxvq);
2452 next_timeout = rxvq->int_deadline - now;
2455 if ((next_timeout < timeout) && (next_timeout > 0.0))
2456 timeout = next_timeout;
2463 clib_warning (
"BUG: unhandled event type %d", event_type);
2470 timeout = 3153600000.0;
2479 .name =
"vhost-user-send-interrupt-process",
2535 txvq->
used->flags = 0;
2538 clib_warning (
"BUG: unhandled mode %d changed for if %d queue %d", mode,
2558 if (is_up && vui->
is_up)
2567 .name =
"vhost-user",
2588 struct sockaddr_un sun;
2591 f64 timeout = 3153600000.0 ;
2592 uword *event_data = 0;
2595 sun.sun_family = AF_UNIX;
2610 if (vui->unix_server_index == ~0) {
2611 if (vui->clib_file_index == ~0)
2614 ((sockfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0))
2620 if (!vui->sock_errno || (vui->sock_errno != errno))
2623 (
"Error: Could not open unix socket for %s",
2624 vui->sock_filename);
2625 vui->sock_errno = errno;
2631 strncpy (sun.sun_path, (char *) vui->sock_filename,
2632 sizeof (sun.sun_path) - 1);
2635 if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
2636 clib_unix_warning (
"fcntl");
2638 if (connect (sockfd, (struct sockaddr *) &sun,
2639 sizeof (struct sockaddr_un)) == 0)
2642 if (fcntl(sockfd, F_SETFL, 0) < 0)
2643 clib_unix_warning (
"fcntl2");
2645 vui->sock_errno = 0;
2646 template.file_descriptor = sockfd;
2647 template.private_data =
2648 vui - vhost_user_main.vhost_user_interfaces;
2649 vui->clib_file_index = clib_file_add (&file_main, &template);
2656 vui->sock_errno = errno;
2663 socklen_t len = sizeof (error);
2664 int fd = UNIX_GET_FD(vui->clib_file_index);
2666 getsockopt (fd, SOL_SOCKET, SO_ERROR, &error, &len);
2670 DBG_SOCK (
"getsockopt returned %d", retval);
2671 vhost_user_if_disconnect (vui);
2683 .function = vhost_user_process,
2685 .name =
"vhost-user-process",
2733 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
2735 DBG_SOCK (
"Deleting vhost-user interface %s (instance %d)",
2789 vhost_user_delete_if (vnm, vm, vui->sw_if_index);
2805 struct sockaddr_un un = { };
2808 if ((fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
2809 return VNET_API_ERROR_SYSCALL_ERROR_1;
2811 un.sun_family = AF_UNIX;
2812 strncpy ((
char *) un.sun_path, (
char *) sock_filename,
2813 sizeof (un.sun_path) - 1);
2816 unlink ((
char *) sock_filename);
2818 if (bind (fd, (
struct sockaddr *) &un,
sizeof (un)) == -1)
2820 rv = VNET_API_ERROR_SYSCALL_ERROR_2;
2824 if (listen (fd, 1) == -1)
2826 rv = VNET_API_ERROR_SYSCALL_ERROR_3;
2864 vhost_user_dev_class.index,
2883 const char *sock_filename,
2884 u64 feature_mask,
u32 * sw_if_index)
2893 if (server_sock_fd != -1)
2897 template.file_descriptor = server_sock_fd;
2941 const char *sock_filename,
2945 u8 renumber,
u32 custom_dev_instance,
u8 * hwaddr)
2950 int server_sock_fd = -1;
2954 if (sock_filename ==
NULL || !(strlen (sock_filename) > 0))
2956 return VNET_API_ERROR_INVALID_ARGUMENT;
2967 return VNET_API_ERROR_IF_ALREADY_EXISTS;
2983 feature_mask, &sw_if_idx);
2989 *sw_if_index = sw_if_idx;
2999 const char *sock_filename,
3002 u64 feature_mask,
u8 renumber,
u32 custom_dev_instance)
3007 int server_sock_fd = -1;
3014 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
3016 if (sock_filename ==
NULL || !(strlen (sock_filename) > 0))
3017 return VNET_API_ERROR_INVALID_ARGUMENT;
3026 if (if_index && (*if_index != vui->
if_index))
3027 return VNET_API_ERROR_IF_ALREADY_EXISTS;
3032 &server_sock_fd)) != 0)
3037 sock_filename, feature_mask, &sw_if_idx);
3054 u8 *sock_filename =
NULL;
3057 u64 feature_mask = (
u64) ~ (0ULL);
3059 u32 custom_dev_instance = ~0;
3070 if (
unformat (line_input,
"socket %s", &sock_filename))
3072 else if (
unformat (line_input,
"server"))
3074 else if (
unformat (line_input,
"feature-mask 0x%llx", &feature_mask))
3080 else if (
unformat (line_input,
"renumber %d", &custom_dev_instance))
3096 is_server, &sw_if_index, feature_mask,
3097 renumber, custom_dev_instance, hw)))
3119 u32 sw_if_index = ~0;
3129 if (
unformat (line_input,
"sw_if_index %d", &sw_if_index))
3169 u32 *hw_if_indices = 0;
3181 for (i = 0; i <
vec_len (hw_if_indices); i++)
3198 strncpy ((
char *) vuid->
if_name, (
char *) s,
3206 *out_vuids = r_vuids;
3220 u32 hw_if_index, *hw_if_indices = 0;
3231 struct feat_struct *feat_entry;
3233 static struct feat_struct feat_array[] = {
3234 #define _(s,b) { .str = #s, .bit = b, }, 3240 #define foreach_protocol_feature \ 3241 _(VHOST_USER_PROTOCOL_F_MQ) \ 3242 _(VHOST_USER_PROTOCOL_F_LOG_SHMFD) 3244 static struct feat_struct proto_feat_array[] = {
3245 #define _(s) { .str = #s, .bit = s}, 3263 vec_add1 (hw_if_indices, hw_if_index);
3274 if (
vec_len (hw_if_indices) == 0)
3283 vlib_cli_output (vm,
" number of rx virtqueues in interrupt mode: %d",
3286 for (i = 0; i <
vec_len (hw_if_indices); i++)
3291 hi->
name, hw_if_indices[i]);
3294 " features mask (0x%llx): \n" 3295 " features (0x%llx): \n",
3299 feat_entry = (
struct feat_struct *) &feat_array;
3300 while (feat_entry->str)
3302 if (vui->
features & (1ULL << feat_entry->bit))
3310 feat_entry = (
struct feat_struct *) &proto_feat_array;
3311 while (feat_entry->str)
3359 " region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr\n");
3361 " ====== ===== ================== ================== ================== ================== ==================\n");
3363 for (j = 0; j < vui->
nregions; j++)
3366 " %d %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
3368 vui->
regions[j].guest_phys_addr,
3370 vui->
regions[j].userspace_addr,
3380 (q & 1) ?
"RX" :
"TX",
3384 " qsz %d last_avail_idx %d last_used_idx %d\n",
3391 " avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
3406 " id addr len flags next user_addr\n");
3408 " ===== ================== ===== ====== ===== ==================\n");
3413 " %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n",
3492 .path =
"create vhost-user",
3493 .short_help =
"create vhost-user socket <socket-filename> [server] " 3494 "[feature-mask <hex>] [hwaddr <mac-addr>] [renumber <dev_instance>] ",
3513 .path =
"delete vhost-user",
3514 .short_help =
"delete vhost-user {<interface> | sw_if_index <sw_idx>}",
3653 .path =
"show vhost-user",
3654 .short_help =
"show vhost-user [<interface> [<interface> [..]]] [descriptors]",
3688 else if (
unformat (line_input,
"off"))
3711 .path =
"debug vhost-user",
3712 .short_help =
"debug vhost-user <on | off>",
3728 else if (
unformat (input,
"dont-dump-memory"))
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) ...
static clib_error_t * vhost_user_init(vlib_main_t *vm)
static void vhost_user_vring_close(vhost_user_intf_t *vui, u32 qid)
static void vnet_device_increment_rx_packets(u32 thread_index, u64 count)
static void vhost_user_if_disconnect(vhost_user_intf_t *vui)
#define vec_foreach_index(var, v)
Iterate over vector indices.
static void clib_file_del(clib_file_main_t *um, clib_file_t *f)
#define VRING_AVAIL_F_NO_INTERRUPT
u32 virtio_ring_flags
The device index.
virtio_net_hdr_mrg_rxbuf_t hdr
Length of the first data descriptor.
static uword random_default_seed(void)
Default random seed (unix/linux user-mode)
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...
#define clib_smp_swap(addr, new)
vhost_cpu_t * cpus
Per-CPU data for vhost-user.
static void vhost_user_create_ethernet(vnet_main_t *vnm, vlib_main_t *vm, vhost_user_intf_t *vui, u8 *hwaddress)
Create ethernet interface for vhost user interface.
#define VHOST_USER_DOWN_DISCARD_COUNT
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
u8 runtime_data[0]
Function dependent node-runtime data.
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
#define VHOST_VRING_IDX_TX(qid)
vnet_main_t * vnet_get_main(void)
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
void vhost_user_rx_trace(vhost_trace_t *t, vhost_user_intf_t *vui, u16 qid, vlib_buffer_t *b, vhost_user_vring_t *txvq)
u64 region_guest_addr_hi[VHOST_MEMORY_MAX_NREGIONS]
vnet_interface_main_t interface_main
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
static f64 vlib_time_now(vlib_main_t *vm)
#define foreach_virtio_trace_flags
vhost_copy_t copy[VHOST_USER_COPY_ARRAY_N]
static void vhost_user_term_if(vhost_user_intf_t *vui)
Disables and reset interface structure.
#define VLIB_BUFFER_PRE_DATA_SIZE
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 VHOST_USER_EVENT_START_TIMER
#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_always_inline u32 vhost_user_input_copy(vhost_user_intf_t *vui, vhost_copy_t *cpy, u16 copy_len, u32 *map_hint)
#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 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)
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
unformat_function_t unformat_vnet_sw_interface
#define VNET_HW_INTERFACE_FLAG_LINK_UP
static char * vhost_user_input_func_error_strings[]
static char * vhost_user_tx_func_error_strings[]
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
format_function_t format_vnet_sw_if_index_name
vhost_trace_t * current_trace
static uword vlib_process_suspend_time_is_zero(f64 dt)
Returns TRUE if a process suspend time is less than 10us.
#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)
clib_file_function_t * read_function
#define vlib_worker_thread_barrier_sync(X)
static void vhost_user_vui_init(vnet_main_t *vnm, vhost_user_intf_t *vui, int server_sock_fd, const char *sock_filename, u64 feature_mask, u32 *sw_if_index)
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)
static clib_error_t * vhost_user_socket_error(clib_file_t *uf)
#define VHOST_VRING_F_LOG
vnet_hw_interface_rx_mode
VNET_DEVICE_CLASS(vhost_user_dev_class, static)
static clib_error_t * vhost_user_socket_read(clib_file_t *uf)
static u8 * format_vhost_user_interface_name(u8 *s, va_list *args)
#define static_always_inline
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#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...
vlib_combined_counter_main_t * combined_sw_if_counters
static_always_inline void vnet_device_input_set_interrupt_pending(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
#define foreach_protocol_feature
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
clib_file_main_t file_main
#define VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE
vhost_user_tx_func_error_t
static void unmap_all_mem_regions(vhost_user_intf_t *vui)
static void vhost_user_set_interrupt_pending(vhost_user_intf_t *vui, u32 ifq)
vhost_user_input_func_error_t
#define vlib_call_init_function(vm, x)
#define VHOST_USER_TX_COPY_THRESHOLD
static uword pointer_to_uword(const void *p)
#define UNIX_GET_FD(unixfd_idx)
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
static int vhost_user_init_server_sock(const char *sock_filename, int *sock_fd)
Open server unix socket on specified sock_filename.
static uword vhost_user_send_interrupt_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
VLIB_DEVICE_TX_FUNCTION_MULTIARCH(vhost_user_dev_class, vhost_user_tx)
#define VHOST_USER_EVENT_STOP_TIMER
static void vhost_user_vring_unlock(vhost_user_intf_t *vui, u32 qid)
Unlock the vring lock.
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static_always_inline uword vnet_get_device_input_thread_index(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id)
u16 state
Input node state.
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)
u32 random
Pseudo random iterator.
static_always_inline void vhost_user_log_dirty_pages(vhost_user_intf_t *vui, u64 addr, u64 len)
uword mhash_set_mem(mhash_t *h, void *key, uword *new_value, uword *old_value)
#define VIRTQ_DESC_F_INDIRECT
#define clib_error_return_unix(e, args...)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
int vnet_hw_interface_get_rx_mode(vnet_main_t *vnm, u32 hw_if_index, u16 queue_id, vnet_hw_interface_rx_mode *mode)
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
#define pool_put(P, E)
Free an object E in pool P.
format_function_t format_vnet_hw_interface_rx_mode
void vhost_user_tx_trace(vhost_trace_t *t, vhost_user_intf_t *vui, u16 qid, vlib_buffer_t *b, vhost_user_vring_t *rxvq)
#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)
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)
#define VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE
u32 node_index
Node index.
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).
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 clib_error_t * vhost_user_exit(vlib_main_t *vm)
static void vhost_user_tx_thread_placement(vhost_user_intf_t *vui)
static void vhost_user_vring_init(vhost_user_intf_t *vui, u32 qid)
u8 * format_ethernet_header_with_length(u8 *s, va_list *args)
static vlib_node_registration_t vhost_user_send_interrupt_node
(constructor) VLIB_REGISTER_NODE (vhost_user_send_interrupt_node)
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)
u16 device_index
The interface queue index (Not the virtio vring idx)
vhost_user_intf_t * vhost_user_interfaces
#define VLIB_REGISTER_NODE(x,...)
static void mhash_init_c_string(mhash_t *h, uword n_value_bytes)
static_always_inline uword vlib_get_thread_index(void)
#define CLIB_PREFETCH(addr, size, type)
static_always_inline void vhost_user_log_dirty_pages_2(vhost_user_intf_t *vui, u64 addr, u64 len, u8 is_host_address)
#define vec_free(V)
Free vector's memory (no header).
static int vhost_user_vring_try_lock(vhost_user_intf_t *vui, u32 qid)
Try once to lock the vring.
#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_warning(format, args...)
#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)
clib_error_t * debug_vhost_user_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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 uword vhost_user_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
u16 first_desc_len
Runtime queue flags.
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD
#define VLIB_BUFFER_DATA_SIZE
static void vhost_user_input_rewind_buffers(vlib_main_t *vm, vhost_cpu_t *cpu, vlib_buffer_t *b_head)
#define VLIB_CLI_COMMAND(x,...)
#define VHOST_USER_VRING_NOFD_MASK
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
u32 rx_buffers[VHOST_USER_RX_BUFFERS_N]
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
#define VHOST_USER_RX_BUFFER_STARVATION
static uword * mhash_get(mhash_t *h, const void *key)
static uword clib_file_add(clib_file_main_t *um, clib_file_t *template)
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)
static void clib_mem_free(void *p)
#define VIRTQ_DESC_F_NEXT
volatile u32 * vring_locks[VHOST_VRING_MAX_N]
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)
mhash_t if_index_by_sock_name
#define clib_error_report(e)
static void * vlib_frame_args(vlib_frame_t *f)
Get pointer to frame scalar data.
static clib_error_t * vhost_user_kickfd_read_ready(clib_file_t *uf)
static u8 * format_vhost_trace(u8 *s, va_list *va)
#define VHOST_USER_RX_COPY_THRESHOLD
static void vhost_user_vring_lock(vhost_user_intf_t *vui, u32 qid)
Spin until the vring is successfully locked.
static vlib_main_t * vlib_get_main(void)
static void vhost_user_rx_thread_placement()
Unassign existing interface/queue to thread mappings and re-assign new interface/queue to thread mapp...
static u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, vlib_buffer_free_list_index_t index)
Allocate buffers from specific freelist into supplied array.
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
static void vhost_user_update_iface_state(vhost_user_intf_t *vui)
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
struct _vlib_node_registration vlib_node_registration_t
#define foreach_vhost_user_tx_func_error
void * region_mmap_addr[VHOST_MEMORY_MAX_NREGIONS]
static u32 vhost_user_if_input(vlib_main_t *vm, vhost_user_main_t *vum, vhost_user_intf_t *vui, u16 qid, vlib_node_runtime_t *node, vnet_hw_interface_rx_mode mode)
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)
#define VRING_USED_F_NO_NOTIFY
#define VHOST_USER_RX_BUFFERS_N
static clib_error_t * vhost_user_socksvr_accept_ready(clib_file_t *uf)
int vhost_user_intf_ready(vhost_user_intf_t *vui)
Returns whether at least one TX and one RX vring are enabled.
vhost_user_vring_t vrings[VHOST_VRING_MAX_N]
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
#define VHOST_VRING_MAX_N
#define clib_unix_warning(format, args...)
vlib_node_registration_t vhost_user_input_node
(constructor) VLIB_REGISTER_NODE (vhost_user_input_node)
#define DBG_SOCK(args...)
u32 vhost_user_rx_discard_packet(vlib_main_t *vm, vhost_user_intf_t *vui, vhost_user_vring_t *txvq, u32 discard_max)
Try to discard packets from the tx ring (VPP RX path).
static vhost_user_main_t vhost_user_main
static void * clib_mem_alloc_aligned(uword size, uword align)
static u32 random_u32(u32 *seed)
32-bit random number generator
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
static_always_inline void vnet_feature_start_device_input_x1(u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
static vlib_thread_main_t * vlib_get_thread_main()
u64 region_guest_addr_lo[VHOST_MEMORY_MAX_NREGIONS]
#define vec_foreach(var, vec)
Vector iterator.
#define foreach_vhost_user_input_func_error
u16 flags
Copy of main node flags.
#define CLIB_MEMORY_BARRIER()
virtio_net_hdr_mrg_rxbuf_t tx_headers[VLIB_FRAME_SIZE]
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_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static_always_inline u32 vhost_user_tx_copy(vhost_user_intf_t *vui, vhost_copy_t *cpy, u16 copy_len, u32 *map_hint)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static clib_error_t * vhost_user_interface_rx_mode_change(vnet_main_t *vnm, u32 hw_if_index, u32 qid, vnet_hw_interface_rx_mode mode)
#define VHOST_USER_PROTOCOL_F_MQ
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)
#define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE
static clib_error_t * vhost_user_callfd_read_ready(clib_file_t *uf)
int dont_dump_vhost_user_memory
#define VHOST_VRING_IDX_RX(qid)