static int test_misc(void) { char memdump[] = "memdump_test"; if (rte_bsf32(129)) FAIL("rte_bsf32"); rte_memdump(stdout, "test", memdump, sizeof(memdump)); rte_hexdump(stdout, "test", memdump, sizeof(memdump)); rte_pause(); return 0; }
static int usock_mbuf_write(struct vr_usocket *usockp, struct rte_mbuf *mbuf) { unsigned int i, pkt_len; struct msghdr mhdr; struct rte_mbuf *m; struct iovec *iov; if (!mbuf) return 0; pkt_len = rte_pktmbuf_pkt_len(mbuf); if (!pkt_len) return 0; iov = usockp->usock_iovec; m = mbuf; for (i = 0; (m && (i < PKT0_MAX_IOV_LEN)); i++) { iov->iov_base = rte_pktmbuf_mtod(m, unsigned char *); iov->iov_len = rte_pktmbuf_data_len(m); m = m->next; iov++; } if ((i == PKT0_MAX_IOV_LEN) && m) usockp->usock_pkt_truncated++; mhdr.msg_name = NULL; mhdr.msg_namelen = 0; mhdr.msg_iov = usockp->usock_iovec; mhdr.msg_iovlen = i; mhdr.msg_control = NULL; mhdr.msg_controllen = 0; mhdr.msg_flags = 0; #ifdef VR_DPDK_USOCK_DUMP RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d sending message\n", __func__, pthread_self(), usockp->usock_fd); rte_hexdump(stdout, "usock message dump:", &mhdr, sizeof(mhdr)); #endif return sendmsg(usockp->usock_fd, &mhdr, MSG_DONTWAIT); }
static int vr_usocket_connect(struct vr_usocket *usockp) { struct sockaddr_un sun; RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d\n", __func__, pthread_self(), usockp->usock_fd); if (usockp->usock_proto != PACKET) return -EINVAL; sun.sun_family = AF_UNIX; memset(sun.sun_path, 0, sizeof(sun.sun_path)); strncpy(sun.sun_path, VR_PACKET_AGENT_UNIX_FILE, sizeof(sun.sun_path) - 1); #ifdef VR_DPDK_USOCK_DUMP RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d retry connecting\n", __func__, pthread_self(), usockp->usock_fd); rte_hexdump(stdout, "usock address dump:", &sun, sizeof(sun)); #endif return vr_dpdk_retry_connect(usockp->usock_fd, (struct sockaddr *)&sun, sizeof(sun)); }
static int __usock_read(struct vr_usocket *usockp) { int ret; unsigned int offset = usockp->usock_read_offset; unsigned int len = usockp->usock_read_len; unsigned int toread = len - offset; struct nlmsghdr *nlh; unsigned int proto = usockp->usock_proto; char *buf = usockp->usock_rx_buf; if (toread > usockp->usock_buf_len) { toread = usockp->usock_buf_len - offset; } retry_read: if (usockp->usock_owner != pthread_self()) { if (usockp->usock_owner) RTE_LOG(WARNING, USOCK, "WARNING: thread %lx is trying to read" " usocket FD %d owned by thread %lx\n", pthread_self(), usockp->usock_fd, usockp->usock_owner); usockp->usock_owner = pthread_self(); } ret = read(usockp->usock_fd, buf + offset, toread); #ifdef VR_DPDK_USOCK_DUMP if (ret > 0) { RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d read %d bytes\n", __func__, pthread_self(), usockp->usock_fd, ret); rte_hexdump(stdout, "usock buffer dump:", buf + offset, ret); } else if (ret < 0) { RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d read returned error %d: %s (%d)\n", __func__, pthread_self(), usockp->usock_fd, ret, rte_strerror(errno), errno); } #endif if (ret <= 0) { if (!ret) return -1; if (errno == EINTR) goto retry_read; if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) return 0; RTE_LOG(ERR, USOCK, "Error reading FD %d: %s (%d)\n", usockp->usock_fd, rte_strerror(errno), errno); return ret; } offset += ret; usockp->usock_read_offset = offset; if (proto == NETLINK) { if (usockp->usock_state == READING_HEADER) { if (usockp->usock_read_offset == usockp->usock_read_len) { usockp->usock_state = READING_DATA; nlh = (struct nlmsghdr *)(usockp->usock_rx_buf); usockp->usock_read_len = nlh->nlmsg_len; } } if (usockp->usock_buf_len < usockp->usock_read_len) { usockp->usock_rx_buf = vr_malloc(usockp->usock_read_len, VR_USOCK_BUF_OBJECT); if (!usockp->usock_rx_buf) { /* bad, but let's recover */ usockp->usock_rx_buf = buf; usockp->usock_read_len -= usockp->usock_read_offset; usockp->usock_read_offset = 0; usockp->usock_state = READING_FAULTY_DATA; } else { memcpy(usockp->usock_rx_buf, buf, usockp->usock_read_offset); vr_free(buf, VR_USOCK_BUF_OBJECT); usockp->usock_buf_len = usockp->usock_read_len; buf = usockp->usock_rx_buf; } } } else if (proto == PACKET) { usockp->usock_read_len = ret; } return ret; }
static int __usock_write(struct vr_usocket *usockp) { int ret; unsigned int len; unsigned char *buf; struct vr_usocket *parent = NULL; if (usockp->usock_proto != EVENT) { parent = usockp->usock_parent; if (!parent) return -1; } buf = usockp->usock_tx_buf; if (!buf || !usockp->usock_write_len) return 0; len = usockp->usock_write_len; buf += usockp->usock_write_offset; len -= usockp->usock_write_offset; retry_write: #ifdef VR_DPDK_USOCK_DUMP RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d writing %d bytes\n", __func__, pthread_self(), usockp->usock_fd, len); rte_hexdump(stdout, "usock buffer dump:", buf, len); #endif if (usockp->usock_owner != pthread_self()) { if (usockp->usock_owner) RTE_LOG(WARNING, USOCK, "WARNING: thread %lx (lcore %u) is trying to write %u bytes" " to usocket FD %d owned by thread %lx\n", pthread_self(), rte_lcore_id(), len, usockp->usock_fd, usockp->usock_owner); usockp->usock_owner = pthread_self(); } ret = write(usockp->usock_fd, buf, len); if (ret > 0) { usockp->usock_write_offset += ret; if (usockp->usock_write_offset == usockp->usock_write_len) { /* remove from output poll */ if (parent) parent->usock_pfds[usockp->usock_child_index].events = POLLIN; usockp->usock_tx_buf = NULL; } else { if (parent) parent->usock_pfds[usockp->usock_child_index].events = POLLOUT; } } else if (ret < 0) { RTE_LOG(DEBUG, VROUTER, "%s[%lx]: write error FD %d\n", __func__, pthread_self(), usockp->usock_fd); usock_set_error(usockp, ret); if (errno == EINTR) goto retry_write; if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { if (parent) { parent->usock_pfds[usockp->usock_child_index].events = POLLOUT; return 0; } } usockp->usock_tx_buf = NULL; } return ret; }
static int vr_usocket_bind(struct vr_usocket *usockp) { int error = 0; struct sockaddr_in sin; struct sockaddr_un sun; struct sockaddr *addr = NULL; socklen_t addrlen = 0; int optval; bool server; optval = 1; RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d setting option\n", __func__, pthread_self(), usockp->usock_fd); if (setsockopt(usockp->usock_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) return -errno; switch (usockp->usock_type) { case TCP: sin.sin_family = AF_INET; sin.sin_port = rte_cpu_to_be_16(VR_NETLINK_TCP_PORT); sin.sin_addr.s_addr = INADDR_ANY; addr = (struct sockaddr *)&sin; addrlen = sizeof(sin); server = true; break; case UNIX: sun.sun_family = AF_UNIX; memset(sun.sun_path, 0, sizeof(sun.sun_path)); strncpy(sun.sun_path, VR_NETLINK_UNIX_FILE, sizeof(sun.sun_path) - 1); addr = (struct sockaddr *)&sun; addrlen = sizeof(sun); server = true; mkdir(VR_SOCKET_DIR, VR_SOCKET_DIR_MODE); unlink(sun.sun_path); break; case RAW: sun.sun_family = AF_UNIX; memset(sun.sun_path, 0, sizeof(sun.sun_path)); strncpy(sun.sun_path, VR_PACKET_UNIX_FILE, sizeof(sun.sun_path) - 1); addr = (struct sockaddr *)&sun; addrlen = sizeof(sun); server = false; mkdir(VR_SOCKET_DIR, VR_SOCKET_DIR_MODE); unlink(sun.sun_path); break; default: return -EINVAL; } #ifdef VR_DPDK_USOCK_DUMP RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d binding\n", __func__, pthread_self(), usockp->usock_fd); rte_hexdump(stdout, "usock address dump:", addr, addrlen); #endif error = bind(usockp->usock_fd, addr, addrlen); if (error < 0) return error; if (server) { RTE_LOG(DEBUG, USOCK, "%s[%lx]: FD %d listening\n", __func__, pthread_self(), usockp->usock_fd); error = listen(usockp->usock_fd, 1); if (error < 0) return error; usockp->usock_state = LISTENING; } return 0; }
/* * vr_uvh_cl_msg_handler - handler for messages from user space vhost * clients. Calls the appropriate handler based on the message type. * * Returns 0 on success, -1 on error. * * TODO: upon error, this function currently makes the process exit. * Instead, it should close the socket and continue serving other clients. */ static int vr_uvh_cl_msg_handler(int fd, void *arg) { vr_uvh_client_t *vru_cl = (vr_uvh_client_t *) arg; struct msghdr mhdr; struct iovec iov; int i, err, ret = 0, read_len = 0; struct cmsghdr *cmsg; memset(&mhdr, 0, sizeof(mhdr)); if (vru_cl->vruc_msg_bytes_read == 0) { mhdr.msg_control = &vru_cl->vruc_cmsg; mhdr.msg_controllen = sizeof(vru_cl->vruc_cmsg); iov.iov_base = (void *) &vru_cl->vruc_msg; iov.iov_len = VHOST_USER_HSIZE; mhdr.msg_iov = &iov; mhdr.msg_iovlen = 1; ret = recvmsg(fd, &mhdr, MSG_DONTWAIT); if (ret < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { ret = 0; goto cleanup; } vr_uvhost_log("Receive returned %d in vhost server for client %s\n", ret, vru_cl->vruc_path); ret = -1; goto cleanup; } else if (ret > 0) { if (mhdr.msg_flags & MSG_CTRUNC) { vr_uvhost_log("Truncated control message from vhost client %s\n", vru_cl->vruc_path); ret = -1; goto cleanup; } cmsg = CMSG_FIRSTHDR(&mhdr); if (cmsg && (cmsg->cmsg_len > 0) && (cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) { vru_cl->vruc_num_fds_sent = (cmsg->cmsg_len - CMSG_LEN(0))/ sizeof(int); if (vru_cl->vruc_num_fds_sent > VHOST_MEMORY_MAX_NREGIONS) { vr_uvhost_log("Too many FDs sent for client %s: %d\n", vru_cl->vruc_path, vru_cl->vruc_num_fds_sent); vru_cl->vruc_num_fds_sent = VHOST_MEMORY_MAX_NREGIONS; } memcpy(vru_cl->vruc_fds_sent, CMSG_DATA(cmsg), vru_cl->vruc_num_fds_sent*sizeof(int)); } vru_cl->vruc_msg_bytes_read = ret; if (ret < VHOST_USER_HSIZE) { ret = 0; goto cleanup; } read_len = vru_cl->vruc_msg.size; } else { /* * recvmsg returned 0, so return error. */ vr_uvhost_log("Receive returned %d in vhost server for client %s\n", ret, vru_cl->vruc_path); ret = -1; goto cleanup; } } else if (vru_cl->vruc_msg_bytes_read < VHOST_USER_HSIZE) { read_len = VHOST_USER_HSIZE - vru_cl->vruc_msg_bytes_read; } else { read_len = vru_cl->vruc_msg.size - (vru_cl->vruc_msg_bytes_read - VHOST_USER_HSIZE); } if (read_len) { if (vru_cl->vruc_owner != pthread_self()) { if (vru_cl->vruc_owner) RTE_LOG(WARNING, UVHOST, "WARNING: thread %lx is trying to read" " uvhost client FD %d owned by thread %lx\n", pthread_self(), fd, vru_cl->vruc_owner); vru_cl->vruc_owner = pthread_self(); } ret = read(fd, (((char *)&vru_cl->vruc_msg) + vru_cl->vruc_msg_bytes_read), read_len); #ifdef VR_DPDK_RX_PKT_DUMP if (ret > 0) { RTE_LOG(DEBUG, UVHOST, "%s[%lx]: FD %d read %d bytes\n", __func__, pthread_self(), fd, ret); rte_hexdump(stdout, "uvhost full message dump:", (((char *)&vru_cl->vruc_msg)), ret + vru_cl->vruc_msg_bytes_read); } else if (ret < 0) { RTE_LOG(DEBUG, UVHOST, "%s[%lx]: FD %d read returned error %d: %s (%d)\n", __func__, pthread_self(), fd, ret, rte_strerror(errno), errno); } #endif if (ret < 0) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { ret = 0; goto cleanup; } vr_uvhost_log( "Error: read returned %d, %d %d %d in vhost server for client %s\n", ret, errno, read_len, vru_cl->vruc_msg_bytes_read, vru_cl->vruc_path); ret = -1; goto cleanup; } else if (ret == 0) { vr_uvhost_log("Read returned %d in vhost server for client %s\n", ret, vru_cl->vruc_path); ret = -1; goto cleanup; } vru_cl->vruc_msg_bytes_read += ret; if (vru_cl->vruc_msg_bytes_read < VHOST_USER_HSIZE) { ret = 0; goto cleanup; } if (vru_cl->vruc_msg_bytes_read < (vru_cl->vruc_msg.size + VHOST_USER_HSIZE)) { ret = 0; goto cleanup; } } ret = vr_uvh_cl_call_handler(vru_cl); if (ret < 0) { vr_uvhost_log("Error handling message %d client %s\n", vru_cl->vruc_msg.request, vru_cl->vruc_path); ret = -1; goto cleanup; } ret = vr_uvh_cl_send_reply(fd, vru_cl); if (ret < 0) { vr_uvhost_log("Error sending reply for message %d client %s\n", vru_cl->vruc_msg.request, vru_cl->vruc_path); ret = -1; goto cleanup; } cleanup: err = errno; /* close all the FDs received */ for (i = 0; i < vru_cl->vruc_num_fds_sent; i++) { if (vru_cl->vruc_fds_sent[i] > 0) close(vru_cl->vruc_fds_sent[i]); } if (ret == -1) { /* set VQ_NOT_READY state to vif's queues. */ for (i = 0; i < VR_DPDK_VIRTIO_MAX_QUEUES; i++) { vr_dpdk_virtio_rxqs[vru_cl->vruc_idx][i].vdv_ready_state = VQ_NOT_READY; vr_dpdk_virtio_txqs[vru_cl->vruc_idx][i].vdv_ready_state = VQ_NOT_READY; } rte_wmb(); synchronize_rcu(); /* * Unmaps qemu's FDs. */ vr_dpdk_virtio_uvh_vif_munmap(&vr_dpdk_virtio_uvh_vif_mmap[vru_cl->vruc_idx]); } /* clear state for next message from this client. */ vru_cl->vruc_msg_bytes_read = 0; memset(&vru_cl->vruc_msg, 0, sizeof(vru_cl->vruc_msg)); memset(vru_cl->vruc_cmsg, 0, sizeof(vru_cl->vruc_cmsg)); memset(vru_cl->vruc_fds_sent, 0, sizeof(vru_cl->vruc_fds_sent)); vru_cl->vruc_num_fds_sent = 0; errno = err; return ret; }