Merge branch 'net-virtio-vsock'
This commit is contained in:
commit
1a200b51fa
|
@ -241,21 +241,18 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
|
|||
}
|
||||
|
||||
static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
|
||||
struct sk_buff *skb)
|
||||
u32 len)
|
||||
{
|
||||
if (vvs->rx_bytes + skb->len > vvs->buf_alloc)
|
||||
if (vvs->rx_bytes + len > vvs->buf_alloc)
|
||||
return false;
|
||||
|
||||
vvs->rx_bytes += skb->len;
|
||||
vvs->rx_bytes += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs,
|
||||
struct sk_buff *skb)
|
||||
u32 len)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = skb_headroom(skb) - sizeof(struct virtio_vsock_hdr) - skb->len;
|
||||
vvs->rx_bytes -= len;
|
||||
vvs->fwd_cnt += len;
|
||||
}
|
||||
|
@ -367,7 +364,7 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
|
|||
|
||||
spin_lock_bh(&vvs->rx_lock);
|
||||
while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
|
||||
skb = __skb_dequeue(&vvs->rx_queue);
|
||||
skb = skb_peek(&vvs->rx_queue);
|
||||
|
||||
bytes = len - total;
|
||||
if (bytes > skb->len)
|
||||
|
@ -388,10 +385,11 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
|
|||
skb_pull(skb, bytes);
|
||||
|
||||
if (skb->len == 0) {
|
||||
virtio_transport_dec_rx_pkt(vvs, skb);
|
||||
u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);
|
||||
|
||||
virtio_transport_dec_rx_pkt(vvs, pkt_len);
|
||||
__skb_unlink(skb, &vvs->rx_queue);
|
||||
consume_skb(skb);
|
||||
} else {
|
||||
__skb_queue_head(&vvs->rx_queue, skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,17 +435,17 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
|
|||
|
||||
while (!msg_ready) {
|
||||
struct virtio_vsock_hdr *hdr;
|
||||
size_t pkt_len;
|
||||
|
||||
skb = __skb_dequeue(&vvs->rx_queue);
|
||||
if (!skb)
|
||||
break;
|
||||
hdr = virtio_vsock_hdr(skb);
|
||||
pkt_len = (size_t)le32_to_cpu(hdr->len);
|
||||
|
||||
if (dequeued_len >= 0) {
|
||||
size_t pkt_len;
|
||||
size_t bytes_to_copy;
|
||||
|
||||
pkt_len = (size_t)le32_to_cpu(hdr->len);
|
||||
bytes_to_copy = min(user_buf_len, pkt_len);
|
||||
|
||||
if (bytes_to_copy) {
|
||||
|
@ -466,7 +464,6 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
|
|||
dequeued_len = err;
|
||||
} else {
|
||||
user_buf_len -= bytes_to_copy;
|
||||
skb_pull(skb, bytes_to_copy);
|
||||
}
|
||||
|
||||
spin_lock_bh(&vvs->rx_lock);
|
||||
|
@ -484,7 +481,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
|
|||
msg->msg_flags |= MSG_EOR;
|
||||
}
|
||||
|
||||
virtio_transport_dec_rx_pkt(vvs, skb);
|
||||
virtio_transport_dec_rx_pkt(vvs, pkt_len);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1037,7 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
|||
|
||||
spin_lock_bh(&vvs->rx_lock);
|
||||
|
||||
can_enqueue = virtio_transport_inc_rx_pkt(vvs, skb);
|
||||
can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
|
||||
if (!can_enqueue) {
|
||||
free_pkt = true;
|
||||
goto out;
|
||||
|
|
|
@ -860,6 +860,114 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
|
|||
close(fd);
|
||||
}
|
||||
|
||||
#define INV_BUF_TEST_DATA_LEN 512
|
||||
|
||||
static void test_inv_buf_client(const struct test_opts *opts, bool stream)
|
||||
{
|
||||
unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
|
||||
ssize_t ret;
|
||||
int fd;
|
||||
|
||||
if (stream)
|
||||
fd = vsock_stream_connect(opts->peer_cid, 1234);
|
||||
else
|
||||
fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("connect");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
control_expectln("SENDDONE");
|
||||
|
||||
/* Use invalid buffer here. */
|
||||
ret = recv(fd, NULL, sizeof(data), 0);
|
||||
if (ret != -1) {
|
||||
fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (errno != ENOMEM) {
|
||||
fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = recv(fd, data, sizeof(data), MSG_DONTWAIT);
|
||||
|
||||
if (stream) {
|
||||
/* For SOCK_STREAM we must continue reading. */
|
||||
if (ret != sizeof(data)) {
|
||||
fprintf(stderr, "expected recv(2) success, got %zi\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Don't check errno in case of success. */
|
||||
} else {
|
||||
/* For SOCK_SEQPACKET socket's queue must be empty. */
|
||||
if (ret != -1) {
|
||||
fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (errno != EAGAIN) {
|
||||
fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
control_writeln("DONE");
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void test_inv_buf_server(const struct test_opts *opts, bool stream)
|
||||
{
|
||||
unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
|
||||
ssize_t res;
|
||||
int fd;
|
||||
|
||||
if (stream)
|
||||
fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
|
||||
else
|
||||
fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("accept");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
res = send(fd, data, sizeof(data), 0);
|
||||
if (res != sizeof(data)) {
|
||||
fprintf(stderr, "unexpected send(2) result %zi\n", res);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
control_writeln("SENDDONE");
|
||||
|
||||
control_expectln("DONE");
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void test_stream_inv_buf_client(const struct test_opts *opts)
|
||||
{
|
||||
test_inv_buf_client(opts, true);
|
||||
}
|
||||
|
||||
static void test_stream_inv_buf_server(const struct test_opts *opts)
|
||||
{
|
||||
test_inv_buf_server(opts, true);
|
||||
}
|
||||
|
||||
static void test_seqpacket_inv_buf_client(const struct test_opts *opts)
|
||||
{
|
||||
test_inv_buf_client(opts, false);
|
||||
}
|
||||
|
||||
static void test_seqpacket_inv_buf_server(const struct test_opts *opts)
|
||||
{
|
||||
test_inv_buf_server(opts, false);
|
||||
}
|
||||
|
||||
static struct test_case test_cases[] = {
|
||||
{
|
||||
.name = "SOCK_STREAM connection reset",
|
||||
|
@ -920,6 +1028,16 @@ static struct test_case test_cases[] = {
|
|||
.run_client = test_seqpacket_bigmsg_client,
|
||||
.run_server = test_seqpacket_bigmsg_server,
|
||||
},
|
||||
{
|
||||
.name = "SOCK_STREAM test invalid buffer",
|
||||
.run_client = test_stream_inv_buf_client,
|
||||
.run_server = test_stream_inv_buf_server,
|
||||
},
|
||||
{
|
||||
.name = "SOCK_SEQPACKET test invalid buffer",
|
||||
.run_client = test_seqpacket_inv_buf_client,
|
||||
.run_server = test_seqpacket_inv_buf_server,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue