diff mbox series

[net-next,v5,3/3] net/tls: Remove redundant array allocation.

Message ID 20180719162613.27184-4-vakul.garg@nxp.com
State Changes Requested, archived
Delegated to: David Miller
Headers show
Series net/tls: Minor code cleanup patches | expand

Commit Message

Vakul Garg July 19, 2018, 4:26 p.m. UTC
In function decrypt_skb(), array allocation in case when sgout is NULL
is unnecessary. Instead, local variable sgin_arr[] can be used.

Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
---
 net/tls/tls_sw.c | 4 ----
 1 file changed, 4 deletions(-)

Comments

David Miller July 22, 2018, 2:25 a.m. UTC | #1
From: Vakul Garg <vakul.garg@nxp.com>
Date: Thu, 19 Jul 2018 21:56:13 +0530

> In function decrypt_skb(), array allocation in case when sgout is NULL
> is unnecessary. Instead, local variable sgin_arr[] can be used.
> 
> Signed-off-by: Vakul Garg <vakul.garg@nxp.com>

Hmmm...

Dave, can you take a look at this?  Do you think there might have
been a reason you felt that you needed to dynamically allocate
the scatterlists when you COW and skb and do in-place decryption?

I guess this change is ok, nsg can only get smaller when the SKB
is COW'd.
Dave Watson July 23, 2018, 4:35 p.m. UTC | #2
On 07/21/18 07:25 PM, David Miller wrote:
> From: Vakul Garg <vakul.garg@nxp.com>
> Date: Thu, 19 Jul 2018 21:56:13 +0530
> 
> > In function decrypt_skb(), array allocation in case when sgout is NULL
> > is unnecessary. Instead, local variable sgin_arr[] can be used.
> > 
> > Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
> 
> Hmmm...
> 
> Dave, can you take a look at this?  Do you think there might have
> been a reason you felt that you needed to dynamically allocate
> the scatterlists when you COW and skb and do in-place decryption?
> 
> I guess this change is ok, nsg can only get smaller when the SKB
> is COW'd.
> 

> >         memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
> >         if (!sgout) {
> >                 nsg = skb_cow_data(skb, 0, &unused) + 1;
> > -               sgin = kmalloc_array(nsg, sizeof(*sgin), sk->sk_allocation);
> >                 sgout = sgin;
> >         }

I don't think this patch is safe as-is.  sgin_arr is a stack array of
size MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that
it walks the whole chain of skbs from skb->next, and can return any
number of segments.  Therefore we need to heap allocate.  I think I
copied the IPSEC code here.

For perf though, we could use the stack array if skb_cow_data returns
<= MAX_SKB_FRAGS.

This code is slightly confusing though, since we don't heap allocate
in the zerocopy case - what happens is that skb_to_sgvec returns
-EMSGSIZE, and we fall back to the non-zerocopy case, and return again
to this function, where we then hit the skb_cow_data path and heap
allocate.
David Miller July 24, 2018, 4:41 a.m. UTC | #3
From: Dave Watson <davejwatson@fb.com>
Date: Mon, 23 Jul 2018 09:35:09 -0700

> I don't think this patch is safe as-is.  sgin_arr is a stack array of
> size MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that
> it walks the whole chain of skbs from skb->next, and can return any
> number of segments.  Therefore we need to heap allocate.  I think I
> copied the IPSEC code here.

Ok I see what you are saying.

So it means that, when a non-NULL sgout is passed into decrypt_skb(),
via decrypt_skb_update(), via tls_sw_recvmsg() it means that it is the
zerocopy case and you know that you only have page frags and no SKB
frag list, right?

I agree with you that this change is therefore incorrect.
Vakul Garg July 24, 2018, 4:43 a.m. UTC | #4
Hi Dave

Can you still apply the rest of two patches in the series or do I need to send them again separately?

Regards

Vakul
David Miller July 24, 2018, 4:49 a.m. UTC | #5
From: Vakul Garg <vakul.garg@nxp.com>
Date: Tue, 24 Jul 2018 04:43:55 +0000

> Can you still apply the rest of two patches in the series or do I
> need to send them again separately?

When a change of any kind needs to be made to a patch series, you must
always resubmit the entire series.

Thank you.
Vakul Garg July 24, 2018, 8:22 a.m. UTC | #6
> -----Original Message-----
> From: Dave Watson [mailto:davejwatson@fb.com]
> Sent: Monday, July 23, 2018 10:05 PM
> To: David Miller <davem@davemloft.net>
> Cc: Vakul Garg <vakul.garg@nxp.com>; netdev@vger.kernel.org;
> borisp@mellanox.com; aviadye@mellanox.com; Doron Roberts-Kedes
> <doronrk@fb.com>
> Subject: Re: [net-next v5 3/3] net/tls: Remove redundant array allocation.
> 
> On 07/21/18 07:25 PM, David Miller wrote:
> > From: Vakul Garg <vakul.garg@nxp.com>
> > Date: Thu, 19 Jul 2018 21:56:13 +0530
> >
> > > In function decrypt_skb(), array allocation in case when sgout is
> > > NULL is unnecessary. Instead, local variable sgin_arr[] can be used.
> > >
> > > Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
> >
> > Hmmm...
> >
> > Dave, can you take a look at this?  Do you think there might have been
> > a reason you felt that you needed to dynamically allocate the
> > scatterlists when you COW and skb and do in-place decryption?
> >
> > I guess this change is ok, nsg can only get smaller when the SKB is
> > COW'd.
> >
> 
> > >         memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
> > >         if (!sgout) {
> > >                 nsg = skb_cow_data(skb, 0, &unused) + 1;
> > > -               sgin = kmalloc_array(nsg, sizeof(*sgin), sk->sk_allocation);
> > >                 sgout = sgin;
> > >         }
> 
> I don't think this patch is safe as-is.  sgin_arr is a stack array of size
> MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that it
> walks the whole chain of skbs from skb->next, and can return any number of
> segments.  Therefore we need to heap allocate.  I think I copied the IPSEC
> code here.
> 
> For perf though, we could use the stack array if skb_cow_data returns <=
> MAX_SKB_FRAGS.
> 
> This code is slightly confusing though, since we don't heap allocate in the
> zerocopy case - what happens is that skb_to_sgvec returns -EMSGSIZE, and
> we fall back to the non-zerocopy case, and return again to this function,
> where we then hit the skb_cow_data path and heap allocate.

Thanks for explaining. 
I am missing the point why MAX_SKB_FRAGS sized local array 
sgin has been used in tls_sw_recvmsg(). What is special about MAX_SKB_FRAGS so
that we used it as a size factor for 'sgin'?

Will it be a bad idea to get rid of array 'sgin' on stack and simply kmalloc 'sgin' for 
whatever the number the number of pages returned by iov_iter_npages()?
We can allocate for sgout too with the same kmalloc().

(Using a local array based 'sgin' is coming in the way to achieve sending multiple async
record decryption requests to the accelerator without waiting for previous one to complete.)
Dave Watson July 25, 2018, 9:01 p.m. UTC | #7
On 07/24/18 08:22 AM, Vakul Garg wrote:
> > I don't think this patch is safe as-is.  sgin_arr is a stack array of size
> > MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that it
> > walks the whole chain of skbs from skb->next, and can return any number of
> > segments.  Therefore we need to heap allocate.  I think I copied the IPSEC
> > code here.
> > 
> > For perf though, we could use the stack array if skb_cow_data returns <=
> > MAX_SKB_FRAGS.
> > 
> > This code is slightly confusing though, since we don't heap allocate in the
> > zerocopy case - what happens is that skb_to_sgvec returns -EMSGSIZE, and
> > we fall back to the non-zerocopy case, and return again to this function,
> > where we then hit the skb_cow_data path and heap allocate.
> 
> Thanks for explaining. 
> I am missing the point why MAX_SKB_FRAGS sized local array 
> sgin has been used in tls_sw_recvmsg(). What is special about MAX_SKB_FRAGS so
> that we used it as a size factor for 'sgin'?

There is nothing special about it, in the zerocopy-fastpath if we
happen to fit in MAX_SKB_FRAGS we avoid any kmalloc whatsoever though.
It could be renamed MAX_SC_FOR_FASTPATH or something.

> Will it be a bad idea to get rid of array 'sgin' on stack and simply kmalloc 'sgin' for 
> whatever the number the number of pages returned by iov_iter_npages()?
> We can allocate for sgout too with the same kmalloc().
> 
> (Using a local array based 'sgin' is coming in the way to achieve sending multiple async
> record decryption requests to the accelerator without waiting for previous one to complete.)

