This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 91376b8423326eb1758f9e367740ce0d3f354c64
Author: Yongrong Wang <[email protected]>
AuthorDate: Mon Mar 10 10:30:00 2025 +0800

    net/vsock: add vsock framework
    
    1. Vsock framework, support G2H and H2G transport register;
    2. Only support STREAM and not support SOCK_SEQPACKET/MSG_PEEK;
    
    [skip-cmake-parity]
    
    Signed-off-by: Bowen Wang <[email protected]>
    Signed-off-by: Yongrong Wang <[email protected]>
---
 net/Kconfig              |    1 +
 net/Makefile             |    1 +
 net/net_initialize.c     |    5 +
 net/socket/net_sockif.c  |    7 +
 net/vsock/CMakeLists.txt |   26 +
 net/vsock/Kconfig        |   39 +
 net/vsock/Make.defs      |   32 +
 net/vsock/vsock.h        |  137 +++
 net/vsock/vsock_addr.c   |  107 ++
 net/vsock/vsock_sockif.c | 2442 ++++++++++++++++++++++++++++++++++++++++++++++
 net/vsock/vsock_virtio.h |  105 ++
 11 files changed, 2902 insertions(+)

diff --git a/net/Kconfig b/net/Kconfig
index 6927e138ed1..55c662b0ae2 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -457,6 +457,7 @@ source "net/arp/Kconfig"
 source "net/procfs/Kconfig"
 source "net/usrsock/Kconfig"
 source "net/utils/Kconfig"
+source "net/vsock/Kconfig"
 
 config NET_STATISTICS
        bool "Collect network statistics"
diff --git a/net/Makefile b/net/Makefile
index 495775f0023..33c7171721e 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -58,6 +58,7 @@ include route/Make.defs
 include procfs/Make.defs
 include usrsock/Make.defs
 include utils/Make.defs
+include vsock/Make.defs
 endif
 
 CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)net
diff --git a/net/net_initialize.c b/net/net_initialize.c
index 8a2d54dad9a..c4792faf359 100644
--- a/net/net_initialize.c
+++ b/net/net_initialize.c
@@ -47,6 +47,7 @@
 #include "netlink/netlink.h"
 #include "route/route.h"
 #include "usrsock/usrsock.h"
+#include "vsock/vsock.h"
 
 /****************************************************************************
  * Public Functions
@@ -108,6 +109,10 @@ void net_initialize(void)
 
   usrsock_initialize();
 #endif
+
+#ifdef CONFIG_NET_VSOCK
+  vsock_initialize();
+#endif
 }
 
 #endif /* CONFIG_NET */
diff --git a/net/socket/net_sockif.c b/net/socket/net_sockif.c
index 90c4a9589be..aafb6c0ff6e 100644
--- a/net/socket/net_sockif.c
+++ b/net/socket/net_sockif.c
@@ -42,6 +42,7 @@
 #include "bluetooth/bluetooth.h"
 #include "ieee802154/ieee802154.h"
 #include "socket/socket.h"
