UPSTREAM: vsock/virtio: non-linear skb handling for tap

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>
(cherry picked from commit 4b0bf10eb077cb43c09746251ef3608d62c45667)
Bug: 421244320
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: I7f184148aa8a91032c65ef61326ca7f513f157a3
This commit is contained in:
Arseniy Krasnov
2023-09-16 16:09:17 +03:00
committed by Isaac Manjarres
parent 82309a607c
commit 45954b1a14

View File

@@ -115,6 +115,27 @@ out:
return NULL; 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 */ /* Packet capture */
static struct sk_buff *virtio_transport_build_skb(void *opaque) static struct sk_buff *virtio_transport_build_skb(void *opaque)
{ {
@@ -123,7 +144,6 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
struct af_vsockmon_hdr *hdr; struct af_vsockmon_hdr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
size_t payload_len; size_t payload_len;
void *payload_buf;
/* A packet could be split to fit the RX buffer, so we can retrieve /* 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 * the payload length from the header and the buffer pointer taking
@@ -131,7 +151,6 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
*/ */
pkt_hdr = virtio_vsock_hdr(pkt); pkt_hdr = virtio_vsock_hdr(pkt);
payload_len = pkt->len; payload_len = pkt->len;
payload_buf = pkt->data;
skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len, skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len,
GFP_ATOMIC); GFP_ATOMIC);
@@ -174,7 +193,13 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque)
skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr)); skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr));
if (payload_len) { 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; return skb;