Yes we could do this, and yes we would need to heap allocate if you
want to support multiple outstanding decryption requests.  I think
async crypto prevents any sort of zerocopy-fastpath, however.
Vakul Garg July 27, 2018, 9:34 a.m. UTC | #8
> -----Original Message-----
> From: Dave Watson [mailto:davejwatson@fb.com]
> Sent: Thursday, July 26, 2018 2:31 AM
> To: Vakul Garg <vakul.garg@nxp.com>
> Cc: David Miller <davem@davemloft.net>; netdev@vger.kernel.org;
> borisp@mellanox.com; aviadye@mellanox.com; Doron Roberts-Kedes
> <doronrk@fb.com>
> Subject: Re: [net-next v5 3/3] net/tls: Remove redundant array allocation.
> 
> On 07/24/18 08:22 AM, Vakul Garg wrote:
> > > I don't think this patch is safe as-is.  sgin_arr is a stack array
> > > of size MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is
> > > that it walks the whole chain of skbs from skb->next, and can return
> > > any number of segments.  Therefore we need to heap allocate.  I
> > > think I copied the IPSEC code here.
> > >
> > > For perf though, we could use the stack array if skb_cow_data
> > > returns <= MAX_SKB_FRAGS.
> > >
> > > This code is slightly confusing though, since we don't heap allocate
> > > in the zerocopy case - what happens is that skb_to_sgvec returns
> > > -EMSGSIZE, and we fall back to the non-zerocopy case, and return
> > > again to this function, where we then hit the skb_cow_data path and
> heap allocate.
> >
> > Thanks for explaining.
> > I am missing the point why MAX_SKB_FRAGS sized local array sgin has
> > been used in tls_sw_recvmsg(). What is special about MAX_SKB_FRAGS so
> > that we used it as a size factor for 'sgin'?
> 
> There is nothing special about it, in the zerocopy-fastpath if we happen to fit
> in MAX_SKB_FRAGS we avoid any kmalloc whatsoever though.
> It could be renamed MAX_SC_FOR_FASTPATH or something.
> 
> > Will it be a bad idea to get rid of array 'sgin' on stack and simply
> > kmalloc 'sgin' for whatever the number the number of pages returned by
> iov_iter_npages()?
> > We can allocate for sgout too with the same kmalloc().
> >
> > (Using a local array based 'sgin' is coming in the way to achieve
> > sending multiple async record decryption requests to the accelerator
> > without waiting for previous one to complete.)
> 
> Yes we could do this, and yes we would need to heap allocate if you want to
> support multiple outstanding decryption requests.  I think async crypto
> prevents any sort of zerocopy-fastpath, however.

We already do a aead_request_alloc (which internally does kmalloc).
To mitigate the cost of kmalloc/kfree for sg lists and aad, I am allocating a 
combined memory chunk for all of these and then segmenting it into
aead_req, aad, sgin, sgout. This way there should be no extra cost for
memory allocations in non-async.
Dave Watson July 27, 2018, 3:38 p.m. UTC | #9
On 07/27/18 09:34 AM, Vakul Garg wrote:
> 
> 
> > -----Original Message-----
> > From: Dave Watson [mailto:davejwatson@fb.com]
> > Sent: Thursday, July 26, 2018 2:31 AM
> > To: Vakul Garg <vakul.garg@nxp.com>
> > Cc: David Miller <davem@davemloft.net>; netdev@vger.kernel.org;
> > borisp@mellanox.com; aviadye@mellanox.com; Doron Roberts-Kedes
> > <doronrk@fb.com>
> > Subject: Re: [net-next v5 3/3] net/tls: Remove redundant array allocation.
> > 
> > On 07/24/18 08:22 AM, Vakul Garg wrote:
> > > Will it be a bad idea to get rid of array 'sgin' on stack and simply
> > > kmalloc 'sgin' for whatever the number the number of pages returned by
> > iov_iter_npages()?
> > > We can allocate for sgout too with the same kmalloc().
> > >
> > > (Using a local array based 'sgin' is coming in the way to achieve
> > > sending multiple async record decryption requests to the accelerator
> > > without waiting for previous one to complete.)
> > 
> > Yes we could do this, and yes we would need to heap allocate if you want to
> > support multiple outstanding decryption requests.  I think async crypto
> > prevents any sort of zerocopy-fastpath, however.
> 
> We already do a aead_request_alloc (which internally does kmalloc).
> To mitigate the cost of kmalloc/kfree for sg lists and aad, I am allocating a 
> combined memory chunk for all of these and then segmenting it into
> aead_req, aad, sgin, sgout. This way there should be no extra cost for
> memory allocations in non-async.

