Stefano Garzarella
2021-Mar-15 11:15 UTC
[RFC PATCH v6 13/22] virtio/vsock: add SEQPACKET receive logic
On Sun, Mar 07, 2021 at 09:02:50PM +0300, Arseny Krasnov wrote:>This modifies current receive logic for SEQPACKET support: >1) Inserts 'SEQ_BEGIN' packet to socket's rx queue. >2) Inserts 'RW' packet to socket's rx queue, but without merging with > buffer of last packet in queue. >3) Performs check for packet and socket types on receive(if mismatch, > then reset connection). > >Signed-off-by: Arseny Krasnov <arseny.krasnov at kaspersky.com> >--- > net/vmw_vsock/virtio_transport_common.c | 63 +++++++++++++++++-------- > 1 file changed, 44 insertions(+), 19 deletions(-) > >diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c >index 6fc78fec41c0..9d86375935ce 100644 >--- a/net/vmw_vsock/virtio_transport_common.c >+++ b/net/vmw_vsock/virtio_transport_common.c >@@ -165,6 +165,14 @@ void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt) > } > EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt); > >+static u16 virtio_transport_get_type(struct sock *sk) >+{ >+ if (sk->sk_type == SOCK_STREAM) >+ return VIRTIO_VSOCK_TYPE_STREAM; >+ else >+ return VIRTIO_VSOCK_TYPE_SEQPACKET; >+} >+ > /* This function can only be used on connecting/connected sockets, > * since a socket assigned to a transport is required. > * >@@ -1062,25 +1070,27 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk, > goto out; > } > >- /* Try to copy small packets into the buffer of last packet queued, >- * to avoid wasting memory queueing the entire buffer with a small >- * payload. >- */ >- if (pkt->len <= GOOD_COPY_LEN && !list_empty(&vvs->rx_queue)) { >- struct virtio_vsock_pkt *last_pkt; >+ if (le16_to_cpu(pkt->hdr.type) == VIRTIO_VSOCK_TYPE_STREAM) { >+ /* Try to copy small packets into the buffer of last packet queued, >+ * to avoid wasting memory queueing the entire buffer with a small >+ * payload. >+ */ >+ if (pkt->len <= GOOD_COPY_LEN && !list_empty(&vvs->rx_queue)) { >+ struct virtio_vsock_pkt *last_pkt; > >- last_pkt = list_last_entry(&vvs->rx_queue, >- struct virtio_vsock_pkt, list); >+ last_pkt = list_last_entry(&vvs->rx_queue, >+ struct virtio_vsock_pkt, list); > >- /* If there is space in the last packet queued, we copy the >- * new packet in its buffer. >- */ >- if (pkt->len <= last_pkt->buf_len - last_pkt->len) { >- memcpy(last_pkt->buf + last_pkt->len, pkt->buf, >- pkt->len); >- last_pkt->len += pkt->len; >- free_pkt = true; >- goto out; >+ /* If there is space in the last packet queued, we copy the >+ * new packet in its buffer. >+ */ >+ if (pkt->len <= last_pkt->buf_len - last_pkt->len) { >+ memcpy(last_pkt->buf + last_pkt->len, pkt->buf, >+ pkt->len); >+ last_pkt->len += pkt->len; >+ free_pkt = true; >+ goto out; >+ } > } > } > >@@ -1100,9 +1110,13 @@ virtio_transport_recv_connected(struct sock *sk, > int err = 0; > > switch (le16_to_cpu(pkt->hdr.op)) { >+ case VIRTIO_VSOCK_OP_SEQ_BEGIN: >+ case VIRTIO_VSOCK_OP_SEQ_END: > case VIRTIO_VSOCK_OP_RW: > virtio_transport_recv_enqueue(vsk, pkt); >- sk->sk_data_ready(sk); >+ >+ if (le16_to_cpu(pkt->hdr.op) != VIRTIO_VSOCK_OP_SEQ_BEGIN) >+ sk->sk_data_ready(sk); > return err; > case VIRTIO_VSOCK_OP_CREDIT_UPDATE: > sk->sk_write_space(sk); >@@ -1245,6 +1259,12 @@ virtio_transport_recv_listen(struct sock *sk, struct virtio_vsock_pkt *pkt, > return 0; > } > >+static bool virtio_transport_valid_type(u16 type) >+{ >+ return (type == VIRTIO_VSOCK_TYPE_STREAM) || >+ (type == VIRTIO_VSOCK_TYPE_SEQPACKET); >+} >+ > /* We are under the virtio-vsock's vsock->rx_lock or vhost-vsock's vq->mutex > * lock. > */ >@@ -1270,7 +1290,7 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, > le32_to_cpu(pkt->hdr.buf_alloc), > le32_to_cpu(pkt->hdr.fwd_cnt)); > >- if (le16_to_cpu(pkt->hdr.type) != VIRTIO_VSOCK_TYPE_STREAM) { >+ if (!virtio_transport_valid_type(le16_to_cpu(pkt->hdr.type))) { > (void)virtio_transport_reset_no_sock(t, pkt); > goto free_pkt; > } >@@ -1287,6 +1307,11 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, > } > } > >+ if (virtio_transport_get_type(sk) != le16_to_cpu(pkt->hdr.type)) { >+ (void)virtio_transport_reset_no_sock(t, pkt);We must release the refcnt acquired by vsock_find_connected_socket() or vsock_find_bound_socket(), so we need to add: sock_put(sk);>+ goto free_pkt; >+ } >+ > vsk = vsock_sk(sk); > > lock_sock(sk); >-- >2.25.1 >