mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
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>
This commit is contained in:
parent
64c99d2d6a
commit
4b0bf10eb0
|
|
@ -106,6 +106,27 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
@ -114,7 +135,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
|
||||||
|
|
@ -122,7 +142,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);
|
||||||
|
|
@ -165,7 +184,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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user