Makes sense, sounds good to me.
Vakul Garg Aug. 1, 2018, 1:49 p.m. UTC | #10
> -----Original Message-----
> From: Dave Watson [mailto:davejwatson@fb.com]
> Sent: Monday, July 23, 2018 10:05 PM
> To: David Miller <davem@davemloft.net>
> Cc: Vakul Garg <vakul.garg@nxp.com>; netdev@vger.kernel.org;
> borisp@mellanox.com; aviadye@mellanox.com; Doron Roberts-Kedes
> <doronrk@fb.com>
> Subject: Re: [net-next v5 3/3] net/tls: Remove redundant array allocation.
> 
> On 07/21/18 07:25 PM, David Miller wrote:
> > From: Vakul Garg <vakul.garg@nxp.com>
> > Date: Thu, 19 Jul 2018 21:56:13 +0530
> >
> > > In function decrypt_skb(), array allocation in case when sgout is
> > > NULL is unnecessary. Instead, local variable sgin_arr[] can be used.
> > >
> > > Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
> >
> > Hmmm...
> >
> > Dave, can you take a look at this?  Do you think there might have been
> > a reason you felt that you needed to dynamically allocate the
> > scatterlists when you COW and skb and do in-place decryption?
> >
> > I guess this change is ok, nsg can only get smaller when the SKB is
> > COW'd.
> >
> 
> > >         memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
> > >         if (!sgout) {
> > >                 nsg = skb_cow_data(skb, 0, &unused) + 1;
> > > -               sgin = kmalloc_array(nsg, sizeof(*sgin), sk->sk_allocation);
> > >                 sgout = sgin;
> > >         }
> 
> I don't think this patch is safe as-is.  sgin_arr is a stack array of size
> MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that it
> walks the whole chain of skbs from skb->next, and can return any number of
> segments.  Therefore we need to heap allocate.  I think I copied the IPSEC
> code here.
> 
> For perf though, we could use the stack array if skb_cow_data returns <=
> MAX_SKB_FRAGS.

skb_cow_data() is being called only when caller passes sgout=NULL (i.e.
non-zero copy case). In case of zero-copy, we do not call skb_cow_data()
and just assume that MAX_SKB_FRAGS+2 sized scatterlist array sgin_arr[]
is sufficient. This assumption could be wrong. So skb_cow_data() should be
called unconditionally to determine number of scatterlist entries required
for skb.

> 
> This code is slightly confusing though, since we don't heap allocate in the
> zerocopy case - what happens is that skb_to_sgvec returns -EMSGSIZE, and
> we fall back to the non-zerocopy case, and return again to this function,
> where we then hit the skb_cow_data path and heap allocate.

If skb_to_sgvec return -EMSGSIZE, decrypt_skb() would return failure, 
resulting in abort of TLS session.
Dave Watson Aug. 1, 2018, 8:52 p.m. UTC | #11
On 08/01/18 01:49 PM, Vakul Garg wrote:
> > I don't think this patch is safe as-is.  sgin_arr is a stack array of size
> > MAX_SKB_FRAGS (+ overhead), while my read of skb_cow_data is that it
> > walks the whole chain of skbs from skb->next, and can return any number of
> > segments.  Therefore we need to heap allocate.  I think I copied the IPSEC
> > code here.
> > 
> > For perf though, we could use the stack array if skb_cow_data returns <=
> > MAX_SKB_FRAGS.
> 
> skb_cow_data() is being called only when caller passes sgout=NULL (i.e.
> non-zero copy case). In case of zero-copy, we do not call skb_cow_data()
> and just assume that MAX_SKB_FRAGS+2 sized scatterlist array sgin_arr[]
> is sufficient. This assumption could be wrong. So skb_cow_data() should be
> called unconditionally to determine number of scatterlist entries required
> for skb.

I agree it is best to unify them.  I was originally worried about perf
with the extra allocation (which you proposed fixing by merging with
the crypto allocation, which would be great), and the perf of
skb_cow_data().  Zerocopy doesn't require skb_cow_data(), but we do
have to walk the skbs to calculate nsg correctly.

However skb_cow_data perf might be fine after your fix "strparser: Call
skb_unclone conditionally".
diff mbox series

Patch

diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index e15ace0ebd79..1aa2d46713d7 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -704,7 +704,6 @@  int decrypt_skb(struct sock *sk, struct sk_buff *skb,
 	memcpy(iv, tls_ctx->rx.iv, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
 	if (!sgout) {
 		nsg = skb_cow_data(skb, 0, &unused) + 1;
-		sgin = kmalloc_array(nsg, sizeof(*sgin), sk->sk_allocation);
 		sgout = sgin;
 	}
 
@@ -725,9 +724,6 @@  int decrypt_skb(struct sock *sk, struct sk_buff *skb,
 				rxm->full_len - tls_ctx->rx.overhead_size,
 				skb, sk->sk_allocation);
 
-	if (sgin != &sgin_arr[0])
-		kfree(sgin);
-
 	return ret;
 }