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> 42 #define VHOST_USER_DEBUG_SOCKET 0 43 #define VHOST_USER_DEBUG_VQ 0 47 #define VHOST_USER_COPY_TX_HDR 0 49 #if VHOST_USER_DEBUG_SOCKET == 1 50 #define DBG_SOCK(args...) clib_warning(args); 52 #define DBG_SOCK(args...) 55 #if VHOST_USER_DEBUG_VQ == 1 56 #define DBG_VQ(args...) clib_warning(args); 58 #define DBG_VQ(args...) 63 #define foreach_vhost_user_tx_func_error \ 65 _(NOT_READY, "vhost user state error") \ 66 _(PKT_DROP_NOBUF, "tx packet drops (no available descriptors)") \ 67 _(MMAP_FAIL, "mmap failure") 70 #define _(f,s) VHOST_USER_TX_FUNC_ERROR_##f, 82 #define foreach_vhost_user_input_func_error \ 83 _(NO_ERROR, "no error") \ 84 _(NO_BUFFER, "no available buffer") \ 85 _(MMAP_FAIL, "mmap failure") \ 86 _(UNDERSIZED_FRAME, "undersized ethernet frame received (< 14 bytes)") 89 #define _(f,s) VHOST_USER_INPUT_FUNC_ERROR_##f, 106 .name =
"vhost-user",
112 u32 show_dev_instance = ~0;
118 if (show_dev_instance != ~0)
119 i = show_dev_instance;
121 s =
format (s,
"VirtualEthernet0/0/%d", i);
126 u32 new_dev_instance)
136 DBG_SOCK(
"renumbered vhost-user interface dev_instance %d to %d",
152 DBG_VQ(
"failed to map guest mem addr %llx", addr);
188 DBG_SOCK(
"unmap memory region %d addr 0x%lx len 0x%lx page_sz 0x%x", i,
194 clib_warning(
"failed to unmap memory region (errno %d)", errno);
205 __attribute__((unused))
int n;
241 #define VHOST_LOG_PAGE 0x1000 246 || !(vui->
features & (1 << FEAT_VHOST_F_LOG_ALL)))) {
250 DBG_SOCK(
"vhost_user_log_dirty_pages(): out of range\n");
262 #define vhost_user_log_dirty_ring(vui, vq, member) \ 263 if (PREDICT_FALSE(vq->log_used)) { \ 264 vhost_user_log_dirty_pages(vui, vq->log_guest_addr + offsetof(vring_used_t, member), \ 265 sizeof(vq->used->member)); \ 271 int fd, number_of_fds = 0;
273 vhost_user_msg_t msg;
278 struct cmsghdr *cmsg;
284 p =
hash_get (vum->vhost_user_interface_index_by_sock_fd,
287 DBG_SOCK (
"FD %d doesn't belong to any interface",
296 memset(&mh, 0,
sizeof(mh));
297 memset(control, 0,
sizeof(control));
300 iov[0].iov_base = (
void *) &msg;
305 mh.msg_control = control;
306 mh.msg_controllen =
sizeof(control);
313 if (mh.msg_flags & MSG_CTRUNC) {
317 cmsg = CMSG_FIRSTHDR(&mh);
319 if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) &&
320 (cmsg->cmsg_type == SCM_RIGHTS) &&
322 number_of_fds = (cmsg->cmsg_len - CMSG_LEN(0)) /
sizeof(
int);
323 clib_memcpy(fds, CMSG_DATA(cmsg), number_of_fds *
sizeof(
int));
327 if ((msg.flags & 7) != 1) {
328 DBG_SOCK(
"malformed message received. closing socket");
333 int rv __attribute__((unused));
338 switch (msg.request) {
340 DBG_SOCK(
"if %d msg VHOST_USER_GET_FEATURES",
344 msg.u64 = (1 << FEAT_VIRTIO_NET_F_MRG_RXBUF) |
345 (1 << FEAT_VIRTIO_F_ANY_LAYOUT) |
346 (1 << FEAT_VHOST_F_LOG_ALL) |
347 (1 << FEAT_VIRTIO_NET_F_GUEST_ANNOUNCE) |
348 (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES);
351 msg.size =
sizeof(msg.u64);
355 DBG_SOCK(
"if %d msg VHOST_USER_SET_FEATURES features 0x%016llx",
360 if (vui->
features & (1 << FEAT_VIRTIO_NET_F_MRG_RXBUF))
371 for (q = 0; q < 2; q++) {
384 DBG_SOCK(
"if %d msg VHOST_USER_SET_MEM_TABLE nregions %d",
387 if ((msg.memory.nregions < 1) ||
390 DBG_SOCK(
"number of mem regions must be between 1 and %i",
396 if (msg.memory.nregions != number_of_fds) {
397 DBG_SOCK(
"each memory region must have FD");
401 for(i=0; i < msg.memory.nregions; i++) {
412 MAP_SHARED, fds[i], 0);
414 DBG_SOCK(
"map memory region %d addr 0 len 0x%lx fd %d mapped 0x%lx " 418 clib_warning(
"failed to map memory. errno is %d", errno);
424 vui->
nregions = msg.memory.nregions;
428 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_NUM idx %d num %d",
431 if ((msg.state.num > 32768) ||
432 (msg.state.num == 0) ||
435 vui->
vrings[msg.state.index].
qsz = msg.state.num;
439 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_ADDR idx %d",
442 vui->
vrings[msg.state.index].
desc = (vring_desc_t *)
444 vui->
vrings[msg.state.index].
used = (vring_used_t *)
446 vui->
vrings[msg.state.index].
avail = (vring_avail_t *)
452 DBG_SOCK(
"failed to map user memory for hw_if_index %d",
464 if (!(vui->
features & (1 << FEAT_VHOST_USER_F_PROTOCOL_FEATURES))) {
472 vui->
vrings[msg.state.index].
used->flags |= 1;
476 DBG_SOCK(
"if %d msg VHOST_USER_SET_OWNER",
481 DBG_SOCK(
"if %d msg VHOST_USER_RESET_OWNER",
486 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_CALL u64 %d",
489 q = (
u8) (msg.u64 & 0xFF);
491 if (!(msg.u64 & 0x100))
493 if (number_of_fds != 1)
504 template.file_descriptor = fds[0];
512 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_KICK u64 %d",
515 q = (
u8) (msg.u64 & 0xFF);
517 if (!(msg.u64 & 0x100))
519 if (number_of_fds != 1)
529 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_ERR u64 %d",
532 q = (
u8) (msg.u64 & 0xFF);
534 if (!(msg.u64 & 0x100))
536 if (number_of_fds != 1)
548 DBG_SOCK(
"if %d msg VHOST_USER_SET_VRING_BASE idx %d num %d",
555 DBG_SOCK(
"if %d msg VHOST_USER_GET_VRING_BASE idx %d num %d",
563 msg.size =
sizeof(msg.state);
567 DBG_SOCK(
"if %d msg VHOST_USER_NONE",
574 DBG_SOCK(
"if %d msg VHOST_USER_SET_LOG_BASE",
577 if (msg.size !=
sizeof(msg.log)) {
578 DBG_SOCK(
"invalid msg size for VHOST_USER_SET_LOG_BASE: %d instead of %d",
579 msg.size,
sizeof(msg.log));
584 DBG_SOCK(
"VHOST_USER_PROTOCOL_F_LOG_SHMFD not set but VHOST_USER_SET_LOG_BASE received");
591 ssize_t map_sz = (msg.log.size + msg.log.offset + page_sz) & ~(page_sz - 1);
596 DBG_SOCK(
"map log region addr 0 len 0x%lx off 0x%lx fd %d mapped 0x%lx",
600 clib_warning(
"failed to map memory. errno is %d", errno);
608 msg.size =
sizeof(msg.u64);
614 DBG_SOCK(
"if %d msg VHOST_USER_SET_LOG_FD",
624 msg.size =
sizeof(msg.u64);
628 DBG_SOCK(
"if %d msg VHOST_USER_SET_PROTOCOL_FEATURES features 0x%lx",
636 DBG_SOCK(
"if %d VHOST_USER_SET_VRING_ENABLE, enable: %d",
642 DBG_SOCK(
"unknown vhost-user message %d received. closing socket",
683 DBG_SOCK (
"fd %d doesn't belong to any interface",
696 int client_fd, client_len;
697 struct sockaddr_un client;
706 DBG_SOCK (
"fd %d doesn't belong to any interface",
713 client_len =
sizeof(client);
715 (
struct sockaddr *)&client,
716 (socklen_t *)&client_len);
723 template.file_descriptor = client_fd;
777 #if VHOST_USER_COPY_TX_HDR == 1 778 virtio_net_hdr_t hdr;
794 #if VHOST_USER_COPY_TX_HDR == 1 798 s =
format (s,
"%U virtqueue %d",
802 #if VHOST_USER_COPY_TX_HDR == 1 803 s =
format (s,
"\n%Uvirtio_net_hdr flags 0x%02x gso_type %u hdr_len %u",
840 #if VHOST_USER_COPY_TX_HDR == 1 852 int rv __attribute__((unused));
854 rv = write(vq->
callfd, &x,
sizeof(x));
867 uword n_rx_packets = 0, n_rx_bytes = 0;
869 u32 n_left_to_next, * to_next;
874 u32 cpu_index, rx_len, drops, flush;
917 qsz_mask = txvq->
qsz - 1;
946 flush = n_left - _vec_len(vum->
rx_buffers[cpu_index]);
954 VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER, flush);
970 while (n_left > 0 && n_left_to_next > 0) {
972 u32 bi_head, bi_current;
973 u16 desc_chain_head, desc_current;
974 u8 error = VHOST_USER_INPUT_FUNC_ERROR_NO_ERROR;
977 bi_head = bi_current = vum->
rx_buffers[cpu_index][--rx_len];
988 offset = txvq->
desc[desc_current].len;
994 error = VHOST_USER_INPUT_FUNC_ERROR_MMAP_FAIL;
998 #if VHOST_USER_COPY_TX_HDR == 1 1000 clib_memcpy(b->pre_data, buffer_addr,
sizeof(virtio_net_hdr_t));
1003 if (txvq->
desc[desc_current].len > offset) {
1004 u16 len = txvq->
desc[desc_current].len - offset;
1006 b_head, &b_current, buffer_addr + offset, len);
1008 if (copied != len) {
1009 error = VHOST_USER_INPUT_FUNC_ERROR_NO_BUFFER;
1016 if (txvq->
desc[desc_current].flags & VIRTQ_DESC_F_NEXT )
1017 desc_current = txvq->
desc[desc_current].next;
1030 error == VHOST_USER_INPUT_FUNC_ERROR_NO_ERROR)) {
1031 error = VHOST_USER_INPUT_FUNC_ERROR_UNDERSIZED_FRAME;
1052 to_next[0] = bi_head;
1056 to_next, n_left_to_next,
1065 _vec_len(vum->
rx_buffers[cpu_index]) = rx_len;
1079 if((txvq->
callfd > 0) && !(txvq->
avail->flags & 1)) {
1099 n_rx_packets, n_rx_bytes);
1101 return n_rx_packets;
1112 uword n_rx_packets = 0;
1123 return n_rx_packets;
1129 .name =
"vhost-user-input",
1132 .state = VLIB_NODE_STATE_DISABLED,
1156 uword n_packets = 0;
1161 u8 error = VHOST_USER_TX_FUNC_ERROR_NONE;
1167 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
1173 while (__sync_lock_test_and_set (vui->lockp, 1))
1180 error = VHOST_USER_TX_FUNC_ERROR_NOT_READY;
1185 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1190 used_index = rxvq->
used->idx;
1191 qsz_mask = rxvq->
qsz - 1;
1196 u16 desc_chain_head, desc_current, desc_len;
1208 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1213 offset = vui->virtio_net_hdr_sz;
1216 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1222 virtio_net_hdr_mrg_rxbuf_t * hdr = (virtio_net_hdr_mrg_rxbuf_t *) buffer_addr;
1224 hdr->hdr.gso_type = 0;
1228 if (vui->virtio_net_hdr_sz == 12)
1229 hdr->num_buffers = 1;
1232 buffer_addr += offset;
1251 if (rxvq->
desc[desc_current].len <= offset) {
1254 desc_current = rxvq->
desc[desc_current].next;
1256 used_index -= hdr->num_buffers - 1;
1258 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1261 }
else if (vui->virtio_net_hdr_sz == 12) {
1264 rxvq->
used->ring[used_index & qsz_mask].id = desc_chain_head;
1265 rxvq->
used->ring[used_index & qsz_mask].len = desc_len;
1273 used_index -= hdr->num_buffers - 1;
1275 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1281 desc_current = desc_chain_head;
1286 used_index -= hdr->num_buffers - 1;
1288 error = VHOST_USER_TX_FUNC_ERROR_MMAP_FAIL;
1292 error = VHOST_USER_TX_FUNC_ERROR_PKT_DROP_NOBUF;
1297 u16 bytes_to_copy = bytes_left > (rxvq->
desc[desc_current].len - offset) ? (rxvq->
desc[desc_current].len - offset) : bytes_left;
1301 bytes_left -= bytes_to_copy;
1302 offset += bytes_to_copy;
1303 buffer_addr += bytes_to_copy;
1304 desc_len += bytes_to_copy;
1308 rxvq->
used->ring[used_index & qsz_mask].id = desc_chain_head;
1309 rxvq->
used->ring[used_index & qsz_mask].len = desc_len;
1318 rxvq->
used->idx = used_index;
1322 if((rxvq->
callfd > 0) && !(rxvq->
avail->flags & 1)) {
1334 if (
PREDICT_FALSE(n_left && error != VHOST_USER_TX_FUNC_ERROR_NONE)) {
1366 .name =
"vhost-user",
1373 .no_flatten_output_chains = 1,
1383 struct sockaddr_un sun;
1386 f64 timeout = 3153600000.0 ;
1387 uword *event_data = 0;
1389 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1390 sun.sun_family = AF_UNIX;
1413 strncpy(sun.sun_path, (
char *) vui->
sock_filename,
sizeof(sun.sun_path) - 1);
1415 if (connect(sockfd, (
struct sockaddr *) &sun,
sizeof(
struct sockaddr_un)) == 0) {
1418 template.file_descriptor = sockfd;
1422 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
1432 socklen_t len =
sizeof (error);
1433 int retval = getsockopt(vui->
unix_fd, SOL_SOCKET, SO_ERROR, &error, &len);
1446 .name =
"vhost-user-process",
1460 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1477 DBG_SOCK (
"deleted (deactivated) vhost-user interface instance %d", p[0]);
1486 struct sockaddr_un un;
1489 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1492 return VNET_API_ERROR_SYSCALL_ERROR_1;
1495 un.sun_family = AF_UNIX;
1496 strcpy((
char *) un.sun_path, (
char *) sock_filename);
1499 unlink( (
char *) sock_filename);
1501 len = strlen((
char *) un.sun_path) + strlen((
char *) sock_filename);
1503 if (bind(fd, (
struct sockaddr *) &un, len) == -1) {
1504 rv = VNET_API_ERROR_SYSCALL_ERROR_2;
1508 if (listen(fd, 1) == -1) {
1509 rv = VNET_API_ERROR_SYSCALL_ERROR_3;
1515 template.file_descriptor = fd;
1532 if (inactive_cnt > 0) {
1537 DBG_SOCK(
"reusing inactive vhost-user interface index %d", vui_idx);
1563 rnd = (
u32) (now * 1e6);
1573 vhost_user_dev_class.index,
1588 const char * sock_filename,
1589 u8 is_server,
u64 feature_mask,
1609 for (q = 0; q < 2; q++) {
1645 VLIB_NODE_STATE_POLLING);
1648 VLIB_NODE_STATE_POLLING);
1655 const char * sock_filename,
1659 u8 renumber,
u32 custom_dev_instance,
1671 clib_warning(
"vhost-user interfaces are not supported with multiple io threads");
1686 feature_mask, &sw_if_idx);
1695 *sw_if_index = sw_if_idx;
1701 const char * sock_filename,
1705 u8 renumber,
u32 custom_dev_instance)
1717 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
1734 feature_mask, &sw_if_idx);
1751 u8 * sock_filename =
NULL;
1754 u64 feature_mask = (
u64)~0;
1756 u32 custom_dev_instance = ~0;
1765 if (
unformat (line_input,
"socket %s", &sock_filename))
1767 else if (
unformat (line_input,
"server"))
1769 else if (
unformat (line_input,
"feature-mask 0x%llx", &feature_mask))
1773 else if (
unformat (line_input,
"renumber %d", &custom_dev_instance)) {
1785 is_server, &sw_if_index, feature_mask,
1786 renumber, custom_dev_instance, hw);
1799 u32 sw_if_index = ~0;
1806 if (
unformat (line_input,
"sw_if_index %d", &sw_if_index))
1828 u32 * hw_if_indices = 0;
1841 for (i = 0; i <
vec_len (hw_if_indices); i++) {
1857 strncpy((
char *)vuid->
if_name, (
char *)s,
1865 *out_vuids = r_vuids;
1879 u32 hw_if_index, * hw_if_indices = 0;
1883 struct feat_struct {
u8 bit;
char *str;};
1884 struct feat_struct *feat_entry;
1886 static struct feat_struct feat_array[] = {
1887 #define _(s,b) { .str = #s, .bit = b, }, 1895 vec_add1 (hw_if_indices, hw_if_index);
1906 if (
vec_len (hw_if_indices) == 0) {
1916 for (i = 0; i <
vec_len (hw_if_indices); i++) {
1920 hi->
name, hw_if_indices[i]);
1925 feat_entry = (
struct feat_struct *) &feat_array;
1926 while(feat_entry->str) {
1927 if (vui->
features & (1 << feat_entry->bit))
1942 vlib_cli_output(vm,
" region fd guest_phys_addr memory_size userspace_addr mmap_offset mmap_addr\n");
1943 vlib_cli_output(vm,
" ====== ===== ================== ================== ================== ================== ==================\n");
1945 for (j = 0; j < vui->
nregions; j++) {
1946 vlib_cli_output(vm,
" %d %-5d 0x%016lx 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n", j,
1963 vlib_cli_output(vm,
" avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
1977 vlib_cli_output(vm,
" ===== ================== ===== ====== ===== ==================\n");
1978 for(j = 0; j < vui->
vrings[q].
qsz; j++) {
2006 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)
static void * map_user_mem(vhost_user_intf_t *vui, u64 addr)
static void vhost_user_if_disconnect(vhost_user_intf_t *vui)
always_inline void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
static void * map_guest_mem(vhost_user_intf_t *vui, u64 addr)
#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)
always_inline vlib_thread_main_t * vlib_get_thread_main()
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)
always_inline uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
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)
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 uword vhost_user_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *f)
always_inline uword unix_file_add(unix_main_t *um, unix_file_t *template)
always_inline void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
#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.
always_inline void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
always_inline void vhost_user_log_dirty_pages(vhost_user_intf_t *vui, u64 addr, u64 len)
static void vhost_user_vui_register(vlib_main_t *vm, vhost_user_intf_t *vui)
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)
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#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)
#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)
always_inline u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
#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)
vlib_combined_counter_main_t * combined_sw_if_counters
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
int input_cpu_first_index
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
always_inline void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
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)
vhost_user_input_func_error_t
#define vlib_call_init_function(vm, x)
always_inline u32 random_u32(u32 *seed)
32-bit random number generator
static clib_error_t * vhost_user_socket_read(unix_file_t *uf)
static uword vhost_user_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
#define VLIB_BUFFER_NEXT_PRESENT
always_inline void * clib_mem_alloc_aligned(uword size, uword align)
#define VLIB_BUFFER_PRE_DATA_SIZE
format_function_t format_vnet_sw_interface_name
#define pool_elt_at_index(p, i)
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
u16 current_length
Nbytes between current data and the end of this buffer.
int vhost_user_delete_if(vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index)
always_inline void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 cpu_index, u32 index, u32 increment)
uword os_get_cpu_number(void)
#define clib_error_return_unix(e, args...)
always_inline f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
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.
#define VLIB_CONFIG_FUNCTION(x, n,...)
#define vhost_user_log_dirty_ring(vui, vq, member)
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)
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)
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
always_inline void * vlib_frame_args(vlib_frame_t *f)
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)
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)
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).
#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
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define VHOST_USER_PROTOCOL_F_LOG_SHMFD
#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
always_inline void unix_file_del(unix_main_t *um, unix_file_t *f)
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
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)
#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)
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)
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
static int vhost_user_init_server_sock(const char *sock_filename, int *sockfd)
#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)
always_inline void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
#define DBG_SOCK(args...)
static vhost_user_main_t vhost_user_main
#define VHOST_NET_VRING_IDX_TX
#define VLIB_REGISTER_NODE(x,...)
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
always_inline f64 vlib_time_now(vlib_main_t *vm)
#define CLIB_MEMORY_BARRIER()
#define clib_error_return(e, args...)
#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.
always_inline void vlib_buffer_chain_init(vlib_buffer_t *first)
uword * vhost_user_interface_index_by_sw_if_index
always_inline void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
uword runtime_data[(128-1 *sizeof(vlib_node_function_t *)-1 *sizeof(vlib_error_t *)-11 *sizeof(u32)-5 *sizeof(u16))/sizeof(uword)]
always_inline 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)
vlib_main_t ** vlib_mains
int dont_dump_vhost_user_memory
always_inline vnet_sw_interface_t * vnet_get_hw_sw_interface(vnet_main_t *vnm, u32 hw_if_index)