--- v5
+++ v3
@@ -1,55 +1,199 @@
-'virtio_transport_send_credit_update()' has some extra args:
-1) 'type' may be set in 'virtio_transport_send_pkt_info()' using type
- of socket.
-2) This function is static and 'hdr' arg was always NULL.
+This adds rest of logic for SEQPACKET:
+1) Shared functions for packet sending now set valid type of packet
+ according socket type.
+2) SEQPACKET specific function like SEQ_BEGIN send and data dequeue.
+3) TAP support for SEQPACKET is not so easy if it is necessary to
+send whole record to TAP interface. This could be done by allocating
+new packet when whole record is received, data of record must be
+copied to TAP packet.
Signed-off-by: Arseny Krasnov <arseny.krasnov@kaspersky.com>
---
- net/vmw_vsock/virtio_transport_common.c | 15 ++++-----------
- 1 file changed, 4 insertions(+), 11 deletions(-)
+ include/linux/virtio_vsock.h | 7 ++++
+ net/vmw_vsock/virtio_transport_common.c | 55 +++++++++++++++++++++----
+ 2 files changed, 55 insertions(+), 7 deletions(-)
+diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
+index af8705ea8b95..ad9783df97c9 100644
+--- a/include/linux/virtio_vsock.h
++++ b/include/linux/virtio_vsock.h
+@@ -84,7 +84,14 @@ virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len, int flags);
+
++bool virtio_transport_seqpacket_seq_send_len(struct vsock_sock *vsk, size_t len);
+ size_t virtio_transport_seqpacket_seq_get_len(struct vsock_sock *vsk);
++ssize_t
++virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
++ struct msghdr *msg,
++ size_t len,
++ int type);
++
+ s64 virtio_transport_stream_has_data(struct vsock_sock *vsk);
+ s64 virtio_transport_stream_has_space(struct vsock_sock *vsk);
+
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
-index 1c9d71ca5e8e..833104b71a1c 100644
+index 90f9feef9d8f..fab14679ca7b 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
-@@ -271,13 +271,10 @@ void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit)
- }
- EXPORT_SYMBOL_GPL(virtio_transport_put_credit);
-
--static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
-- int type,
-- struct virtio_vsock_hdr *hdr)
-+static int virtio_transport_send_credit_update(struct vsock_sock *vsk)
- {
- struct virtio_vsock_pkt_info info = {
- .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE,
-- .type = type,
- .vsk = vsk,
- };
-
-@@ -385,11 +382,8 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
- * messages, we set the limit to a high value. TODO: experiment
- * with different values.
- */
-- if (free_space < VIRTIO_VSOCK_MAX_PKT_BUF_SIZE) {
-- virtio_transport_send_credit_update(vsk,
-- VIRTIO_VSOCK_TYPE_STREAM,
-- NULL);
-- }
-+ if (free_space < VIRTIO_VSOCK_MAX_PKT_BUF_SIZE)
-+ virtio_transport_send_credit_update(vsk);
-
- return total;
-
-@@ -498,8 +492,7 @@ void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val)
+@@ -139,6 +139,7 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
+ break;
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
++ case VIRTIO_VSOCK_OP_SEQ_BEGIN:
+ hdr->op = cpu_to_le16(AF_VSOCK_OP_CONTROL);
+ break;
+ default:
+@@ -157,6 +158,10 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
+
+ void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt)
+ {
++ /* TODO: implement tap support for SOCK_SEQPACKET. */
++ if (le16_to_cpu(pkt->hdr.type) == VIRTIO_VSOCK_TYPE_SEQPACKET)
++ return;
++
+ if (pkt->tap_delivered)
+ return;
+
+@@ -405,6 +410,19 @@ static u16 virtio_transport_get_type(struct sock *sk)
+ return VIRTIO_VSOCK_TYPE_SEQPACKET;
+ }
+
++bool virtio_transport_seqpacket_seq_send_len(struct vsock_sock *vsk, size_t len)
++{
++ struct virtio_vsock_pkt_info info = {
++ .type = VIRTIO_VSOCK_TYPE_SEQPACKET,
++ .op = VIRTIO_VSOCK_OP_SEQ_BEGIN,
++ .vsk = vsk,
++ .flags = len
++ };
++
++ return virtio_transport_send_pkt_info(vsk, &info);
++}
++EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_seq_send_len);
++
+ static inline void virtio_transport_del_n_free_pkt(struct virtio_vsock_pkt *pkt)
+ {
+ list_del(&pkt->list);
+@@ -576,6 +594,18 @@ virtio_transport_stream_dequeue(struct vsock_sock *vsk,
+ }
+ EXPORT_SYMBOL_GPL(virtio_transport_stream_dequeue);
+
++ssize_t
++virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
++ struct msghdr *msg,
++ size_t len, int flags)
++{
++ if (flags & MSG_PEEK)
++ return -EOPNOTSUPP;
++
++ return virtio_transport_seqpacket_do_dequeue(vsk, msg, len);
++}
++EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_dequeue);
++
+ int
+ virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+@@ -659,14 +689,15 @@ EXPORT_SYMBOL_GPL(virtio_transport_do_socket_init);
+ void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val)
+ {
+ struct virtio_vsock_sock *vvs = vsk->trans;
++ int type;
+
+ if (*val > VIRTIO_VSOCK_MAX_BUF_SIZE)
+ *val = VIRTIO_VSOCK_MAX_BUF_SIZE;
vvs->buf_alloc = *val;
- virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM,
- NULL);
-+ virtio_transport_send_credit_update(vsk);
++ type = virtio_transport_get_type(sk_vsock(vsk));
++ virtio_transport_send_credit_update(vsk, type, NULL);
}
EXPORT_SYMBOL_GPL(virtio_transport_notify_buffer_size);
+
+@@ -793,10 +824,11 @@ int virtio_transport_connect(struct vsock_sock *vsk)
+ {
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_REQUEST,
+- .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .vsk = vsk,
+ };
+
++ info.type = virtio_transport_get_type(sk_vsock(vsk));
++
+ return virtio_transport_send_pkt_info(vsk, &info);
+ }
+ EXPORT_SYMBOL_GPL(virtio_transport_connect);
+@@ -805,7 +837,6 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int mode)
+ {
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_SHUTDOWN,
+- .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .flags = (mode & RCV_SHUTDOWN ?
+ VIRTIO_VSOCK_SHUTDOWN_RCV : 0) |
+ (mode & SEND_SHUTDOWN ?
+@@ -813,6 +844,8 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int mode)
+ .vsk = vsk,
+ };
+
++ info.type = virtio_transport_get_type(sk_vsock(vsk));
++
+ return virtio_transport_send_pkt_info(vsk, &info);
+ }
+ EXPORT_SYMBOL_GPL(virtio_transport_shutdown);
+@@ -834,12 +867,18 @@ virtio_transport_stream_enqueue(struct vsock_sock *vsk,
+ {
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RW,
+- .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .msg = msg,
+ .pkt_len = len,
+ .vsk = vsk,
++ .flags = 0,
+ };
+
++ info.type = virtio_transport_get_type(sk_vsock(vsk));
++
++ if (info.type == VIRTIO_VSOCK_TYPE_SEQPACKET &&
++ msg->msg_flags & MSG_EOR)
++ info.flags |= VIRTIO_VSOCK_RW_EOR;
++
+ return virtio_transport_send_pkt_info(vsk, &info);
+ }
+ EXPORT_SYMBOL_GPL(virtio_transport_stream_enqueue);
+@@ -857,7 +896,6 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
+ {
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RST,
+- .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .reply = !!pkt,
+ .vsk = vsk,
+ };
+@@ -866,6 +904,8 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
+ if (pkt && le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST)
+ return 0;
+
++ info.type = virtio_transport_get_type(sk_vsock(vsk));
++
+ return virtio_transport_send_pkt_info(vsk, &info);
+ }
+
+@@ -1177,13 +1217,14 @@ virtio_transport_send_response(struct vsock_sock *vsk,
+ {
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RESPONSE,
+- .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .remote_cid = le64_to_cpu(pkt->hdr.src_cid),
+ .remote_port = le32_to_cpu(pkt->hdr.src_port),
+ .reply = true,
+ .vsk = vsk,
+ };
+
++ info.type = virtio_transport_get_type(sk_vsock(vsk));
++
+ return virtio_transport_send_pkt_info(vsk, &info);
+ }
--
2.25.1