diff options
Diffstat (limited to 'vu_common.c')
| -rw-r--r-- | vu_common.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/vu_common.c b/vu_common.c index b13b7c3..5f2ce18 100644 --- a/vu_common.c +++ b/vu_common.c @@ -76,13 +76,13 @@ void vu_init_elem(struct vu_virtq_element *elem, struct iovec *iov, int elem_cnt * in the in_sg array. * @max_elem: Number of virtqueue elements in the array * @size: Maximum size of the data in the frame - * @frame_size: The total size of the buffers (output) + * @collected: Collected buffer length, up to @size, set on return * * Return: number of elements used to contain the frame */ int vu_collect(const struct vu_dev *vdev, struct vu_virtq *vq, struct vu_virtq_element *elem, int max_elem, - size_t size, size_t *frame_size) + size_t size, size_t *collected) { size_t current_size = 0; int elem_cnt = 0; @@ -113,25 +113,24 @@ int vu_collect(const struct vu_dev *vdev, struct vu_virtq *vq, break; } - if (frame_size) - *frame_size = current_size; + if (collected) + *collected = current_size; return elem_cnt; } /** * vu_set_vnethdr() - set virtio-net headers - * @vdev: vhost-user device * @vnethdr: Address of the header to set * @num_buffers: Number of guest buffers of the frame */ -void vu_set_vnethdr(const struct vu_dev *vdev, - struct virtio_net_hdr_mrg_rxbuf *vnethdr, - int num_buffers) +void vu_set_vnethdr(struct virtio_net_hdr_mrg_rxbuf *vnethdr, int num_buffers) { vnethdr->hdr = VU_HEADER; - if (vu_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) - vnethdr->num_buffers = htole16(num_buffers); + /* Note: if VIRTIO_NET_F_MRG_RXBUF is not negotiated, + * num_buffers must be 1 + */ + vnethdr->num_buffers = htole16(num_buffers); } /** @@ -261,7 +260,7 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size) vu_init_elem(elem, in_sg, VIRTQUEUE_MAX_SIZE); - size += sizeof(struct virtio_net_hdr_mrg_rxbuf); + size += VNET_HLEN; elem_cnt = vu_collect(vdev, vq, elem, VIRTQUEUE_MAX_SIZE, size, &total); if (total < size) { debug("vu_send_single: no space to send the data " @@ -269,18 +268,15 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size) goto err; } - vu_set_vnethdr(vdev, in_sg[0].iov_base, elem_cnt); + vu_set_vnethdr(in_sg[0].iov_base, elem_cnt); - total -= sizeof(struct virtio_net_hdr_mrg_rxbuf); + total -= VNET_HLEN; /* copy data from the buffer to the iovec */ - iov_from_buf(in_sg, elem_cnt, sizeof(struct virtio_net_hdr_mrg_rxbuf), - buf, total); + iov_from_buf(in_sg, elem_cnt, VNET_HLEN, buf, total); - if (*c->pcap) { - pcap_iov(in_sg, elem_cnt, - sizeof(struct virtio_net_hdr_mrg_rxbuf)); - } + if (*c->pcap) + pcap_iov(in_sg, elem_cnt, VNET_HLEN); vu_flush(vdev, vq, elem, elem_cnt); @@ -293,3 +289,17 @@ err: return -1; } + +/** + * vu_pad() - Pad 802.3 frame to minimum length (60 bytes) if needed + * @iov: Buffer in iovec array where end of 802.3 frame is stored + * @l2len: Layer-2 length already filled in frame + */ +void vu_pad(struct iovec *iov, size_t l2len) +{ + if (l2len >= ETH_ZLEN) + return; + + memset((char *)iov->iov_base + iov->iov_len, 0, ETH_ZLEN - l2len); + iov->iov_len += ETH_ZLEN - l2len; +} |
