NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: PR/36864 CVS commit: src/sys/opencrypto
Hi,
I've had a look at it.
In general it is a good idea - see conclusion below.
Let's do some calculations ...
I've compressed /dev/zero with gzip -9 - result:
size output
1024 -> 29 -> factor 35
10240 -> 45 -> factor 227
102400 -> 133 -> factor 769
1024000 -> 1026 -> factor 998
10240000 -> 9981 -> factor 1025
remark: 1024000000 -> 995308 -> factor 1028, it looks like we won't get
much better factors at all.
ZBUF is 10 at the moment, so we get the following size factors,
aggregated size factors and buffer sizes (assumed last is 1000000)
4 - 4 - 1950
8 - 12 - 3901
16 - 28 - 7812
32 - 60 - 15625
64 - 124 - 31250
128 - 292 - 62500
256 - 548 - 125000
512 - 1060 - 230000
1024 - 2084 - 500000
2048 - 4132 - 1000000 -> max buffer 1978038 (near 2 MB)
remark: If we will never get much better factor than 1030 at all, ZBUF =
8 would be large enougth. My test above seems to point to that.
There are two use-cases for the opencrypto stuff - as far as I know:
1. IPSEC
2. /dev/crypto
Let's look at 1 first:
The reasonable max. size for network packets for common network types is
1500 or 9k for jumbo frames.
So lets assume 10k. This will lead to a max factor of 227 in compressing
only 0 bytes. This mean, you have 45 bytes of input size, resulting in a
180 byte start buffer. In order to do the decompression you need 6
allocations (180+360+720+1440+2880+5760 = 11340).
This is much better than 10240/180 = 57 buffer allocations.
In my PR, I've mentioned a minimum start size for the algorithm. I've
fixed it to 2k with the idea that a power of two is a good idea and all
normal network packets will fit into one buffer when decompressed.
Till now I think that it would be a good idea to create a sysctl
variable that defines a minimum start buffer size that should be used if
4*size is smaller. The variable should have a default value of 0 - no
minimum size.
This allows the admin to set it to e.g. 1500 (or 9k if jumbo frames are
used for compressed traffic) so that "normal" network packets will fit
into one buffer regardless of the compression factor.
For 10k pakets 1500 will lead to only 3 allocations (1500, 3000, 6000)
I think this would be a even better performance boost for IPSEC, because
if we can get everything into one buffer, we avoid copying everything
again at end of decompression ...
Let's look at 2:
In general we cannot assume anything about the size that gets compressed
or decompressed.
The limit of 1000000 Bytes max. chunk size may be a very hard thing
here. (Sorry, I do not use /dev/crypto, so I don't know anything about
realy reasonable sizes.)
In general, I think for /dev/crypto it would be better to allow any size
for compression/decompression and do the copyin/copyout in parts. (There
must be a reason why all compression lib interfaces are designed like
this ...)
Again, I do not know if this would break some semanticts of the
interface for /dev/crypto with overlapping in-/out-buffers.
And I've no Idea if all hardware devices would be able to handle this.
Perhaps there is already an interface mode for /dev/crypto that allows
partial work and continuations - I've never looked for this up to now.
remark: That may conflict with the change done some PR's before by
setting Z_FINISH in compression - that needs to get "tunable" to support
this ...
The current Patch will limit decompression to something a little bit
less 2MB. This may be OK, but I would be surprised if it is, because 2MB
is not very much for user-level stuff.
Conclusion:
For IPSEC this change is a great step into the right direction.
But I recommend adding a sysctl variable with a minimum start size too.
Due to the fact that I do not use /dev/crypto, I cannot decide if the
limit to ca. 2MB in decompression is OK or not.
Last, some ideas from my side for /dev/crypto:
For /dev/crypto usage I think that the internal interfaces of opencrypto
are not optimal.
The aproach to get everything into some "objects" and operate on them,
creating new objects, sounds like a commonly used aproach in object
oriented programming.
This aproach is not optimal for data-stream processing, because it
assumes that we have endless memory if we are going to process larger
amounts of data - it will not scale. It is no good idea to do this on
user level and inside the kernel such an aproach has lost nothing - my
oppion.
The current patch will speed up /dev/crypto work, so it is a step into
the right direction for /dev/crypto usage too.
In the interface of /dev/crypto the user needs to reserve enougth
user-level memory to copy back everything.
So the user-process knows something about the expected size of the
thing. (Or makes a dummy call just in order to get the required size
information without any data transfer.)
Perhaps this can be used to do some even better heuristics when
allocating buffer space. If there are some limit-checks at /dev/crypto
syscall level, the size used there should be used here too. (At least a
comment that references theese values is missing here.)
Perhaps a max result size parameter makes sence in the calling interface
of deflate/gzip-routines, to avoid useless decompression that cannot be
copied back to user level due to size reasons. Or the "rest" gets
decompressed into a static garbage buffer in order get the result-size,
if required.
The "best sollution" would be (from my point of view), if the whole
internal interface get changed, so that partial data transfer may
directly happen from/to the user level and the result-size gets
allocated (and expanded if needed) by the caller.
Of cause this would break interchangeability with other implementations
and I'm not shure it this realy make sense.
I also simply do not know what kind of "productive" user-level programs
are "designed" to use compresion via /dev/crypto.
All network data stream related things should be inside of the kernel -
my oppinion - for performance reasons. Sorry, I'm no friend of placeing
kernel functionality (mainly data stream or network packet processing)
in user-level programs.
(racoon (IKE) and IPSEC is a good example here: (fast) data-stream
processing inside the kernel - key-exchange, access validation and other
complex things in a user-level program that configures the kernel IPSEC
parts.)
For testing and development of something /dev/crypto might be a very
nice thing, of cause.
Best regards
W. Stukenbrock
Matthias Drochner wrote:
The following reply was made to PR kern/36864; it has been noted by GNATS.
From: "Matthias Drochner" <drochner%netbsd.org@localhost>
To: gnats-bugs%gnats.NetBSD.org@localhost
Cc:
Subject: PR/36864 CVS commit: src/sys/opencrypto
Date: Fri, 18 Feb 2011 22:02:10 +0000
Module Name: src
Committed By: drochner
Date: Fri Feb 18 22:02:09 UTC 2011
Modified Files:
src/sys/opencrypto: deflate.c
Log Message:
redo result buffer allocation, to avoid dynamic allocations:
-use exponentially growing buffer sizes instead of just linear extension
-drop the dynamic allocation of buffer metadata introduced in rev.1.8 --
if the initial array is not sufficient something is wrong
-apply some (arbitrary, heuristic) limit so that compressed data
which extract into insane amounts of constant data don't kill the system
This addresses PR kern/36864 by Wolfgang Stukenbrock. Some tuning
might be useful, but hopefully this is an improvement already.
To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/sys/opencrypto/deflate.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Home |
Main Index |
Thread Index |
Old Index