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:
committed by
Isaac Manjarres
parent
82309a607c
commit
45954b1a14
@@ -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;
|
||||||
|
Reference in New Issue
Block a user