Beispiel #1
0
static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
                                    int64_t pos)
{
    QEMUFileSocket *s = opaque;
    ssize_t len;
    ssize_t size = iov_size(iov, iovcnt);

    len = iov_send(s->fd, iov, iovcnt, 0, size);
    if (len < size) {
        len = -socket_error();
    }
    return len;
}
Beispiel #2
0
static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
                                    int64_t pos)
{
    QEMUFileSocket *s = opaque;
    ssize_t len;
    ssize_t size = iov_size(iov, iovcnt);
    ssize_t offset = 0;
    int     err;

    while (size > 0) {
        len = iov_send(s->fd, iov, iovcnt, offset, size);

        if (len > 0) {
            size -= len;
            offset += len;
        }

        if (size > 0) {
            err = socket_error();

            if (err != EAGAIN && err != EWOULDBLOCK) {
                error_report("socket_writev_buffer: Got err=%d for (%zu/%zu)",
                             err, (size_t)size, (size_t)len);
                /*
                 * If I've already sent some but only just got the error, I
                 * could return the amount validly sent so far and wait for the
                 * next call to report the error, but I'd rather flag the error
                 * immediately.
                 */
                return -err;
            }

            /* Emulate blocking */
            GPollFD pfd;

            pfd.fd = s->fd;
            pfd.events = G_IO_OUT | G_IO_ERR;
            pfd.revents = 0;
            TFR(err = g_poll(&pfd, 1, -1 /* no timeout */));
            /* Errors other than EINTR intentionally ignored */
        }
     }

    return offset;
}
Beispiel #3
0
    g_assert_cmpint(recv_sock, !=, -1);

    /* send a qmp command to guarantee that 'connected' is setting to true. */
    qmp_discard_response("{ 'execute' : 'query-status'}");

    struct iovec iov[] = {
        {
            .iov_base = &size,
            .iov_len = sizeof(size),
        }, {
            .iov_base = send_buf,
            .iov_len = sizeof(send_buf),
        },
    };

    ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
    g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
    close(backend_sock[0]);

    ret = qemu_recv(recv_sock, &len, sizeof(len), 0);
    g_assert_cmpint(ret, ==, sizeof(len));
    len = ntohl(len);

    g_assert_cmpint(len, ==, sizeof(send_buf));
    recv_buf = g_malloc(len);
    ret = qemu_recv(recv_sock, recv_buf, len, 0);
    g_assert_cmpstr(recv_buf, ==, send_buf);

    g_free(recv_buf);
    close(recv_sock);
    unlink(sock_path0);
Beispiel #4
0
    NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
    uint32_t len = htonl(size);
    struct iovec iov[] = {
        {
            .iov_base = &len,
            .iov_len  = sizeof(len),
        }, {
            .iov_base = (void *)buf,
            .iov_len  = size,
        },
    };
    size_t remaining;
    ssize_t ret;

    remaining = iov_size(iov, 2) - s->send_index;
    ret = iov_send(s->fd, iov, 2, s->send_index, remaining);

    if (ret == -1 && errno == EAGAIN) {
        ret = 0; /* handled further down */
    }
    if (ret == -1) {
        s->send_index = 0;
        return -errno;
    }
    if (ret < (ssize_t)remaining) {
        s->send_index += ret;
        net_socket_write_poll(s, true);
        return 0;
    }
    s->send_index = 0;
    return size;
Beispiel #5
0
        {
            .iov_base = &len,
            .iov_len = sizeof(len),
        }, {
            .iov_base = test,
            .iov_len = sizeof(test),
        },
    };
    int ret;

    req_addr = guest_alloc(alloc, 64);

    free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
    qvirtqueue_kick(bus, dev, vq, free_head);

    ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
    g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));

    qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
    memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
    g_assert_cmpstr(buffer, ==, "TEST");

    guest_free(alloc, req_addr);
}

static void tx_test(const QVirtioBus *bus, QVirtioDevice *dev,
                    QGuestAllocator *alloc, QVirtQueue *vq,
                    int socket)
{
    uint64_t req_addr;
    uint32_t free_head;
Beispiel #6
0
static void test_io(void)
{
#ifndef _WIN32
/* socketpair(PF_UNIX) which does not exist on windows */

    int sv[2];
    int r;
    unsigned i, j, k, s, t;
    fd_set fds;
    unsigned niov;
    struct iovec *iov, *siov;
    unsigned char *buf;
    size_t sz;

    iov_random(&iov, &niov);
    sz = iov_size(iov, niov);
    buf = g_malloc(sz);
    for (i = 0; i < sz; ++i) {
        buf[i] = i & 255;
    }
    iov_from_buf(iov, niov, 0, buf, sz);

    siov = g_malloc(sizeof(*iov) * niov);
    memcpy(siov, iov, sizeof(*iov) * niov);

    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
       perror("socketpair");
       exit(1);
    }

    FD_ZERO(&fds);

    t = 0;
    if (fork() == 0) {
       /* writer */

       close(sv[0]);
       FD_SET(sv[1], &fds);
       fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
       r = g_test_rand_int_range(sz / 2, sz);
       setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));

       for (i = 0; i <= sz; ++i) {
           for (j = i; j <= sz; ++j) {
               k = i;
               do {
                   s = g_test_rand_int_range(0, j - k + 1);
                   r = iov_send(sv[1], iov, niov, k, s);
                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
                   if (r >= 0) {
                       k += r;
                       t += r;
                       usleep(g_test_rand_int_range(0, 30));
                   } else if (errno == EAGAIN) {
                       select(sv[1]+1, NULL, &fds, NULL, NULL);
                       continue;
                   } else {
                       perror("send");
                       exit(1);
                   }
               } while(k < j);
           }
       }
       exit(0);

    } else {
       /* reader & verifier */

       close(sv[1]);
       FD_SET(sv[0], &fds);
       fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
       r = g_test_rand_int_range(sz / 2, sz);
       setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
       usleep(500000);

       for (i = 0; i <= sz; ++i) {
           for (j = i; j <= sz; ++j) {
               k = i;
               iov_memset(iov, niov, 0, 0xff, -1);
               do {
                   s = g_test_rand_int_range(0, j - k + 1);
                   r = iov_recv(sv[0], iov, niov, k, s);
                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
                   if (r > 0) {
                       k += r;
                       t += r;
                   } else if (!r) {
                       if (s) {
                           break;
                       }
                   } else if (errno == EAGAIN) {
                       select(sv[0]+1, &fds, NULL, NULL, NULL);
                       continue;
                   } else {
                       perror("recv");
                       exit(1);
                   }
               } while(k < j);
               test_iov_bytes(iov, niov, i, j - i);
           }
        }
     }
#endif
}