Message ID | 20230603204939.1598818-5-AVKrasnov@sberdevices.ru (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | vsock: MSG_ZEROCOPY flag support | expand |
On Sat, Jun 03, 2023 at 11:49:26PM +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@sberdevices.ru> >--- > net/vmw_vsock/virtio_transport_common.c | 31 ++++++++++++++++++++++--- > 1 file changed, 28 insertions(+), 3 deletions(-) > >diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c >index 5819a9cd4515..0de562c1dc4b 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(struct sk_buff *skb, `const struct sk_buff *skb` should be better also to understand that the function copy data from *skb to *dst. >+ 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 >
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 5819a9cd4515..0de562c1dc4b 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(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;
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@sberdevices.ru> --- net/vmw_vsock/virtio_transport_common.c | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)