[RFC,v3,04/17] vsock/virtio: non-linear skb handling for tap

Message ID 20230522073950.3574171-5-AVKrasnov@sberdevices.ru
State New
Headers
Series vsock: MSG_ZEROCOPY flag support |

Commit Message

Arseniy Krasnov May 22, 2023, 7:39 a.m. UTC
  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(-)
  

Comments

Simon Horman May 22, 2023, 1:13 p.m. UTC | #1
On Mon, May 22, 2023 at 10:39:37AM +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 16effa8d55d2..9854f48a0544 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 iovec iovec;
> +	size_t to_copy;
> +
> +	iovec.iov_base = dst;

Hi Arseniy,

Sparse seems unhappy about this.
Though, TBH, I'm unsure what should be done about it.

.../virtio_transport_common.c:117:24: warning: incorrect type in assignment (different address spaces)
.../virtio_transport_common.c:117:24:    expected void [noderef] __user *iov_base
.../virtio_transport_common.c:117:24:    got void *dst


...
  
Arseniy Krasnov May 22, 2023, 1:15 p.m. UTC | #2
On 22.05.2023 16:13, Simon Horman wrote:
> On Mon, May 22, 2023 at 10:39:37AM +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 16effa8d55d2..9854f48a0544 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 iovec iovec;
>> +	size_t to_copy;
>> +
>> +	iovec.iov_base = dst;
> 
> Hi Arseniy,
> 
> Sparse seems unhappy about this.
> Though, TBH, I'm unsure what should be done about it.
> 
> .../virtio_transport_common.c:117:24: warning: incorrect type in assignment (different address spaces)
> .../virtio_transport_common.c:117:24:    expected void [noderef] __user *iov_base
> .../virtio_transport_common.c:117:24:    got void *dst
> 
Got it, i'll check how to resolve this problem!

Thanks!
> 
> ...
  

Patch

diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index 16effa8d55d2..9854f48a0544 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 iovec iovec;
+	size_t to_copy;
+
+	iovec.iov_base = dst;
+	iovec.iov_len = len;
+
+	iov_iter.iter_type = ITER_IOVEC;
+	iov_iter.__iov = &iovec;
+	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;