+#include "vsock/vsock.h"
 
 /****************************************************************************
  * Private Function Prototypes
@@ -266,6 +267,12 @@ net_sockif(sa_family_t family, int type, int protocol)
         break;
 #endif
 
+#ifdef CONFIG_NET_VSOCK
+      case PF_VSOCK:
+        sockif = &g_vsock_sockif;
+        break;
+#endif
+
       default:
         nerr("ERROR: Address family unsupported: %d\n", family);
     }
diff --git a/net/vsock/CMakeLists.txt b/net/vsock/CMakeLists.txt
new file mode 100644
index 00000000000..839d7ff9898
--- /dev/null
+++ b/net/vsock/CMakeLists.txt
@@ -0,0 +1,26 @@
+# 
##############################################################################
+# net/vsock/CMakeLists.txt
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+# Virtual Socket source files
+
+if(CONFIG_NET_VSOCK)
+  set(SRCS vsock_sockif.c vsock_addr.c)
+  target_sources(net PRIVATE ${SRCS})
+endif()
diff --git a/net/vsock/Kconfig b/net/vsock/Kconfig
new file mode 100644
index 00000000000..58ee4af8807
--- /dev/null
+++ b/net/vsock/Kconfig
@@ -0,0 +1,39 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+menu "Virtual Socket networking stack API"
+
+config NET_VSOCK
+       bool
+
+if NET_VSOCK
+
+config NET_VSOCK_RX_BUFSIZE
+       int "Virtual Socket rx buffer size"
+       default 2048
+
+config NET_VSOCK_NPOLLWAITERS
+       int "Virtual Socket poll waiter number"
+       default 4
+
+config NET_VSOCK_PKT_BUFSIZE
+       int "Virtual Socket packet tx buffer size"
+       default 2048
+
+config NET_VSOCK_PKT_BUFCOUNT
+       int "Virtual Socket packet virtqueue buf count"
+       default 16
+
+config NET_VSOCK_WORK_PRIORITY
+       int "Virtual Socket work priority"
+       default 223
+
+config NET_VSOCK_WORK_STACKSIZE
+       int "Virtual Socket work stack size"
+       default DEFAULT_TASK_STACKSIZE
+
+endif # NET_VSOCK
+
+endmenu # Virtual Socket networking stack API
diff --git a/net/vsock/Make.defs b/net/vsock/Make.defs
new file mode 100644
index 00000000000..db599d61ed3
--- /dev/null
+++ b/net/vsock/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# net/vsock/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# Virtio Socket source files
+
+ifeq ($(CONFIG_NET_VSOCK),y)
+
+SOCK_CSRCS += vsock_sockif.c vsock_addr.c
+
+# Include Virtio Socket build support
+
+DEPPATH += --dep-path vsock
+VPATH += :vsock
+
+endif # CONFIG_NET_VSOCK
diff --git a/net/vsock/vsock.h b/net/vsock/vsock.h
new file mode 100644
index 00000000000..773a9e36bd3
--- /dev/null
+++ b/net/vsock/vsock.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+ * net/vsock/vsock.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __NET_VSOCK_VSOCK_H
+#define __NET_VSOCK_VSOCK_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_NET_VSOCK
+
+#include <debug.h>
+
+#include <netpacket/vm_sockets.h>
+#include <nuttx/list.h>
+#include <nuttx/net/net.h>
+#include <nuttx/virtio/virtio.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define VSOCK_PKT_LEN   sizeof(struct vsock_pkt_s)
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+struct vsock_pkt_s
+{
+  size_t                vbidx;
+  size_t                vboff;
+  size_t                vbcnt;
+  FAR void             *priv;
+  struct virtqueue_buf  vb[CONFIG_NET_VSOCK_PKT_BUFCOUNT];
+};
+
+struct vsock_transport_s;
+struct vsock_transport_ops_s
+{
+  /* Virtio/Vhost/Local transport operations */
+
+  CODE uint64_t (*get_localcid)(FAR struct vsock_transport_s *t);
+  CODE uint64_t (*get_remotecid)(FAR struct vsock_transport_s *t);
+  CODE int (*alloc_pkt)(FAR struct vsock_transport_s *t,
+                        FAR struct vsock_pkt_s *pkt,
+                        size_t data_len);
+  CODE ssize_t (*send_pkt)(FAR struct vsock_transport_s *t,
+                           FAR struct vsock_pkt_s *pkt);
+};
+
+struct vsock_transport_s
+{
+  FAR const struct vsock_transport_ops_s *ops;
+  FAR struct list_node                    node;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern const struct sock_intf_s g_vsock_sockif;
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+static inline_function FAR struct vsock_hdr_s *
+vsock_pkt2hdr(FAR struct vsock_pkt_s *pkt)
+{
+  return (FAR struct vsock_hdr_s *)pkt->vb[0].buf;
+}
+
+void vsock_recv_pkt(FAR struct vsock_transport_s *t,
+                    FAR struct vsock_pkt_s *pkt);
+
+int vsock_queue_work(FAR struct work_s *work, worker_t worker, FAR void *arg,
+                     clock_t delay);
+
+/* Register vsock transport layer to the vsock interface layer, should be
+ * called by the vsock transport layer only.
+ */
+
+void vsock_transport_register(FAR struct vsock_transport_s *t);
+
+/* Virtual socket address operation, these functions implemented in
+ * vsock_addr.c
+ */
+
+int vsock_addr_is_valid(FAR const struct sockaddr *addr, socklen_t addrlen);
+int vsock_addr_set(FAR struct sockaddr_vm *vmaddr,
+                   FAR const struct sockaddr *addr,
+                   socklen_t addrlen);
+int vsock_addr_get(FAR const struct sockaddr_vm *vmaddr,
+                   FAR struct sockaddr *addr,
+                   FAR socklen_t *addrlen);
+void vsock_addr_init(FAR struct sockaddr_vm *addr, uint64_t cid,
+                     uint32_t port);
+bool vsock_addr_equal(FAR const struct sockaddr_vm *addr1,
+                      FAR const struct sockaddr_vm *addr2);
+
+/* Virtual socket initialize */
+
+int vsock_initialize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_VSOCK */
+
+#endif /* __NET_VSOCK_VSOCK_H */
diff --git a/net/vsock/vsock_addr.c b/net/vsock/vsock_addr.c
new file mode 100644
index 00000000000..159fd2a1c78
--- /dev/null
+++ b/net/vsock/vsock_addr.c
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * net/vsock/vsock_addr.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <errno.h>
+#include <string.h>
+
+#include "vsock/vsock.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int vsock_addr_is_valid(FAR const struct sockaddr *addr, socklen_t addrlen)
+{
+  FAR const struct sockaddr_vm *vmaddr =
+    (FAR const struct sockaddr_vm *)addr;
+
+  if (addrlen < sizeof(struct sockaddr_vm))
+    {
+      return -EINVAL;
+    }
+
+  if (vmaddr == NULL)
+    {
+      return -EFAULT;
+    }
+
+  if (vmaddr->svm_family != AF_VSOCK)
+    {
+      return -EAFNOSUPPORT;
+    }
+
+  if (vmaddr->svm_flags & ~VMADDR_FLAG_TO_HOST)
+    {
+      return -EINVAL;
+    }
+
+  return 0;
+}
+
+int vsock_addr_set(FAR struct sockaddr_vm *vmaddr,
+                   FAR const struct sockaddr *addr,
+                   socklen_t addrlen)
+{
+  int ret;
+
+  ret = vsock_addr_is_valid(addr, addrlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memcpy(vmaddr, addr, sizeof(struct sockaddr_vm));
+  return 0;
+}
+
+int vsock_addr_get(FAR const struct sockaddr_vm *vmaddr,
+                   FAR struct sockaddr *addr,
+                   FAR socklen_t *addrlen)
+{
+  if (addr == NULL || addrlen == NULL ||
+      *addrlen < sizeof(struct sockaddr_vm))
+    {
+      return -EINVAL;
+    }
+
+  memcpy(addr, vmaddr, sizeof(struct sockaddr_vm));
+  *addrlen = sizeof(struct sockaddr_vm);
+  return 0;
+}
+
+void vsock_addr_init(FAR struct sockaddr_vm *addr, uint64_t cid,
+                     uint32_t port)
+{
+  memset(addr, 0, sizeof(*addr));
+  addr->svm_family = AF_VSOCK;
+  addr->svm_cid    = cid;
+  addr->svm_port   = port;
+}
+
+bool vsock_addr_equal(FAR const struct sockaddr_vm *addr1,
+                      FAR const struct sockaddr_vm *addr2)
+{
+  return addr1->svm_cid == addr2->svm_cid &&
+         addr1->svm_port == addr2->svm_port;
+}
diff --git a/net/vsock/vsock_sockif.c b/net/vsock/vsock_sockif.c
new file mode 100644
index 00000000000..670044e3779
--- /dev/null
+++ b/net/vsock/vsock_sockif.c
@@ -0,0 +1,2442 @@
+/****************************************************************************
+ * net/vsock/vsock_sockif.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <nuttx/circbuf.h>
+#include <nuttx/nuttx.h>
+#include <nuttx/spinlock.h>
+
+#include "socket/socket.h"
+#include "vsock/vsock.h"
+#include "vsock/vsock_virtio.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Vsock notify type */
+
+#define VSOCK_NOTIFY_ERROR       0
+#define VSOCK_NOTIFY_LISTEN      1
+#define VSOCK_NOTIFY_RECV        2
+#define VSOCK_NOTIFY_SEND        3
+#define VSOCK_NOTIFY_SHUTDOWN    4
+
+#define VSOCK_IS_SHUTDOWN_RD(s)  ((s) == SHUT_RD)
+#define VSOCK_IS_SHUTDOWN_WR(s)  ((s) == SHUT_WR)
+#define VSOCK_IS_SHUTDOWN(s)     ((s) == SHUT_RDWR)
+
+#define VSOCK_LAST_RESERVED_PORT 1024
+
+#define VSOCK_CLOSE_TIMEOUT      SEC2TICK(8)
+
+/* Virtio Transport function */
+
+#define VSOCK_GET_LOCALCID(t)    (t)->ops->get_localcid(t)
+#define VSOCK_GET_REMOTECID(t)   (t)->ops->get_remotecid(t)
+#define VSOCK_ALLOC_PKT(t,p,c)   (t)->ops->alloc_pkt(t,p,c)
+#define VSOCK_SEND_PKT(t,p)      (t)->ops->send_pkt(t,p)
+
+#ifdef VSOCK_DEBUG
+#  define vsockdbg               _err
+#else
+#  define vsockdbg(fmt, ...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct vsock_msg_s
+{
+  struct uio                    uio;
+
+  /* Recv msg: total capacity to receive data
+   * Send msg: total data length to send
+   */
+
+  size_t                        len;
+};
+
+struct vsock_conn_s
+{
+  /* Common prologue of all connection structures. */
+
+  struct socket_conn_s          sconn;
+
+  FAR struct vsock_transport_s *transport;
+  struct sockaddr_vm            local_addr;
+  struct sockaddr_vm            remote_addr;
+  atomic_int                    ref;
+
+  /* Save bound or connected list node */
+
+  struct list_node              node;
+
+  /* For accept connection, this is the list node in server child list
+   */
+
+  struct list_node              child;
+
+  spinlock_t                    poll_lock;
+  FAR struct pollfd_s          *fds[CONFIG_NET_VSOCK_NPOLLWAITERS];
+
+  /* Rx */
+
+  rmutex_t                      rx_lock;
+  sem_t                         rx_sem;
+  struct circbuf_s              rx_buf;
+  FAR struct vsock_msg_s       *rx_msg;
+  size_t                        rx_lowat;
+
+  spinlock_t                    cnt_lock;
+  uint32_t                      rx_fwd_cnt;
+  uint32_t                      rx_last_fwd_cnt;
+  uint32_t                      rx_buf_alloc;
+
+  /* Tx */
+
+  uint32_t                      tx_cnt;
+  uint32_t                      tx_fwd_cnt;
+  uint32_t                      tx_buf_alloc;
+
+  rmutex_t                      tx_lock;
+  sem_t                         tx_sem;
+
+  /* Shutdown flags */
+
+  uint32_t                      shutdown;
+
+  /* Close timeout work */
+
+  struct work_s                 close_work;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef VSOCK_DEBUG
+static FAR const char *g_vsock_op[] =
+{
+  [VIRTIO_VSOCK_OP_INVALID]        = "INVALID",
+  [VIRTIO_VSOCK_OP_REQUEST]        = "REQUEST",
+  [VIRTIO_VSOCK_OP_RESPONSE]       = "RESPONSE",
+  [VIRTIO_VSOCK_OP_RST]            = "RST",
+  [VIRTIO_VSOCK_OP_SHUTDOWN]       = "SHUTDOWN",
+  [VIRTIO_VSOCK_OP_RW]             = "RW",
+  [VIRTIO_VSOCK_OP_CREDIT_UPDATE]  = "CREDIT_UPDATE",
+  [VIRTIO_VSOCK_OP_CREDIT_REQUEST] = "CREDIT_REQUEST",
+};
+#endif
+
+static_assert(SHUT_RD == VIRTIO_VSOCK_SHUTDOWN_RECV);
+static_assert(SHUT_WR == VIRTIO_VSOCK_SHUTDOWN_SEND);
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int        vsock_setup(FAR struct socket *psock);
+static sockcaps_t vsock_sockcaps(FAR struct socket *psock);
+static void       vsock_addref(FAR struct socket *psock);
+static int        vsock_bind(FAR struct socket *psock,
+                             FAR const struct sockaddr *addr,
+                             socklen_t addrlen);
+static int        vsock_getsockname(FAR struct socket *psock,
+                                    FAR struct sockaddr *addr,
+                                    FAR socklen_t *addrlen);
+static int        vsock_getpeername(FAR struct socket *psock,
+                                    FAR struct sockaddr *addr,
+                                    FAR socklen_t *addrlen);
+static int        vsock_listen(FAR struct socket *psock, int backlog);
+static int        vsock_connect(FAR struct socket *psock,
+                                FAR const struct sockaddr *addr,
+                                socklen_t addrlen);
+static int        vsock_accept(FAR struct socket *psock,
+                               FAR struct sockaddr *addr,
+                               FAR socklen_t *addrlen,
+                               FAR struct socket *newsock, int flags);
+static int        vsock_poll(FAR struct socket *psock,
+                             FAR struct pollfd_s *fds, bool setup);
+static ssize_t    vsock_sendmsg(FAR struct socket *psock,
+                                FAR const struct msghdr *msg, int flags);
+static ssize_t    vsock_recvmsg(FAR struct socket *psock,
+                                FAR struct msghdr *msg, int flags);
+static int        vsock_close(FAR struct socket *psock);
+static int        vsock_ioctl(FAR struct socket *psock, int cmd,
+                              unsigned long arg);
+static int        vsock_shutdown(FAR struct socket *psock, int how);
+#ifdef CONFIG_NET_SOCKOPTS
+static int        vsock_getsockopt(FAR struct socket *psock, int level,
+                                   int option, FAR void *value,
+                                   FAR socklen_t *value_len);
+static int        vsock_setsockopt(FAR struct socket *psock, int level,
+                                   int option, FAR const void *value,
+                                   socklen_t value_len);
+#endif
+
+#ifdef VSOCK_DEBUG
+static void vsock_dump_pkt(FAR struct vsock_pkt_s *pkt,
+                           FAR const char *msg, bool dumpbuf);
+#else
+#  define vsock_dump_pkt(pkt, msg, dumpbuf)
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct sock_intf_s g_vsock_sockif =
+{
+  vsock_setup,       /* si_setup */
+  vsock_sockcaps,    /* si_sockcaps */
+  vsock_addref,      /* si_addref */
+  vsock_bind,        /* si_bind */
+  vsock_getsockname, /* si_getsockname */
+  vsock_getpeername, /* si_getpeername */
+  vsock_listen,      /* si_listen */
+  vsock_connect,     /* si_connect */
+  vsock_accept,      /* si_accept */
+  vsock_poll,        /* si_poll */
+  vsock_sendmsg,     /* si_sendmsg */
+  vsock_recvmsg,     /* si_recvmsg */
+  vsock_close,       /* si_close */
+  vsock_ioctl,       /* si_ioctl */
+  NULL,              /* si_socketpair */
+  vsock_shutdown     /* si_shutdown */
+#ifdef CONFIG_NET_SOCKOPTS
+  , vsock_getsockopt /* si_getsockopt */
+  , vsock_setsockopt /* si_setsockopt */
+#endif
+#ifdef CONFIG_NET_SENDFILE
+  , NULL             /* si_sendfile */
+#endif
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static atomic_t g_vsock_port = VSOCK_LAST_RESERVED_PORT;
+
+static FAR struct kwork_wqueue_s *g_vsock_wqueue = NULL;
+
+/* List and their locks */
+
+static struct list_node g_vsock_conn = LIST_INITIAL_VALUE(g_vsock_conn);
+static struct list_node g_vsock_transport =
+  LIST_INITIAL_VALUE(g_vsock_transport);
+
+static spinlock_t g_vsock_conn_lock = SP_UNLOCKED;
+static spinlock_t g_vsock_transport_lock = SP_UNLOCKED;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vsock_lock/unlock
+ ****************************************************************************/
+
+static inline_function void vsock_lock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_lock(&conn->rx_lock);
+  nxrmutex_lock(&conn->tx_lock);
+}
+
+static inline_function void vsock_unlock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_unlock(&conn->tx_lock);
+  nxrmutex_unlock(&conn->rx_lock);
+}
+
+/****************************************************************************
+ * Name: vsock_rx_lock/unlock
+ ****************************************************************************/
+
+static inline_function void vsock_rx_lock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_lock(&conn->rx_lock);
+}
+
+static inline_function void vsock_rx_unlock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_unlock(&conn->rx_lock);
+}
+
+/****************************************************************************
+ * Name: vsock_rx_lock/unlock
+ ****************************************************************************/
+
+static inline_function void vsock_tx_lock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_lock(&conn->tx_lock);
+}
+
+static inline_function void vsock_tx_unlock(FAR struct vsock_conn_s *conn)
+{
+  nxrmutex_unlock(&conn->tx_lock);
+}
+
+/****************************************************************************
+ * Name: vsock_breaklock/vsock_restorelock
+ ****************************************************************************/
+
+static void vsock_breaklock(FAR struct vsock_conn_s *conn,
+                            FAR unsigned int *rxcount,
+                            FAR unsigned int *txcount)
+{
+  nxrmutex_breaklock(&conn->tx_lock, txcount);
+  nxrmutex_breaklock(&conn->rx_lock, rxcount);
+}
+
+static void vsock_restorelock(FAR struct vsock_conn_s *conn,
+                              unsigned int rxcount, unsigned int txcount)
+{
+  nxrmutex_restorelock(&conn->rx_lock, rxcount);
+  nxrmutex_restorelock(&conn->tx_lock, txcount);
+}
+
+/****************************************************************************
+ * Name: vsock_post
+ ****************************************************************************/
+
+static inline_function void vsock_post(FAR sem_t *sem)
+{
+  int semcount = 0;
+
+  nxsem_get_value(sem, &semcount);
+  if (semcount < 1)
+    {
+      nxsem_post(sem);
+    }
+}
+
+/****************************************************************************
+ * Name: vsock_get_rx_size
+ *
+ * Description:
+ *   Helper function for vsock poll, notify the polling thread
+ *
+ ****************************************************************************/
+
+static size_t vsock_get_rx_size(FAR struct vsock_conn_s *conn)
+{
+  size_t rx_size = 0;
+
+  if (_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      rx_size = circbuf_used(&conn->rx_buf);
+      if (conn->rx_msg != NULL)
+        {
+          rx_size += conn->rx_msg->len - conn->rx_msg->uio.uio_resid;
+        }
+    }
+  else
+    {
+      vrterr("not connected\n");
+    }
+
+  return rx_size;
+}
+
+/****************************************************************************
+ * Name: vsock_poll_notify
+ *
+ * Description:
+ *   Helper function for vsock poll, notify the polling thread
+ *
+ ****************************************************************************/
+
+static inline_function void vsock_poll_notify(FAR struct vsock_conn_s *conn,
+                                              pollevent_t eventset)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave_nopreempt(&conn->poll_lock);
+  poll_notify(conn->fds, CONFIG_NET_VSOCK_NPOLLWAITERS, eventset);
+  spin_unlock_irqrestore_nopreempt(&conn->poll_lock, flags);
+}
+
+static void vsock_notify(FAR struct vsock_conn_s *conn, int type)
+{
+  switch (type)
+    {
+      case VSOCK_NOTIFY_ERROR:
+        vsock_post(&conn->rx_sem);
+        vsock_post(&conn->tx_sem);
+        vsock_poll_notify(conn, POLLIN | POLLOUT);
+        break;
+      case VSOCK_NOTIFY_LISTEN:
+        vsock_post(&conn->rx_sem);
+        vsock_poll_notify(conn, POLLIN);
+        break;
+      case VSOCK_NOTIFY_SEND:
+        vsock_post(&conn->tx_sem);
+        vsock_poll_notify(conn, POLLOUT);
+        break;
+      case VSOCK_NOTIFY_RECV:
+        if (vsock_get_rx_size(conn) >= conn->rx_lowat)
+          {
+            vsock_post(&conn->rx_sem);
+            vsock_poll_notify(conn, POLLIN);
+          }
+        break;
+      case VSOCK_NOTIFY_SHUTDOWN:
+        if (conn->shutdown & SHUT_RD)
+          {
+            vsock_post(&conn->rx_sem);
+            vsock_poll_notify(conn, POLLIN);
+          }
+
+        if (conn->shutdown & SHUT_WR)
+          {
+            vsock_post(&conn->tx_sem);
+            vsock_poll_notify(conn, POLLOUT);
+          }
+        break;
+    }
+}
+
+/****************************************************************************
+ * Name: vsock_assgin_transport
+ *
+ * Description:
+ *   Assign the vsock transport to the vsock connection and call the
+ *   transport init to initialize the transport vsock connection.
+ *
+ ****************************************************************************/
+
+static int vsock_assgin_transport(FAR struct vsock_conn_s *conn)
+{
+  FAR struct vsock_transport_s *t;
+  uint64_t remote_cid;
+  irqstate_t flags;
+
+  remote_cid = conn->remote_addr.svm_cid;
+  flags = spin_lock_irqsave(&g_vsock_transport_lock);
+  list_for_every_entry(&g_vsock_transport, t, struct vsock_transport_s, node)
+    {
+      if (VSOCK_GET_REMOTECID(t) == remote_cid)
+        {
+          conn->transport = t;
+          break;
+        }
+    }
+
+  spin_unlock_irqrestore(&g_vsock_transport_lock, flags);
+
+  if (conn->transport == NULL)
+    {
+      vrterr("Transport not found\n");
+      return -ENOTSUP;
+    }
+
+  return circbuf_resize(&conn->rx_buf, conn->rx_buf_alloc);
+}
+
+/****************************************************************************
+ * Name: vsock_free
+ *
+ * Description:
+ *   Directly free the vsock connection. Before call this function, other
+ *   connection resource should has been freed, such as transport uninit
+ *
+ ****************************************************************************/
+
+static void vsock_free(FAR struct vsock_conn_s *conn)
+{
+  vsockdbg("vsock free, conn=%p\n", conn);
+  nxrmutex_destroy(&conn->rx_lock);
+  nxrmutex_destroy(&conn->tx_lock);
+  nxsem_destroy(&conn->rx_sem);
+  nxsem_destroy(&conn->tx_sem);
+  circbuf_uninit(&conn->rx_buf);
+  kmm_free(conn);
+}
+
+/****************************************************************************
+ * Name: vsock_add/sub_ref
+ *
+ * Description:
+ *   The virtio transport receive worker/thread may use this the virtual
+ *   socket connection at any time. And the User may call vsock_close to free
+ *   the connection at any time too. So every virtual socket connection
+ *   maintains a reference count for safe free the connection.
+ *   vsock_add/sub_ref() will increase/decrease the reference count, and will
+ *   cleanup the virtual socket connection resource when the reference count
+ *   equals to 0.
+ *
+ ****************************************************************************/
+
+static void vsock_add_ref(FAR struct vsock_conn_s *conn)
+{
+  atomic_fetch_add(&conn->ref, 1);
+}
+
+static void vsock_sub_ref(FAR struct vsock_conn_s *conn)
+{
+  if (atomic_fetch_sub(&conn->ref, 1) <= 1)
+    {
+      vsock_free(conn);
+    }
+}
+
+/****************************************************************************
+ * Name: vsock_alloc
+ *
+ * Description:
+ *   Alloc a vsock connection and initialize it.
+ *
+ ****************************************************************************/
+
+static FAR struct vsock_conn_s *vsock_alloc(void)
+{
+  FAR struct vsock_conn_s *conn;
+  int ret;
+
+  conn = kmm_zalloc(sizeof(*conn));
+  if (conn == NULL)
+    {
+      vrterr("Alloc vsock conn failed\n");
+      return NULL;
+    }
+
+  ret = circbuf_init(&conn->rx_buf, NULL, 0);
+  if (ret < 0)
+    {
+      kmm_free(conn);
+      vrterr("circbuf_init failed\n");
+      return NULL;
+    }
+
+  conn->rx_lowat = 1;
+  conn->rx_buf_alloc = CONFIG_NET_VSOCK_RX_BUFSIZE;
+  list_initialize(&conn->child);
+
+  list_initialize(&conn->node);
+  vsock_addr_init(&conn->local_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+  vsock_addr_init(&conn->remote_addr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+
+  nxrmutex_init(&conn->rx_lock);
+  nxrmutex_init(&conn->tx_lock);
+  spin_lock_init(&conn->poll_lock);
+  spin_lock_init(&conn->cnt_lock);
+  nxsem_init(&conn->rx_sem, 0, 0);
+  nxsem_init(&conn->tx_sem, 0, 0);
+  vsock_add_ref(conn);
+  return conn;
+}
+
+/****************************************************************************
+ * Name: vsock_find_bound/connected_conn
+ *
+ * Description:
+ *   Find the bound or connected connection in corresponding list.
+ *   When received a packet from peer, transport layer call these functions
+ *   to get the corresponding connection.
+ *
+ *   vsock_find_bound_conn(): Find bound connection
+ *   vsock_find_connected_conn(): Find connection connection
+ *
+ ****************************************************************************/
+
+static FAR struct vsock_conn_s *
+vsock_find_bound_conn(FAR const struct sockaddr_vm *addr)
+{
+  FAR const struct sockaddr_vm *local;
+  FAR struct vsock_conn_s *conn;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&g_vsock_conn_lock);
+  list_for_every_entry(&g_vsock_conn, conn, struct vsock_conn_s, node)
+    {
+      local = &conn->local_addr;
+      if (local->svm_port == addr->svm_port &&
+          (local->svm_cid == addr->svm_cid ||
+          local->svm_cid == VMADDR_CID_ANY ||
+          addr->svm_cid == VMADDR_CID_ANY))
+        {
+          vsock_add_ref(conn);
+          spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+          return conn;
+        }
+    }
+
+  spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+  return NULL;
+}
+
+static FAR struct vsock_conn_s *
+vsock_find_connected_conn(FAR const struct sockaddr_vm *remote_addr,
+                          FAR const struct sockaddr_vm *local_addr)
+{
+  FAR struct vsock_conn_s *conn;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&g_vsock_conn_lock);
+  list_for_every_entry(&g_vsock_conn, conn, struct vsock_conn_s, node)
+    {
+      if (conn->remote_addr.svm_cid == remote_addr->svm_cid &&
+          conn->remote_addr.svm_port == remote_addr->svm_port &&
+          conn->local_addr.svm_port == local_addr->svm_port &&
+          (conn->local_addr.svm_cid == VMADDR_CID_ANY ||
+          conn->local_addr.svm_cid == local_addr->svm_cid))
+        {
+          vsock_add_ref(conn);
+          spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+          return conn;
+        }
+    }
+
+  spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: vsock_insert/remove_conn
+ *
+ * Description:
+ *   The bound list maintained the connections that listen (server) for
+ *   connections or want to connect to peer connection (client).
+ *   The transport layer will find the connection in this list to handle
+ *   connection connected event.
+ *
+ *   vsock_insert_conn(): Insert a connection to the bound list
+ *   vsock_remove_conn(): Remove a connection from the bound list
+ *
+ ****************************************************************************/
+
+static inline_function void vsock_insert_conn(FAR struct vsock_conn_s *conn)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&g_vsock_conn_lock);
+  list_add_tail(&g_vsock_conn, &conn->node);
+  spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+}
+
+static inline_function void vsock_remove_conn(FAR struct vsock_conn_s *conn)
+{
+  irqstate_t flags;
+
+  vsockdbg("Remove bound, conn=%p\n", conn);
+  flags = spin_lock_irqsave(&g_vsock_conn_lock);
+  if (list_in_list(&conn->node))
+    {
+      list_delete(&conn->node);
+      list_clear_node(&conn->node);
+    }
+
+  spin_unlock_irqrestore(&g_vsock_conn_lock, flags);
+}
+
+/****************************************************************************
+ * Name: vsock_bind_internal
+ *
+ * Description:
+ *   Get the vsock connection port and add it to the bound connection list.
+ *
+ ****************************************************************************/
+
+static int vsock_bind_internal(FAR struct vsock_conn_s *conn,
+                               FAR const struct sockaddr_vm *addr)
+{
+  struct sockaddr_vm new_addr;
+
+  vsock_addr_init(&new_addr, addr->svm_cid, addr->svm_port);
+
+  if (addr->svm_port == VMADDR_PORT_ANY)
+    {
+      /* Simple method to find a port that not used by other */
+
+      for (; ; )
+        {
+          new_addr.svm_port = atomic_fetch_add(&g_vsock_port, 1);
+          if (vsock_find_bound_conn(&new_addr) == NULL)
+            {
+              goto out;
+            }
+        }
+
+      return -EADDRNOTAVAIL;
+    }
+  else
+    {
+      if (addr->svm_port < VSOCK_LAST_RESERVED_PORT)
+        {
+          return -EACCES;
+        }
+
+      if (vsock_find_bound_conn(&new_addr) != NULL)
+        {
+          return -EADDRINUSE;
+        }
+    }
+
+out:
+  vsock_addr_init(&conn->local_addr, new_addr.svm_cid, new_addr.svm_port);
+  vsock_insert_conn(conn);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: vsock_unbind_internal
+ *
+ * Description:
+ *   Remove the connection from the bound connection list and init the err
+ *   number and connection state
+ *
+ ****************************************************************************/
+
+static void vsock_unbind_internal(FAR struct vsock_conn_s *conn)
+{
+  conn->sconn.s_error = 0;
+  vsock_remove_conn(conn);
+}
+
+/****************************************************************************
+ * Name: vsock_alloc_tx_credit
+ ****************************************************************************/
+
+static inline_function uint32_t
+vsock_alloc_tx_credit(FAR struct vsock_conn_s *conn, uint32_t credit)
+{
+  uint32_t ret;
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  ret = conn->tx_buf_alloc - (conn->tx_cnt - conn->tx_fwd_cnt);
+  if (ret > credit)
+    {
+      ret = credit;
+    }
+
+  conn->tx_cnt += ret;
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_free_tx_credit
+ ****************************************************************************/
+
+static inline_function void
+vsock_free_tx_credit(FAR struct vsock_conn_s *conn, uint32_t credit)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  conn->tx_cnt -= credit;
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+}
+
+/****************************************************************************
+ * Name: vsock_get_tx_credit
+ ****************************************************************************/
+
+static inline_function size_t
+vsock_get_tx_credit(FAR struct vsock_conn_s *conn)
+{
+  irqstate_t flags;
+  size_t len;
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  len = conn->tx_buf_alloc - (conn->tx_cnt - conn->tx_fwd_cnt);
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+  return len;
+}
+
+/****************************************************************************
+ * Name: vsock_update_tx_credit
+ ****************************************************************************/
+
+static void vsock_update_tx_credit(FAR struct vsock_conn_s *conn,
+                                   FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  irqstate_t flags;
+
+  /* Listener sockets are not associated with any transport, so we are
+   * not able to take the state to see if there is space available in the
+   * remote peer, but since they are only used to receive requests, we
+   * can assume that there is always space available in the other peer.
+   */
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  conn->tx_buf_alloc = hdr->buf_alloc;
+  conn->tx_fwd_cnt = hdr->fwd_cnt;
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+}
+
+/****************************************************************************
+ * Name: vsock_msg_done
+ *
+ * Description:
+ *   Judge whether the virtual msg is full (RX) or empty (TX).
+ *
+ ****************************************************************************/
+
+static inline_function bool vsock_msg_done(FAR const struct vsock_msg_s *msg)
+{
+  return msg->uio.uio_resid == 0;
+}
+
+/****************************************************************************
+ * Name: vsock_copy_pkt2msg
+ *
+ * Description:
+ *   Copy the rx pkt data in the rx queue to the msg until the msg full or
+ *   ran out of the rx pkt data.
+ *
+ ****************************************************************************/
+
+static size_t vsock_copy_pkt2msg(FAR struct vsock_conn_s *conn,
+                                 FAR struct vsock_msg_s *msg,
+                                 FAR struct vsock_pkt_s *pkt)
+{
+  size_t ret = 0;
+
+  vsockdbg("pkt vbcnt=%zu vbidx=%zu vboff=%zu vb[0].len=%u msg used=%zu\n",
+           pkt->vbcnt, pkt->vbidx, pkt->vboff, pkt->vb[0].len,
+           msg->len - msg->uio.uio_resid);
+
+  while (!vsock_msg_done(msg) && pkt->vbidx < pkt->vbcnt &&
+         pkt->vboff <= pkt->vb[pkt->vbidx].len)
+    {
+      FAR const char *buf = pkt->vb[pkt->vbidx].buf + pkt->vboff;
+      size_t len = pkt->vb[pkt->vbidx].len - pkt->vboff;
+      size_t copied = MIN(len, msg->uio.uio_resid);
+
+      uio_copyfrom(&msg->uio, 0, buf, copied);
+      uio_advance(&msg->uio, copied);
+      if (copied >= len)
+        {
+          pkt->vbidx++;
+          pkt->vboff = 0;
+        }
+      else
+        {
+          pkt->vboff += copied;
+        }
+
+      ret += copied;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_copy_circ2msg
+ *
+ * Description:
+ *   Copy data from the circular buffer to the virtual socket message until
+ *   circular buffer empty or virtual socket message full.
+ *
+ ****************************************************************************/
+
+static size_t vsock_copy_circ2msg(FAR struct vsock_conn_s *conn,
+                                  FAR struct vsock_msg_s *msg)
+{
+  FAR struct circbuf_s *circ = &conn->rx_buf;
+  size_t ret = 0;
+
+  while (!circbuf_is_empty(circ) && !vsock_msg_done(msg))
+    {
+      size_t len;
+
+      FAR const char *buf = circbuf_get_readptr(circ, &len);
+
+      len = MIN(len, msg->uio.uio_resid);
+
+      uio_copyfrom(&msg->uio, 0, buf, len);
+      uio_advance(&msg->uio, len);
+      circbuf_readcommit(circ, len);
+      ret += len;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_copy_msg2pkt
+ ****************************************************************************/
+
+static size_t vsock_copy_msg2pkt(FAR struct vsock_pkt_s *pkt,
+                                FAR struct vsock_msg_s *msg, size_t total)
+{
+  size_t ret = 0;
+
+  DEBUGASSERT(total <= msg->uio.uio_resid);
+  while (total > 0 && pkt->vbidx < pkt->vbcnt &&
+         pkt->vboff <= pkt->vb[pkt->vbidx].len)
+    {
+      FAR void *buf = pkt->vb[pkt->vbidx].buf + pkt->vboff;
+      size_t len = pkt->vb[pkt->vbidx].len - pkt->vboff;
+
+      size_t copied = MIN(len, total);
+      uio_copyto(&msg->uio, 0, buf, copied);
+      uio_advance(&msg->uio, copied);
+      if (copied >= len)
+        {
+          pkt->vbidx++;
+          pkt->vboff = 0;
+        }
+      else
+        {
+          pkt->vboff += copied;
+        }
+
+      total -= copied;
+      ret += copied;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_copy_pkt2circ
+ *
+ * Description:
+ *   Copy the rx pkt data in the rx queue to the rx circular buffer until
+ *   the rx buffer full or ran out of the rx pkt data.
+ *
+ ****************************************************************************/
+
+static size_t vsock_copy_pkt2circ(FAR struct vsock_conn_s *conn,
+                                   FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct circbuf_s *circ = &conn->rx_buf;
+  size_t ret = 0;
+
+  vsockdbg("pkt vbcnt=%zu vbidx=%zu vboff=%zu "
+           "vb[0].len=%" PRIu32 " rxbuf used=%" PRIu32 "\n",
+           pkt->vbcnt, pkt->vbidx, pkt->vboff, pkt->vb[0].len,
+           circbuf_used(circ));
+
+  while (!circbuf_is_full(circ) && pkt->vbidx < pkt->vbcnt &&
+         pkt->vboff <= pkt->vb[pkt->vbidx].len)
+    {
+      FAR const char *buf = pkt->vb[pkt->vbidx].buf + pkt->vboff;
+      size_t len = pkt->vb[pkt->vbidx].len - pkt->vboff;
+
+      size_t copied = circbuf_write(circ, buf, len);
+
+      if (copied >= len)
+        {
+          DEBUGASSERT(copied == len);
+          pkt->vbidx++;
+          pkt->vboff = 0;
+        }
+      else
+        {
+          DEBUGASSERT(circbuf_is_full(circ));
+          pkt->vboff += copied;
+        }
+
+      ret += copied;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_send_pkt
+ ****************************************************************************/
+
+static int vsock_send_pkt(FAR struct vsock_conn_s *conn,
+                          FAR struct vsock_msg_s *msg,
+                          uint16_t op, uint32_t hdrflags,
+                          uint64_t dst_cid, uint32_t dst_port)
+{
+  struct vsock_pkt_s pkt;
+  struct vsock_hdr_s *hdr;
+  unsigned int rxcount;
+  unsigned int txcount;
+  irqstate_t flags;
+  uint32_t len;
+  int ret;
+
+  /* vsock_alloc_tx_credit might return less than len credit */
+
+  len = msg ? vsock_alloc_tx_credit(conn, msg->uio.uio_resid) : 0;
+
+  /* Do not send zero length OP_RW pkt */
+
+  if (len == 0 && op == VIRTIO_VSOCK_OP_RW)
+    {
+      return len;
+    }
+
+  memset(&pkt, 0, sizeof(struct vsock_pkt_s));
+
+  vsock_breaklock(conn, &rxcount, &txcount);
+  ret = VSOCK_ALLOC_PKT(conn->transport, &pkt, len);
+  vsock_restorelock(conn, rxcount, txcount);
+  if (ret < 0)
+    {
+      vrterr("Alloc pkt and buffer failed%d\n");
+      vsock_free_tx_credit(conn, len);
+      return ret;
+    }
+
+  if (len != 0)
+    {
+      len = vsock_copy_msg2pkt(&pkt, msg, len);
+    }
+
+  hdr = vsock_pkt2hdr(&pkt);
+  if (dst_cid == 0)
+    {
+      hdr->dst_cid  = conn->remote_addr.svm_cid;
+      hdr->dst_port = conn->remote_addr.svm_port;
+    }
+  else
+    {
+      hdr->dst_cid  = dst_cid;
+      hdr->dst_port = dst_port;
+    }
+
+  hdr->type     = VIRTIO_VSOCK_TYPE_STREAM;
+  hdr->op       = op;
+  hdr->src_cid  = VSOCK_GET_LOCALCID(conn->transport);
+  hdr->src_port = conn->local_addr.svm_port;
+  hdr->flags    = hdrflags;
+  hdr->len      = len;
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  conn->rx_last_fwd_cnt = conn->rx_fwd_cnt;
+  hdr->fwd_cnt = conn->rx_fwd_cnt;
+  hdr->buf_alloc = conn->rx_buf_alloc;
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+
+  vsock_dump_pkt(&pkt, "Send", false);
+  return VSOCK_SEND_PKT(conn->transport, &pkt);
+}
+
+/****************************************************************************
+ * Name: vsock_send_credit
+ ****************************************************************************/
+
+static int vsock_send_credit(FAR struct vsock_conn_s *conn)
+{
+  return vsock_send_pkt(conn, NULL, VIRTIO_VSOCK_OP_CREDIT_UPDATE, 0, 0, 0);
+}
+
+/****************************************************************************
+ * Name: vsock_update_rx_credit
+ ****************************************************************************/
+
+static void vsock_update_rx_credit(FAR struct vsock_conn_s *conn,
+                                   size_t size)
+{
+  irqstate_t flags;
+  uint32_t delta;
+
+  flags = spin_lock_irqsave(&conn->cnt_lock);
+  conn->rx_fwd_cnt += size;
+  delta = conn->rx_fwd_cnt - conn->rx_last_fwd_cnt;
+  spin_unlock_irqrestore(&conn->cnt_lock, flags);
+
+  vsockdbg("used=%" PRIu32 " alloc=%" PRIu32 " fwd=%" PRIu32
+           " last_fwd=%" PRIu32 "\n", delta, conn->rx_buf_alloc,
+           conn->rx_fwd_cnt, conn->rx_last_fwd_cnt);
+  if (delta >= conn->rx_buf_alloc / 2)
+    {
+      vsockdbg("Update the credit\n");
+      vsock_send_credit(conn);
+    }
+}
+
+/****************************************************************************
+ * Name: vsock_reset
+ *
+ * Description:
+ *  Normally packets are associated with a socket.  There may be no socket
+ *  if an attempt was made to connect to a socket that does not exist.
+ *
+ ****************************************************************************/
+
+static int vsock_reset(FAR struct vsock_conn_s *conn,
+                       FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+
+  /* Send RST only if the original pkt is not a RST pkt */
+
+  if (pkt && hdr->op == VIRTIO_VSOCK_OP_RST)
+    {
+      return 0;
+    }
+
+  return vsock_send_pkt(conn, NULL, VIRTIO_VSOCK_OP_RST, 0, 0, 0);
+}
+
+/****************************************************************************
+ * Name: vsock_recv_connecting
+ ****************************************************************************/
+
+static int vsock_recv_connecting(FAR struct vsock_conn_s *conn,
+                                 FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  int ret = -EINVAL;
+
+  switch (hdr->op)
+    {
+      case VIRTIO_VSOCK_OP_RESPONSE:
+        vsockdbg("conn=%p, VSOCK_CONNECTED\n", conn);
+        conn->sconn.s_flags |= _SF_CONNECTED;
+        vsock_notify(conn, VSOCK_NOTIFY_SEND);
+        return 0;
+      case VIRTIO_VSOCK_OP_RST:
+        vrterr("conn=%p, VSOCK_RST\n", conn);
+        ret = -ECONNRESET;
+        break;
+      default:
+        vrterr("conn=%p, VSOCK_ERROR, op=%d\n", conn, hdr->op);
+        break;
+    }
+
+  vsock_reset(conn, pkt);
+  conn->sconn.s_error = ret;
+  vsock_notify(conn, VSOCK_NOTIFY_ERROR);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_reset_no_conn
+ *
+ * Description:
+ *  Normally packets are associated with a socket.  There may be no socket
+ *  if an attempt was made to connect to a socket that does not exist.
+ *
+ ****************************************************************************/
+
+static int vsock_reset_no_conn(FAR struct vsock_transport_s *t,
+                               FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  FAR struct vsock_hdr_s *rhdr;
+  FAR struct vsock_pkt_s reply;
+  int ret;
+
+  /* Send RST only if the original pkt is not a RST pkt */
+
+  if (hdr->op == VIRTIO_VSOCK_OP_RST)
+    {
+      return 0;
+    }
+
+  ret = VSOCK_ALLOC_PKT(t, &reply, 0);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  rhdr           = vsock_pkt2hdr(&reply);
+  rhdr->type     = VIRTIO_VSOCK_TYPE_STREAM;
+  rhdr->op       = VIRTIO_VSOCK_OP_RST;
+  rhdr->src_cid  = hdr->dst_cid;
+  rhdr->src_port = hdr->dst_port;
+  rhdr->dst_cid  = hdr->src_cid;
+  rhdr->dst_port = hdr->src_port;
+  rhdr->flags    = 0;
+  rhdr->len      = 0;
+
+  vsock_dump_pkt(pkt, "Send", false);
+  return VSOCK_SEND_PKT(t, &reply);
+}
+
+/****************************************************************************
+ * Name: vsock_recv_listening
+ ****************************************************************************/
+
+static int vsock_recv_listening(FAR struct vsock_conn_s *conn,
+                                FAR struct vsock_transport_s *t,
+                                FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  FAR struct vsock_conn_s *newconn;
+  int ret;
+
+  if (hdr->op != VIRTIO_VSOCK_OP_REQUEST)
+    {
+      ret = -EINVAL;
+      goto reset;
+    }
+
+  newconn = vsock_alloc();
+  if (newconn == NULL)
+    {
+      ret = -ENOMEM;
+      goto reset;
+    }
+
+  vsock_addr_init(&newconn->local_addr, hdr->dst_cid, hdr->dst_port);
+  vsock_addr_init(&newconn->remote_addr, hdr->src_cid, hdr->src_port);
+  ret = vsock_assgin_transport(newconn);
+  if (ret < 0)
+    {
+      vsock_free(newconn);
+      goto reset;
+    }
+
+  list_add_tail(&conn->child, &newconn->child);
+  vsockdbg("create conn=%p dst_port=%" PRIu32 "\n", newconn, hdr->dst_port);
+
+  vsock_update_tx_credit(newconn, pkt);
+  newconn->sconn.s_flags |= _SF_CONNECTED;
+  vsock_insert_conn(newconn);
+  vsock_notify(conn, VSOCK_NOTIFY_LISTEN);
+
+  /* Send VSOCK RESPONSE to peer */
+
+  return vsock_send_pkt(newconn, NULL, VIRTIO_VSOCK_OP_RESPONSE, 0,
+                        hdr->src_cid, hdr->src_port);
+
+reset:
+  vsock_reset_no_conn(t, pkt);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_recv_enqueue
+ ****************************************************************************/
+
+static void vsock_recv_enqueue(FAR struct vsock_conn_s *conn,
+                              FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  uint32_t len = hdr->len;
+  size_t copied = 0;
+
+  DEBUGASSERT(conn != NULL);
+
+  /* If the remote peer doesn't respect the credit information
+   * (rx_buf_alloc, rx_fwd_cnt), sending more data than it can send,
+   * we should drop the packets to prevent a malicious peer
+   * from using all of our memory.
+   *
+   * This is patch follows the VIRTIO spec: "VIRTIO_VSOCK_OP_RW data
+   * packets MUST only be transmitted when the peer has sufficient
+   * free buffer space for the payload"
+   */
+
+  if (len > conn->rx_buf_alloc)
+    {
+      return;
+    }
+
+  /* Copy buffer to the user msg if user is waiting */
+
+  if (conn->rx_msg != NULL)
+    {
+      copied = vsock_copy_pkt2msg(conn, conn->rx_msg, pkt);
+    }
+
+  if (copied > 0)
+    {
+      vsock_update_rx_credit(conn, copied);
+    }
+
+  /* If still has data in rx pkt, copy to socket buffer */
+
+  copied += vsock_copy_pkt2circ(conn, pkt);
+  DEBUGASSERT(copied == len);
+}
+
+/****************************************************************************
+ * Name: vsock_recv_connected
+ ****************************************************************************/
+
+static int vsock_recv_connected(FAR struct vsock_conn_s *conn,
+                                FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+
+  switch (hdr->op)
+    {
+      case VIRTIO_VSOCK_OP_RW:
+        vsock_recv_enqueue(conn, pkt);
+        vsock_notify(conn, VSOCK_NOTIFY_RECV);
+        break;
+      case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
+        vsock_send_credit(conn);
+        break;
+      case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+        vsock_notify(conn, VSOCK_NOTIFY_SEND);
+        break;
+      case VIRTIO_VSOCK_OP_SHUTDOWN:
+        if (hdr->flags & VIRTIO_VSOCK_SHUTDOWN_RECV)
+          {
+            conn->shutdown |= SHUT_WR;
+          }
+
+        if (hdr->flags & VIRTIO_VSOCK_SHUTDOWN_SEND)
+          {
+            conn->shutdown |= SHUT_RD;
+          }
+
+        if (VSOCK_IS_SHUTDOWN(conn->shutdown))
+          {
+            vsockdbg("Shutdown and Reset, hdr->flags=0x%x\n", hdr->flags);
+            vsock_reset(conn, pkt);
+          }
+
+        vsock_notify(conn, VSOCK_NOTIFY_SHUTDOWN);
+        break;
+      case VIRTIO_VSOCK_OP_RST:
+        vsockdbg("Reset\n");
+        vsock_notify(conn, VSOCK_NOTIFY_SHUTDOWN);
+        break;
+      default:
+        return -EINVAL;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: vsock_recv_closing
+ ****************************************************************************/
+
+static void vsock_recv_closing(FAR struct vsock_conn_s *conn,
+                               FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+
+  if (hdr->op == VIRTIO_VSOCK_OP_RST)
+    {
+      work_cancel_sync_wq(g_vsock_wqueue, &conn->close_work);
+      vsock_remove_conn(conn);
+      vsock_sub_ref(conn);
+    }
+}
+
+/****************************************************************************
+ * Name: vsock_close_work
+ ****************************************************************************/
+
+static void vsock_close_work(FAR void *arg)
+{
+  FAR struct vsock_conn_s *conn = arg;
+
+  vsockdbg("close_work conn, conn=%p\n", conn);
+  vsock_lock(conn);
+
+  /* Send RST to the peer */
+
+  vsock_reset(conn, NULL);
+  vsock_remove_conn(conn);
+
+  vsock_unlock(conn);
+  vsock_sub_ref(conn);
+}
+
+/****************************************************************************
+ * Name: vsock_setup
+ *
+ * Description:
+ *   Called for socket() to verify that the provided socket type and
+ *   protocol are usable by this address family.  Perform any family-
+ *   specific socket fields.
+ *
+ *   Only support socket type SOCK_STREAM will be supported
+ *   later.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a user allocated socket structure
+ *            to be initialized.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success.  Otherwise, a negated errno value is
+ *   returned.
+ *
+ ****************************************************************************/
+
+static int vsock_setup(FAR struct socket *psock)
+{
+  FAR struct vsock_conn_s *conn;
+
+  if (psock->s_type == SOCK_STREAM)
+    {
+      conn = vsock_alloc();
+      if (conn == NULL)
+        {
+          return -ENOMEM;
+        }
+
+      psock->s_conn = conn;
+      return OK;
+    }
+
+  return -ENOTSUP;
+}
+
+/****************************************************************************
+ * Name: vsock_sockcaps
+ *
+ * Description:
+ *   Return the bit encoded capabilities of this socket.
+ *
+ * Input Parameters:
+ *   psock - Socket structure of the socket whose capabilities are being
+ *           queried.
+ *
+ * Returned Value:
+ *   The set of socket capabilities is returned.
+ *
+ ****************************************************************************/
+
+static sockcaps_t vsock_sockcaps(FAR struct socket *psock)
+{
+  return SOCKCAP_NONBLOCKING;
+}
+
+/****************************************************************************
+ * Name: vsock_addref
+ *
+ * Description:
+ *   Increment the reference count on the underlying connection structure.
+ *
+ * Input Parameters:
+ *   psock - Socket structure of the socket whose reference count will be
+ *           incremented.
+ *
+ ****************************************************************************/
+
+static void vsock_addref(FAR struct socket *psock)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+
+  vsock_add_ref(conn);
+}
+
+/****************************************************************************
+ * Name: vsock_bind
+ *
+ * Description:
+ *   Validate the sockaddr and call vsock_bind_internal() to get vm port and
+ *   add connection to the bound list to wait peer connect()
+ *
+ * Input Parameters:
+ *   psock    Socket structure of the socket to bind
+ *   addr     Socket local address
+ *   addrlen  Length of 'addr'
+ *
+ * Returned Value:
+ *   0 on success;  A negated errno value is returned on failure.  See
+ *   bind() for a list a appropriate error values.
+ *
+ ****************************************************************************/
+
+static int vsock_bind(FAR struct socket *psock,
+                      FAR const struct sockaddr *addr,
+                      socklen_t addrlen)
+{
+  FAR const struct sockaddr_vm *vmaddr =
+    (FAR const struct sockaddr_vm *)addr;
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret;
+
+  ret = vsock_addr_is_valid(addr, addrlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  vsock_lock(conn);
+  ret = vsock_bind_internal(conn, vmaddr);
+  vsock_unlock(conn);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_getsockname
+ *
+ * Description:
+ *   The vsock_getsockname() function retrieves the locally-bound name of
+ *   the specified virtual socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
+ *
+ * Input Parameters:
+ *   psock    Socket structure of the socket to be queried
+ *   addr     sockaddr structure to receive data [out]
+ *   addrlen  Length of sockaddr structure [in/out]
+ *
+ * Returned Value:
+ *   On success, 0 is returned, the 'addr' argument points to the address
+ *   of the socket, and the 'addrlen' argument points to the length of the
+ *   address.  Otherwise, a negated errno value is returned.  See
+ *   getsockname() for the list of appropriate error numbers.
+ *
+ ****************************************************************************/
+
+static int vsock_getsockname(FAR struct socket *psock,
+                             FAR struct sockaddr *addr,
+                             FAR socklen_t *addrlen)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret;
+
+  ret = vsock_addr_get(&conn->local_addr, addr, addrlen);
+  if (ret >= 0 && conn->transport != NULL)
+    {
+      FAR struct sockaddr_vm *vmaddr = (FAR struct sockaddr_vm *)addr;
+
+      vmaddr->svm_cid = VSOCK_GET_LOCALCID(conn->transport);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_getpeername
+ *
+ * Description:
+ *   The vsock_getpeername() function retrieves the remote-connected name of
+ *   the specified virtual socket, stores this address in the sockaddr
+ *   structure pointed to by the 'addr' argument, and stores the length of
+ *   this address in the object pointed to by the 'addrlen' argument.
+ *
+ * Parameters:
+ *   psock    Socket structure of the socket to be queried
+ *   addr     sockaddr structure to receive data [out]
+ *   addrlen  Length of sockaddr structure [in/out]
+ *
+ * Returned Value:
+ *   On success, 0 is returned, the 'addr' argument points to the address
+ *   of the socket, and the 'addrlen' argument points to the length of the
+ *   address.  Otherwise, a negated errno value is returned.  See
+ *   getpeername() for the list of appropriate error numbers.
+ *
+ ****************************************************************************/
+
+static int vsock_getpeername(FAR struct socket *psock,
+                             FAR struct sockaddr *addr,
+                             FAR socklen_t *addrlen)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+
+  vsock_addr_get(&conn->remote_addr, addr, addrlen);
+  return 0;
+}
+
+/****************************************************************************
+ * Name: vsock_listen
+ *
+ * Description:
+ *   To accept connections, a socket is first created with psock_socket(), a
+ *   willingness to accept incoming connections and a queue limit for
+ *   incoming connections are specified with psock_listen(), and then the
+ *   connections are accepted with psock_accept().  For the case of local
+ *   Unix sockets, psock_listen() calls this function.  The psock_listen()
+ *   call applies only to sockets of type SOCK_STREAM.
+ *
+ * Input Parameters:
+ *   psock    Reference to an internal, boound socket structure.
+ *   backlog  The maximum length the queue of pending connections may grow.
+ *            If a connection request arrives with the queue full, the client
+ *            may receive an error with an indication of ECONNREFUSED or,
+ *            if the underlying protocol supports retransmission, the request
+ *            may be ignored so that retries succeed.
+ *
+ * Returned Value:
+ *   On success, zero is returned. On error, a negated errno value is
+ *   returned.  See listen() for the set of appropriate error values.
+ *
+ ****************************************************************************/
+
+static int vsock_listen(FAR struct socket *psock, int backlog)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+
+  if (psock->s_type != SOCK_STREAM)
+    {
+      return -ENOSYS;
+    }
+
+  if (!_SS_ISBOUND(conn->sconn.s_flags) || backlog <= 0)
+    {
+      return -EINVAL;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: vsock_connect
+ *
+ * Description:
+ *   vsock_connect() connects the virtual socket referred to by the structure
+ *   'psock' to the address specified by 'addr'. The addrlen argument
+ *   specifies the size of 'addr'.  The format of the address in 'addr' is
+ *   determined by the address space of the socket 'psock'.
+ *
+ * Input Parameters:
+ *   psock     Pointer to a socket structure initialized by psock_socket()
+ *   addr      Server address (form depends on type of socket)
+ *   addrlen   Length of actual 'addr'
+ *
+ * Returned Value:
+ *   0 on success; a negated errno value on failure.  See connect() for the
+ *   list of appropriate errno values to be returned.
+ *
+ ****************************************************************************/
+
+static int vsock_connect(FAR struct socket *psock,
+                         FAR const struct sockaddr *addr,
+                         socklen_t addrlen)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  FAR struct sockaddr_vm vmaddr;
+  int ret;
+
+  if (_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      return -EISCONN;
+    }
+
+  /* Set the remote address */
+
+  ret = vsock_addr_set(&conn->remote_addr, addr, addrlen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  vsock_lock(conn);
+
+  /* Get the local port and insert to the bound list */
+
+  vsock_addr_init(&vmaddr, VMADDR_CID_ANY, VMADDR_PORT_ANY);
+  ret = vsock_bind_internal(conn, &vmaddr);
+  if (ret < 0)
+    {
+      goto out;
+    }
+
+  conn->sconn.s_flags |= _SF_BOUND;
+
+  /* Get transport function */
+
+  ret = vsock_assgin_transport(conn);
+  if (ret < 0)
+    {
+      goto err_with_bind;
+    }
+
+  /* Send connect msg */
+
+  ret = vsock_send_pkt(conn, NULL, VIRTIO_VSOCK_OP_REQUEST, 0, 0, 0);
+  if (ret < 0)
+    {
+      goto err_with_bind;
+    }
+
+  if (_SS_ISNONBLOCK(conn->sconn.s_flags))
+    {
+      ret = -EINPROGRESS;
+      goto out;
+    }
+
+  vsockdbg("conn=%p\n", conn);
+  vsock_unlock(conn);
+  ret = net_sem_timedwait(&conn->tx_sem,
+                          _SO_TIMEOUT(conn->sconn.s_sndtimeo));
+  vsock_lock(conn);
+  if (conn->sconn.s_error < 0)
+    {
+      ret = conn->sconn.s_error;
+      goto err_with_bind;
+    }
+  else if (ret >= 0)
+    {
+      goto out;
+    }
+
+err_with_bind:
+  vsock_unbind_internal(conn);
+out:
+  vsock_unlock(conn);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_accept
+ *
+ * Description:
+ *   This function implements accept() for virtual sockets.  See the
+ *   description of accept() for further information.
+ *
+ * Input Parameters:
+ *   psock    The listening Virtual domain socket structure
+ *   addr     Receives the address of the connecting client
+ *   addrlen  Input: allocated size of 'addr',
+ *            Return: returned size of 'addr'
+ *   newconn  The new, accepted Virtual domain connection structure
+ *
+ * Returned Value:
+ *   Returns zero (OK) on success or a negated errno value on failure.
+ *   See the description of accept of the possible errno values in the
+ *   description of accept().
+ *
+ ****************************************************************************/
+
+static int vsock_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+                        FAR socklen_t *addrlen, FAR struct socket *newsock,
+                        int flags)
+{
+  FAR struct vsock_conn_s *server = psock->s_conn;
+  int ret = 0;
+
+  if (!_SS_ISLISTENING(server->sconn.s_flags))
+    {
+      return -EINVAL;
+    }
+
+  for (; ; )
+    {
+      FAR struct vsock_conn_s *conn = NULL;
+
+      vsock_lock(server);
+      if (!list_is_empty(&server->child))
+        {
+          conn = list_first_entry(&server->child, struct vsock_conn_s,
+                                  child);
+          list_delete(&conn->child);
+        }
+
+      vsock_unlock(server);
+
+      if (conn)
+        {
+          newsock->s_domain = psock->s_domain;
+          newsock->s_sockif = psock->s_sockif;
+          newsock->s_type = SOCK_STREAM;
+          newsock->s_conn = conn;
+
+          vsockdbg("conn=%p\n", conn);
+          vsock_addr_get(&conn->remote_addr, addr, addrlen);
+          break;
+        }
+
+      if (_SS_ISNONBLOCK(server->sconn.s_flags))
+        {
+          ret = -EAGAIN;
+          break;
+        }
+
+      ret = net_sem_wait(&server->rx_sem);
+      if (ret < 0)
+        {
+          break;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_poll
+ *
+ * Description:
+ *   The standard poll() operation redirects operations on socket descriptors
+ *   to local_poll which, indiectly, calls to function.
+ *
+ * Input Parameters:
+ *   psock - An instance of the internal socket structure.
+ *   fds   - The structure describing the events to be monitored, OR NULL if
+ *           this is a request to stop monitoring events.
+ *   setup - true: Setup up the poll; false: Teardown the poll
+ *
+ * Returned Value:
+ *  0: Success; Negated errno on failure
+ *
+ ****************************************************************************/
+
+static int vsock_poll(FAR struct socket *psock,
+                      FAR struct pollfd_s *fds, bool setup)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  pollevent_t eventset = 0;
+  irqstate_t flags;
+  int ret = 0;
+  int i;
+
+  if (setup)
+    {
+      flags = spin_lock_irqsave(&conn->poll_lock);
+
+      for (i = 0; i < CONFIG_NET_VSOCK_NPOLLWAITERS; i++)
+        {
+          /* Find an available slot */
+
+          if (!conn->fds[i])
+            {
+              /* Bind the poll structure and this slot */
+
+              conn->fds[i] = fds;
+              fds->priv    = &conn->fds[i];
+              break;
+            }
+        }
+
+      spin_unlock_irqrestore(&conn->poll_lock, flags);
+
+      if (i >= CONFIG_NET_VSOCK_NPOLLWAITERS)
+        {
+          fds->priv = NULL;
+          return -EBUSY;
+        }
+
+      /* Immediately notify on any of the requested events */
+
+      vsock_lock(conn);
+      if (_SS_ISLISTENING(conn->sconn.s_flags))
+        {
+          if (!list_is_empty(&conn->child))
+            {
+              eventset |= POLLIN;
+            }
+        }
+      else if (_SS_ISCONNECTED(conn->sconn.s_flags))
+        {
+          if (VSOCK_IS_SHUTDOWN_WR(conn->shutdown))
+            {
+              eventset |= POLLHUP;
+            }
+
+          if (vsock_get_tx_credit(conn) > 0)
+            {
+              eventset |= POLLOUT;
+            }
+
+          if (VSOCK_IS_SHUTDOWN_RD(conn->shutdown) ||
+              vsock_get_rx_size(conn) >= conn->rx_lowat)
+            {
+              eventset |= POLLIN;
+            }
+        }
+
+      vsock_unlock(conn);
+      vsock_poll_notify(conn, eventset);
+    }
+  else
+    {
+      flags = spin_lock_irqsave(&conn->poll_lock);
+
+      if (fds->priv != NULL)
+        {
+          for (i = 0; i < CONFIG_NET_VSOCK_NPOLLWAITERS; i++)
+            {
+              if (fds == conn->fds[i])
+                {
+                  conn->fds[i] = NULL;
+                  fds->priv = NULL;
+                  break;
+                }
+            }
+        }
+
+      spin_unlock_irqrestore(&conn->poll_lock, flags);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_msg_init
+ *
+ * Description:
+ *   Virtual socket message init function
+ *
+ ****************************************************************************/
+
+static void vsock_msg_init(FAR struct vsock_msg_s *msg,
+                            FAR const struct msghdr *hdr)
+{
+  uio_init(&msg->uio, hdr->msg_iov, hdr->msg_iovlen);
+  msg->len = msg->uio.uio_resid;
+}
+
+/****************************************************************************
+ * Name: vsock_sendmsg
+ *
+ * Description:
+ *   Implements the sendmsg() operation for the case of the Virtual socket
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   msg      msg to send
+ *   flags    Send flags
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error, a negated
+ *   errno value is returned (see sendmsg() for the list of appropriate error
+ *   values.
+ *
+ ****************************************************************************/
+
+static ssize_t vsock_sendmsg(FAR struct socket *psock,
+                             FAR const struct msghdr *hdr, int flags)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  FAR const struct sockaddr *to = hdr->msg_name;
+  struct vsock_msg_s msg;
+  ssize_t ret = 0;
+  bool nonblock;
+
+  vsock_tx_lock(conn);
+
+  if (!_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      if (to == NULL)
+        {
+          ret = -ENOTCONN;
+          goto out;
+        }
+
+      ret = vsock_connect(psock, to, hdr->msg_namelen);
+      if (ret < 0)
+        {
+          goto out;
+        }
+    }
+
+  if (conn->shutdown & SHUT_WR)
+    {
+      ret = -EPIPE;
+      goto out;
+    }
+
+  nonblock = _SS_ISNONBLOCK(conn->sconn.s_flags) ||
+             (flags & MSG_DONTWAIT) != 0;
+
+  vsock_msg_init(&msg, hdr);
+  while (!vsock_msg_done(&msg))
+    {
+      if (conn->shutdown & SHUT_WR)
+        {
+          ret = -EPIPE;
+          goto out;
+        }
+
+      if (vsock_get_tx_credit(conn) > 0)
+        {
+          ret = vsock_send_pkt(conn, &msg, VIRTIO_VSOCK_OP_RW, 0, 0, 0);
+          break;
+        }
+
+      if (nonblock)
+        {
+          ret = -EAGAIN;
+          break;
+        }
+
+      vsock_tx_unlock(conn);
+      ret = net_sem_timedwait(&conn->tx_sem,
+                              _SO_TIMEOUT(conn->sconn.s_sndtimeo));
+      vsock_tx_lock(conn);
+
+      if (ret < 0)
+        {
+          break;
+        }
+    }
+
+out:
+  vsock_tx_unlock(conn);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_recvmsg
+ *
+ * Description:
+ *   recvmsg() receives messages from a local socket and may be used to
+ *   receive data on a socket whether or not it is connection-oriented.
+ *
+ *   If from is not NULL, and the underlying protocol provides the source
+ *   address, this source address is filled in. The argument fromlen
+ *   initialized to the size of the buffer associated with from, and modified
+ *   on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ *   psock    A pointer to a NuttX-specific, internal socket structure
+ *   msg      Buffer to receive the message
+ *   flags    Receive flags (ignored for now)
+ *
+ * Returned Value:
+ *   On success, returns the number of characters received. If no data is
+ *   available to be received and the peer has performed an orderly shutdown,
+ *   recvmsg() will return 0.  Otherwise, on errors, a negated errno value is
+ *   returned (see recvmsg() for the list of appropriate error values).
+ *
+ ****************************************************************************/
+
+static ssize_t vsock_recvmsg(FAR struct socket *psock,
+                             FAR struct msghdr *hdr, int flags)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  FAR struct sockaddr *from = hdr->msg_name;
+  FAR socklen_t *fromlen = &hdr->msg_namelen;
+  struct vsock_msg_s msg;
+  ssize_t ret;
+
+  if (psock->s_type != SOCK_STREAM)
+    {
+      return -ENOTSUP;
+    }
+
+  if (!_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      return -EISCONN;
+    }
+
+  vsock_msg_init(&msg, hdr);
+  vsock_rx_lock(conn);
+
+  /* Try to recv the buffer from rx_buf */
+
+  ret = vsock_copy_circ2msg(conn, &msg);
+  if (ret > 0)
+    {
+      vsock_update_rx_credit(conn, ret);
+    }
+  else if (_SS_ISNONBLOCK(conn->sconn.s_flags) ||
+           (flags & MSG_DONTWAIT) != 0)
+    {
+      ret = -EAGAIN;
+    }
+  else /* ret == 0 */
+    {
+      if (conn->shutdown & SHUT_RD)
+        {
+          vsock_rx_unlock(conn);
+          return 0;
+        }
+
+      /* No data recv, setup the user msg and wait */
+
+      DEBUGASSERT(ret == 0);
+      conn->rx_msg = &msg;
+      nxsem_reset(&conn->rx_sem, 0);
+      vsock_rx_unlock(conn);
+      ret = net_sem_timedwait(&conn->rx_sem,
+                              _SO_TIMEOUT(conn->sconn.s_rcvtimeo));
+      vsock_rx_lock(conn);
+      conn->rx_msg = NULL;
+      if (msg.len > msg.uio.uio_resid)
+        {
+          ret = msg.len - msg.uio.uio_resid;
+        }
+    }
+
+  vsock_rx_unlock(conn);
+  if (ret > 0)
+    {
+      vsock_addr_get(&conn->remote_addr, from, fromlen);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_close
+ *
+ * Description:
+ *   Performs the close operation on a Virtual socket instance
+ *
+ * Input Parameters:
+ *   psock   Socket instance
+ *
+ * Returned Value:
+ *   0 on success; a negated errno value is returned on any failure.
+ *
+ ****************************************************************************/
+
+static int vsock_close(FAR struct socket *psock)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret = OK;
+
+  vsock_lock(conn);
+
+  /* Condition 1: socket()  created connection, bind or connect waiting
+   * Condition 2: socket()  created connection, listen
+   * Condition 3: accept()  created connection, must in connected state
+   */
+
+  if (VSOCK_IS_SHUTDOWN(conn->shutdown))
+    {
+      vsockdbg("Peer has closed conn=%p s_flags=%d\n",
+               conn, conn->sconn.s_flags);
+      vsock_remove_conn(conn);
+    }
+  else if (_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      conn->shutdown = SHUT_RDWR;
+
+      /* Follow Virtio Spec 1.2 to do the clean disconnect:
+       * Clean disconnect is achieved by one or more
+       * VIRTIO_VSOCK_OP_SHUTDOWN packets that indicate no more data will
+       * be sent and received, followed by a VIRTIO_VSOCK_OP_RST response
+       * from the peer. If no VIRTIO_VSOCK_OP_RST response is received within
+       * an implementation-specific amount of time, a VIRTIO_VSOCK_OP_RST
+       * packet is sent to forcibly disconnect the socket.
+       */
+
+      vsockdbg("send shutdown to peer conn=%p\n", conn);
+      ret = vsock_send_pkt(conn, NULL, VIRTIO_VSOCK_OP_SHUTDOWN,
+                           VIRTIO_VSOCK_SHUTDOWN, 0, 0);
+      if (ret < 0)
+        {
+          vsockdbg("send shutdown failed conn=%p\n", conn);
+          vsock_unlock(conn);
+          return ret;
+        }
+
+      /* Queue the close timeout work */
+
+      vsockdbg("queue the close work conn=%p\n", conn);
+      vsock_add_ref(conn);
+      ret = vsock_queue_work(&conn->close_work, vsock_close_work, conn,
+                             VSOCK_CLOSE_TIMEOUT);
+    }
+  else if (_SS_ISBOUND(conn->sconn.s_flags) ||
+           _SS_ISLISTENING(conn->sconn.s_flags))
+    {
+      vsock_unbind_internal(conn);
+    }
+
+  vsock_unlock(conn);
+  vsock_sub_ref(conn);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_shutdown
+ *
+ * Description:
+ *   The shutdown() function will cause all or part of connection on the
+ *   socket associated with the file descriptor socket to be shut down.
+ *
+ *   The shutdown() function disables subsequent send and/or receive
+ *   operations on a socket, depending on the value of the how argument.
+ *
+ * Parameters:
+ *   sockfd - Specifies the file descriptor of the socket.
+ *   how    - Specifies the type of shutdown. The values are as follows:
+ *
+ *     SHUT_RD   - Disables further receive operations.
+ *     SHUT_WR   - Disables further send operations.
+ *     SHUT_RDWR - Disables further send and receive operations.
+ *
+ ****************************************************************************/
+
+static int vsock_shutdown(FAR struct socket *psock, int how)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret;
+
+  vsock_lock(conn);
+  vsockdbg("send shutdown to peer conn=%p\n", conn);
+  conn->shutdown |= how;
+  ret = vsock_send_pkt(conn, NULL, VIRTIO_VSOCK_OP_SHUTDOWN, how, 0, 0);
+  if (ret >= 0)
+    {
+      vsock_notify(conn, VSOCK_NOTIFY_SHUTDOWN);
+    }
+
+  vsock_unlock(conn);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_ioctl
+ *
+ * Description:
+ *   This function performs virtual socket specific operations.
+ *
+ * Parameters:
+ *   psock    A reference to the socket structure of the socket
+ *   cmd      The ioctl command
+ *   arg      The argument of the ioctl cmd
+ *
+ ****************************************************************************/
+
+static int vsock_ioctl(FAR struct socket *psock, int cmd, unsigned long arg)
+{
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: vsock_getsockopt
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_SOCKOPTS
+static int vsock_getsockopt(FAR struct socket *psock, int level, int option,
+                            FAR void *value, FAR socklen_t *value_len)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret = -ENOPROTOOPT;
+
+  if (level != SOL_SOCKET)
+    {
+      return ret;
+    }
+
+  switch (option)
+    {
+      case SO_RCVLOWAT:
+        {
+          FAR unsigned long *rcvlowat = value;
+
+          if (value == NULL || value_len == NULL)
+            {
+              return -EINVAL;
+            }
+
+          vsock_rx_lock(conn);
+          *rcvlowat = conn->rx_lowat;
+          *value_len = sizeof(unsigned long);
+          vsock_rx_unlock(conn);
+          ret = OK;
+        }
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vsock_setsockopt
+ ****************************************************************************/
+
+static int vsock_setsockopt(FAR struct socket *psock, int level, int option,
+                            FAR const void *value, socklen_t value_len)
+{
+  FAR struct vsock_conn_s *conn = psock->s_conn;
+  int ret = -ENOPROTOOPT;
+
+  if (level != SOL_SOCKET)
+    {
+      return ret;
+    }
+
+  switch (option)
+    {
+      case SO_RCVLOWAT:
+        if (value == NULL || value_len != sizeof(unsigned long))
+          {
+            return -EINVAL;
+          }
+
+        vsock_rx_lock(conn);
+        conn->rx_lowat = MIN(*(FAR unsigned long *)value,
+                             conn->rx_buf_alloc);
+        vsock_rx_unlock(conn);
+        ret = OK;
+        break;
+    }
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: vsock_dump_pkt
+ ****************************************************************************/
+
+#ifdef VSOCK_DEBUG
+static void vsock_dump_pkt(FAR struct vsock_pkt_s *pkt,
+                           FAR const char *msg, bool dumpbuf)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  size_t i;
+
+  ninfo("%s pkt: %p src: cid=%" PRIu64 " port=%" PRIu32
+        " dst: cid=%" PRIu64 " port=%" PRIu32
+        " op=%s type=%" PRIu16 " len=%" PRIu32 " flags=0x%" PRIx32
+        " rx_buf_alloc=%" PRIu32 " rx_fwd_cnt=%" PRIu32 " \n",
+        msg, pkt, hdr->src_cid, hdr->src_port, hdr->dst_cid, hdr->dst_port,
+        g_vsock_op[hdr->op], hdr->type, hdr->len, hdr->flags,
+        hdr->buf_alloc, hdr->fwd_cnt);
+
+  if (dumpbuf)
+    {
+      for (i = 0; i < pkt->vbcnt; i++)
+        {
+          lib_dumpbuffer("Virt Buffer:", pkt->vb[i].buf, pkt->vb[i].len);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vsock_recv_pkt
+ ****************************************************************************/
+
+void vsock_recv_pkt(FAR struct vsock_transport_s *t,
+                    FAR struct vsock_pkt_s *pkt)
+{
+  FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt);
+  FAR struct vsock_conn_s *conn;
+  struct sockaddr_vm remote_addr;
+  struct sockaddr_vm local_addr;
+
+  DEBUGASSERT(pkt->vb[0].len == hdr->len + VIRTIO_VSOCK_HDR_LEN);
+  vsock_dump_pkt(pkt, "Recv", false);
+
+  /* Type check */
+
+  if (hdr->type != VIRTIO_VSOCK_TYPE_STREAM)
+    {
+      vrterr("Operation Type Error\n");
+      vsock_reset_no_conn(t, pkt);
+      return;
+    }
+
+  /* Find the connected or bound socket in the list, the refcnt will be
+   * added when a connection is found in bound or connected list.
+   */
+
+  vsock_addr_init(&remote_addr, hdr->src_cid, hdr->src_port);
+  vsock_addr_init(&local_addr, hdr->dst_cid, hdr->dst_port);
+  conn = vsock_find_connected_conn(&remote_addr, &local_addr);
+  if (conn == NULL)
+    {
+      conn = vsock_find_bound_conn(&local_addr);
+      if (conn == NULL)
+        {
+          vsock_reset_no_conn(t, pkt);
+          vrterr("ERROR: No connection found\n");
+          return;
+        }
+    }
+
+  vsock_lock(conn);
+
+  /* Update the window */
+
+  vsock_update_tx_credit(conn, pkt);
+
+  /* Handle the receiving data */
+
+  if (VSOCK_IS_SHUTDOWN(conn->shutdown))
+    {
+      vsock_recv_closing(conn, pkt);
+    }
+  else if (_SS_ISCONNECTED(conn->sconn.s_flags))
+    {
+      vsock_recv_connected(conn, pkt);
+    }
+  else if (_SS_ISLISTENING(conn->sconn.s_flags))
+    {
+      vsock_recv_listening(conn, t, pkt);
+    }
+  else if (_SS_ISBOUND(conn->sconn.s_flags))
+    {
+      vsock_recv_connecting(conn, pkt);
+    }
+  else
+    {
+      vsock_reset_no_conn(t, pkt);
+    }
+
+  vsock_unlock(conn);
+  vsock_sub_ref(conn);
+}
+
+/****************************************************************************
+ * Name: vsock_queue_work
+ *
+ * Description:
+ *   Work queue for the virtual socket layer.
+ *
+ ****************************************************************************/
+
+int vsock_queue_work(FAR struct work_s *work, worker_t worker, FAR void *arg,
+                     clock_t delay)
+{
+  return work_queue_wq(g_vsock_wqueue, work, worker, arg, delay);
+}
+
+/****************************************************************************
+ * Name: vsock_transport_register
+ *
+ * Description:
+ *   Register the virtual socket transport.
+ *
+ ****************************************************************************/
+
+void vsock_transport_register(FAR struct vsock_transport_s *t)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(&g_vsock_transport_lock);
+  list_add_tail(&g_vsock_transport, &t->node);
+  spin_unlock_irqrestore(&g_vsock_transport_lock, flags);
+}
+
+/****************************************************************************
+ * Name: vsock_initialize
+ *
+ * Description:
+ *   Initialize the virtual socket layer.
+ *
+ ****************************************************************************/
+
+int vsock_initialize(void)
+{
+  g_vsock_wqueue = work_queue_create("vsock_work",
+                                     CONFIG_NET_VSOCK_WORK_PRIORITY,
+                                     NULL,
+                                     CONFIG_NET_VSOCK_WORK_STACKSIZE, 1);
+  if (g_vsock_wqueue == NULL)
+    {
+      vrterr("Create vsock wqueue failed\n");
+      return -ENOMEM;
+    }
+
+  return OK;
+}
diff --git a/net/vsock/vsock_virtio.h b/net/vsock/vsock_virtio.h
new file mode 100644
index 00000000000..b87a1d1e05d
--- /dev/null
+++ b/net/vsock/vsock_virtio.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+ * net/vsock/vsock_virtio.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __NET_VSOCK_VSOCK_VIRTIO_H
+#define __NET_VSOCK_VSOCK_VIRTIO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/virtio/virtio-vsock.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* VirtIO Vsock event */
+
+#define VIRTIO_VSOCK_EVENT_TRANSPORT_RESET 0
+
+/* VirtIO Vsock Type: stream or seqpacket */
+
+#define VIRTIO_VSOCK_TYPE_STREAM           1
+#define VIRTIO_VSOCK_TYPE_SEQPACKET        2
+
+/* Invalid operation */
+
+#define VIRTIO_VSOCK_OP_INVALID            0
+
+/* Connect operations */
+
+#define VIRTIO_VSOCK_OP_REQUEST            1
+#define VIRTIO_VSOCK_OP_RESPONSE           2
+#define VIRTIO_VSOCK_OP_RST                3
+#define VIRTIO_VSOCK_OP_SHUTDOWN           4
+
+/* To send payload */
+
+#define VIRTIO_VSOCK_OP_RW                 5
+
+/* Tell the peer our credit info */
+
+#define VIRTIO_VSOCK_OP_CREDIT_UPDATE      6
+
+/* Request the peer to send the credit info to us */
+
+#define VIRTIO_VSOCK_OP_CREDIT_REQUEST     7
+
+/* VIRTIO_VSOCK_OP_SHUTDOWN flags values */
+
+#define VIRTIO_VSOCK_SHUTDOWN_F_RECV       0
+#define VIRTIO_VSOCK_SHUTDOWN_F_SEND       1
+#define VIRTIO_VSOCK_SHUTDOWN_RECV         (1 << VIRTIO_VSOCK_SHUTDOWN_F_RECV)
+#define VIRTIO_VSOCK_SHUTDOWN_SEND         (1 << VIRTIO_VSOCK_SHUTDOWN_F_SEND)
+#define VIRTIO_VSOCK_SHUTDOWN              (VIRTIO_VSOCK_SHUTDOWN_RECV | 
VIRTIO_VSOCK_SHUTDOWN_SEND)
+
+/* VIRTIO_VSOCK_OP_RW flags values */
+
+#define VIRTIO_VSOCK_SEQ_EOM               (1 << 0)
+#define VIRTIO_VSOCK_SEQ_EOR               (1 << 1)
+
+#define VIRTIO_VSOCK_EVENT_LEN             sizeof(struct virtio_vsock_event_s)
+#define VIRTIO_VSOCK_HDR_LEN               sizeof(struct vsock_hdr_s)
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+begin_packed_struct struct vsock_hdr_s
+{
+  uint64_t src_cid;
+  uint64_t dst_cid;
+  uint32_t src_port;
+  uint32_t dst_port;
+  uint32_t len;
+  uint16_t type;
+  uint16_t op;
+  uint32_t flags;
+  uint32_t buf_alloc;
+  uint32_t fwd_cnt;
+} end_packed_struct;
+
+begin_packed_struct struct virtio_vsock_event_s
+{
+  uint32_t id;
+} end_packed_struct;
+
+#endif /* __NET_VSOCK_VSOCK_VIRTIO_H */

Reply via email to