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 9107753826a49c74b5639643f6e6c7c39ae22b4a Author: Yongrong Wang <[email protected]> AuthorDate: Tue Sep 23 16:14:37 2025 +0800 vsock: support multi pkt chain in vsock vhost Tx vsock vhost tx transmission rate increased by about 61%. Signed-off-by: Yongrong Wang <[email protected]> --- net/vsock/vsock.h | 12 +++--- net/vsock/vsock_sockif.c | 87 ++++++++++++++++++++++----------------- net/vsock/vsock_vhost.c | 104 +++++++++++++++++++++++++++++++++++++++-------- net/vsock/vsock_virtio.c | 2 + 4 files changed, 145 insertions(+), 60 deletions(-) diff --git a/net/vsock/vsock.h b/net/vsock/vsock.h index 9af83327209..60b8896128e 100644 --- a/net/vsock/vsock.h +++ b/net/vsock/vsock.h @@ -48,11 +48,13 @@ 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]; + size_t vbidx; + size_t vboff; + size_t vbcnt; + size_t len; + FAR void *priv; + FAR struct vsock_pkt_s *next; + struct virtqueue_buf vb[CONFIG_NET_VSOCK_PKT_BUFCOUNT]; }; struct vsock_transport_s; diff --git a/net/vsock/vsock_sockif.c b/net/vsock/vsock_sockif.c index 87405a80b1f..de1d7b3c854 100644 --- a/net/vsock/vsock_sockif.c +++ b/net/vsock/vsock_sockif.c @@ -916,27 +916,34 @@ static size_t vsock_copy_msg2pkt(FAR struct vsock_pkt_s *pkt, 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 + while (pkt != NULL) + { + while (total > 0 && pkt->vbidx < pkt->vbcnt && + pkt->vboff <= pkt->vb[pkt->vbidx].len) { - pkt->vboff += copied; + 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; } - total -= copied; - ret += copied; + pkt = pkt->next; } return ret; @@ -997,6 +1004,7 @@ static int vsock_send_pkt(FAR struct vsock_conn_s *conn, uint16_t op, uint32_t hdrflags, uint64_t dst_cid, uint32_t dst_port) { + FAR struct vsock_pkt_s *tmp; struct vsock_pkt_s pkt; struct vsock_hdr_s *hdr; unsigned int rxcount; @@ -1033,30 +1041,33 @@ static int vsock_send_pkt(FAR struct vsock_conn_s *conn, vsock_alloc_tx_credit(conn, len); } - hdr = vsock_pkt2hdr(&pkt); - if (dst_cid == 0) + for (tmp = &pkt; tmp != NULL; tmp = tmp->next) { - 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 = vsock_pkt2hdr(tmp); + 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; + 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 = tmp->len - VIRTIO_VSOCK_HDR_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); + 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); diff --git a/net/vsock/vsock_vhost.c b/net/vsock/vsock_vhost.c index cd642c9cdc2..3dc7b0bf3b2 100644 --- a/net/vsock/vsock_vhost.c +++ b/net/vsock/vsock_vhost.c @@ -60,6 +60,9 @@ struct vsock_vhost_priv_s sem_t tx_sem; struct work_s rx_work; + struct list_node tx_pkt_list; + FAR struct vsock_pkt_s *tx_pkt_alloc; + struct vsock_transport_s t; }; @@ -148,30 +151,43 @@ static int vsock_vhost_alloc_pkt(FAR struct vsock_transport_s *t, FAR struct vsock_vhost_priv_s *priv = vsock_vhost_trans2priv(t); FAR struct virtqueue *vq; irqstate_t flags; - size_t vbcnt; + size_t pktcnt; int head; - data_len += VIRTIO_VSOCK_HDR_LEN; - vbcnt = div_round_up(data_len, CONFIG_NET_VSOCK_PKT_BUFSIZE); - vbcnt = MIN(vbcnt, CONFIG_NET_VSOCK_PKT_BUFCOUNT); + pktcnt = data_len == 0 ? 1 : + div_round_up(data_len, CONFIG_NET_VSOCK_PKT_BUFSIZE); + pktcnt = MIN(pktcnt, CONFIG_NET_VSOCK_PKT_BUFCOUNT); vq = priv->hdev->vrings_info[VSOCK_VQ_TX].vq; - for (; ; ) + flags = spin_lock_irqsave(&priv->tx_lock); + while (pktcnt > 0) { - flags = spin_lock_irqsave(&priv->tx_lock); - head = vhost_get_vq_buffers(vq, pkt->vb, vbcnt, &pkt->vbcnt); - spin_unlock_irqrestore(&priv->tx_lock, flags); + head = vhost_get_vq_buffers(vq, pkt->vb, 1, &pkt->vbcnt); if (head < 0) { + spin_unlock_irqrestore(&priv->tx_lock, flags); nxsem_wait(&priv->tx_sem); + flags = spin_lock_irqsave(&priv->tx_lock); continue; } pkt->vbidx = 0; pkt->vboff = VIRTIO_VSOCK_HDR_LEN; pkt->priv = (FAR void *)(uintptr_t)head; - return 0; + pkt->len = MIN(data_len + VIRTIO_VSOCK_HDR_LEN, pkt->vb[0].len); + data_len -= pkt->len - VIRTIO_VSOCK_HDR_LEN; + + if (--pktcnt > 0) + { + pkt->next = (FAR struct vsock_pkt_s *) + list_remove_head(&priv->tx_pkt_list); + DEBUGASSERT(pkt->next != NULL); + pkt = pkt->next; + } } + + spin_unlock_irqrestore(&priv->tx_lock, flags); + return 0; } /**************************************************************************** @@ -182,21 +198,38 @@ static ssize_t vsock_vhost_send_pkt(FAR struct vsock_transport_s *t, FAR struct vsock_pkt_s *pkt) { FAR struct vsock_vhost_priv_s *priv = vsock_vhost_trans2priv(t); - FAR struct vsock_hdr_s *hdr = vsock_pkt2hdr(pkt); + FAR struct vsock_pkt_s *next; + FAR struct vsock_hdr_s *hdr; FAR struct virtqueue *vq; - ssize_t len = hdr->len; + uint32_t data_len; irqstate_t flags; + ssize_t len = 0; int ret; vq = priv->hdev->vrings_info[VSOCK_VQ_TX].vq; flags = spin_lock_irqsave(&priv->tx_lock); - ret = virtqueue_add_consumed_buffer(vq, (uint16_t)(uintptr_t)pkt->priv, - hdr->len + VIRTIO_VSOCK_HDR_LEN); - if (ret < 0) + while (pkt != NULL) { - spin_unlock_irqrestore(&priv->tx_lock, flags); - vhosterr("Add buffer failed ret=%d\n", ret); - return ret; + hdr = vsock_pkt2hdr(pkt); + data_len = hdr->len; + ret = virtqueue_add_consumed_buffer(vq, (uint16_t)(uintptr_t)pkt->priv, + data_len + VIRTIO_VSOCK_HDR_LEN); + if (ret < 0) + { + spin_unlock_irqrestore(&priv->tx_lock, flags); + vhosterr("Add buffer failed ret=%d\n", ret); + return ret; + } + + next = pkt->next; + if (len != 0) + { + pkt->next = NULL; + list_add_head(&priv->tx_pkt_list, (FAR struct list_node *)pkt); + } + + pkt = next; + len += data_len; } virtqueue_kick(vq); @@ -273,6 +306,32 @@ static void vsock_vhost_handle_tx(FAR struct virtqueue *vq) vsock_post(&priv->tx_sem); } +/**************************************************************************** + * Name: vsock_vhost_tx_pkt_init + ****************************************************************************/ + +static int vsock_vhost_tx_pkt_init(FAR struct vsock_vhost_priv_s *priv) +{ + FAR struct virtqueue *vq = priv->hdev->vrings_info[VSOCK_VQ_TX].vq; + uint16_t i; + + list_initialize(&priv->tx_pkt_list); + priv->tx_pkt_alloc = kmm_zalloc(sizeof(struct vsock_pkt_s) * + vq->vq_nentries); + if (priv->tx_pkt_alloc == NULL) + { + return -ENOMEM; + } + + for (i = 0; i < vq->vq_nentries; i++) + { + list_add_tail(&priv->tx_pkt_list, + (FAR struct list_node *)(&priv->tx_pkt_alloc[i])); + } + + return 0; +} + /**************************************************************************** * Name: vsock_vhost_probe ****************************************************************************/ @@ -327,6 +386,13 @@ static int vsock_vhost_probe(FAR struct vhost_device *hdev) priv->host_cid = VMADDR_CID_HOST; } + ret = vsock_vhost_tx_pkt_init(priv); + if (ret < 0) + { + vrterr("vsock_vhost_tx_pkt_init failed, ret=%d\n", ret); + goto err_with_tx; + } + /* Register Virtual Socket H2G transport */ priv->t.ops = &g_vsock_vhost_transport_ops; @@ -336,7 +402,10 @@ static int vsock_vhost_probe(FAR struct vhost_device *hdev) virtqueue_enable_cb(hdev->vrings_info[VSOCK_VQ_TX].vq); return ret; +err_with_tx: + vhost_delete_virtqueues(hdev); err: + nxsem_destroy(&priv->tx_sem); kmm_free(priv); return ret; } @@ -351,6 +420,7 @@ static void vsock_vhost_remove(FAR struct vhost_device *hdev) virtqueue_disable_cb(hdev->vrings_info[VSOCK_VQ_RX].vq); virtqueue_disable_cb(hdev->vrings_info[VSOCK_VQ_TX].vq); + kmm_free(priv->tx_pkt_alloc); vhost_delete_virtqueues(hdev); nxsem_destroy(&priv->tx_sem); kmm_free(priv); diff --git a/net/vsock/vsock_virtio.c b/net/vsock/vsock_virtio.c index 2a8f6279b81..5ccc839d040 100644 --- a/net/vsock/vsock_virtio.c +++ b/net/vsock/vsock_virtio.c @@ -203,6 +203,8 @@ static int vsock_virtio_alloc_pkt(FAR struct vsock_transport_s *t, { pkt->vb[i].len = data_len; } + + pkt->len += pkt->vb[i].len; } priv->tx_buf_num -= vbcnt;
