Stefano Garzarella
2023-Jul-06 16:51 UTC
[RFC PATCH v5 04/17] vsock/virtio: non-linear skb handling for tap
On Sat, Jul 01, 2023 at 09:39:34AM +0300, Arseniy Krasnov wrote:>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 at sberdevices.ru> >--- > Changelog: > v4 -> v5: > * Make 'skb' pointer constant because it is source. > > net/vmw_vsock/virtio_transport_common.c | 31 ++++++++++++++++++++++--- > 1 file changed, 28 insertions(+), 3 deletions(-)Reviewed-by: Stefano Garzarella <sgarzare at redhat.com>> >diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c >index e5683af23e60..dfc48b56d0a2 100644 >--- a/net/vmw_vsock/virtio_transport_common.c >+++ b/net/vmw_vsock/virtio_transport_common.c >@@ -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)->frag_off, >+ &iov_iter, to_copy); >+} >+ > /* Packet capture */ > 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 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 >@@ -122,7 +142,6 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) > */ > 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); >@@ -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; >-- >2.25.1 >