static void dump_data(USBPacket *p, int ret) { iov_hexdump(p->iov.iov, p->iov.niov, stderr, "uhci", ret); }
static void vubr_handle_tx(VuDev *dev, int qidx) { VuVirtq *vq = vu_get_queue(dev, qidx); VubrDev *vubr = container_of(dev, VubrDev, vudev); int hdrlen = vubr->hdrlen; VuVirtqElement *elem = NULL; assert(qidx % 2); for (;;) { ssize_t ret; unsigned int out_num; struct iovec sg[VIRTQUEUE_MAX_SIZE], *out_sg; elem = vu_queue_pop(dev, vq, sizeof(VuVirtqElement)); if (!elem) { break; } out_num = elem->out_num; out_sg = elem->out_sg; if (out_num < 1) { fprintf(stderr, "virtio-net header not in first element\n"); break; } if (VHOST_USER_BRIDGE_DEBUG) { iov_hexdump(out_sg, out_num, stderr, "TX:", 1024); } if (hdrlen) { unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg), out_sg, out_num, hdrlen, -1); out_num = sg_num; out_sg = sg; } struct msghdr msg = { .msg_name = (struct sockaddr *) &vubr->backend_udp_dest, .msg_namelen = sizeof(struct sockaddr_in), .msg_iov = out_sg, .msg_iovlen = out_num, }; do { ret = sendmsg(vubr->backend_udp_sock, &msg, 0); } while (ret == -1 && (errno == EAGAIN || errno == EINTR)); if (ret == -1) { vubr_die("sendmsg()"); } vu_queue_push(dev, vq, elem, 0); vu_queue_notify(dev, vq); free(elem); elem = NULL; } free(elem); } /* this function reverse the effect of iov_discard_front() it must be * called with 'front' being the original struct iovec and 'bytes' * being the number of bytes you shaved off */ static void iov_restore_front(struct iovec *front, struct iovec *iov, size_t bytes) { struct iovec *cur; for (cur = front; cur != iov; cur++) { assert(bytes >= cur->iov_len); bytes -= cur->iov_len; } cur->iov_base -= bytes; cur->iov_len += bytes; } static void iov_truncate(struct iovec *iov, unsigned iovc, size_t bytes) { unsigned i; for (i = 0; i < iovc; i++, iov++) { if (bytes < iov->iov_len) { iov->iov_len = bytes; return; } bytes -= iov->iov_len; } assert(!"couldn't truncate iov"); }