Skip to content

Commit

Permalink
vsock/virtio: non-linear skb handling for tap
Browse files Browse the repository at this point in the history
For tap device new skb is created and data from the current skb is
copied to it. This adds copying data from non-linear skb to new
the skb.

Signed-off-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Arseniy Krasnov authored and Paolo Abeni committed Sep 21, 2023
1 parent 64c99d2 commit 4b0bf10
Showing 1 changed file with 28 additions and 3 deletions.
31 changes: 28 additions & 3 deletions net/vmw_vsock/virtio_transport_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,27 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
return NULL;
}

static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb,
void *dst,
size_t len)
{
struct iov_iter iov_iter = { 0 };
struct kvec kvec;
size_t to_copy;

kvec.iov_base = dst;
kvec.iov_len = len;

iov_iter.iter_type = ITER_KVEC;
iov_iter.kvec = &kvec;
iov_iter.nr_segs = 1;

to_copy = min_t(size_t, len, skb->len);

skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset,
&iov_iter, to_copy);
}

/* Packet capture */
static struct sk_buff *virtio_transport_build_skb(void *opaque)
{
Expand All @@ -114,15 +135,13 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
struct af_vsockmon_hdr *hdr;
struct sk_buff *skb;
size_t payload_len;
void *payload_buf;

/* A packet could be split to fit the RX buffer, so we can retrieve
* the payload length from the header and the buffer pointer taking
* care of the offset in the original packet.
*/
pkt_hdr = virtio_vsock_hdr(pkt);
payload_len = pkt->len;
payload_buf = pkt->data;

skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len,
GFP_ATOMIC);
Expand Down Expand Up @@ -165,7 +184,13 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr));

if (payload_len) {
skb_put_data(skb, payload_buf, payload_len);
if (skb_is_nonlinear(pkt)) {
void *data = skb_put(skb, payload_len);

virtio_transport_copy_nonlinear_skb(pkt, data, payload_len);
} else {
skb_put_data(skb, pkt->data, payload_len);
}
}

return skb;
Expand Down

0 comments on commit 4b0bf10

Please sign in to comment.