Subject: [IPsec] My comments on "Proposed improvements to ESP"

From: "Scott Fluhrer (sfluhrer)" <[email-masked]>
Date: Tue, 28 Jul 2020 21:24:37 +0000

I glanced the proposal, and I have doubts as to how well it works, and in particular, how well it would work in parallelized decryption.  As I understand it, the antireplay window the decryptor checks against is specified in the 'Sender ID/Window ID' field.  If the decryptor can handle only one packet for a specific antireplay window, then the level of parallelism that the decryptor can use is entirely up to the encryptor, which might not take the decryptor's needs into consideration.  For example, if the encryptor decides to send every packet with the same Sender ID/Window ID, then the decryptor would be forced to use a single thread, which eliminates most of the advantage this proposal claimed to offer.

So, does this proposal include any way for the decryptor to suggest (either at SA negotiation time or dynamically) the behavior the encryptor is supposed to follow?

And, if the decryptor can handle a single antireplay window with multiple threads, then most of the parallelizability benefits aren't there (and parallelizing in the encrypt direction is fairly straight-forward; the only non-parallelizable step is assigning the sequence number to each packet, and that's comparatively straight-forward).

In addition, during the WG meeting, I groused in the chat about requiring the receiver to track a large (and not tightly bounded) number of independent sequence windows; I believe that is an issue as well.  On the IPsec dataplanes I've worked on, we tried to keep the data structures simple (and we could not dynamically allocate memory if we saw a sender id/window id that we hadn't seen before).  Now, it has since occurred to me that the data plane could have a number of antireplay windows, and if it saw a sender id/window id that it hadn't seen before, then (after validating the packet), it could send a message to the control plane (which would allocate/refresh the antireplay window, and possible retire a not-recently-used one).  However, that strikes me as adding significant complexity.

I believe that this was asked on the mailing list already, but I will repeat it: what advantage does this approach have over the 'having independent SAs with separate SPIs' approach?

As for the idea of moving the integrity check value before the encapsulated packet, well, that idea might help on your platform; however it strikes me that the advantage would likely be fairly platform dependent.  However, if you are getting rid of the trailer, how would this idea extend to transport mode?  Where would you place the NH field (this is a question, not a criticism; moving the NH field up front is likely to be a benefit).

---

From: Tero Kivinen <[email-masked]>
Date: Wed, 29 Jul 2020 15:57:01 +0300

Scott Fluhrer \(sfluhrer\) writes:
> As for the idea of moving the integrity check value before the
> encapsulated packet, well, that idea might help on your platform;
> however it strikes me that the advantage would likely be fairly
> platform dependent.

Yes. In several kernel implementations the packets are formed as mbufs
which are linked list of pieces of packets, and in that kind of
environments there is easy ways to add/remove bytes to/from start or
to/from the end without needing to copy anything.

In case you have single big buffer for the whole packet then removing
stuff from the end or adding stuff to the end is possible without any
copying provided you have enough space in your buffer. Adding stuff to
the beginning of the packet might require you to copy the whole
packet...

Also the need to read (while receiving packet) the ICV is only after
you have already decrypted the whole packet (if using AEAD), and want
to verify that the value matches. When the ICV is at the end of packet
that means it might already be in the cpu cache, as cpu read the last
bytes of the packet and the cache line might be big enough to include
ICV. If we need to go back to the beginning to read the ICV it might
not be in the cache anymore.

Anyways I do not think we should be doing to much optimizatin based on
the one specific operating system, cpu, or architecture.

If we would be doing this from the scratch, then it might be worth of
investigating different operating systems, different cpus and see if
we can find out what kind of optimizations we can do and how do they
affect, but I do not think we want to make too much changes this late
for just very small gains (my guess is that moving ICV optimization
is not really visible in tests that include actual network). 
-- 
[email-masked]

---

From: Steffen Klassert <[email-masked]>
Date: Wed, 29 Jul 2020 15:58:08 +0200

> to/from the end without needing to copy anything.

On Linux both can happen, packets can be constructed with a scatter-gather
list or as a single linear buffer. In both cases we have headroom to
add headers, but tailroom is not guaranteed. So in most cases we either
need to allocate a new scatter-gather list entry for the trailer, or
we have to allocate a bigger buffer and to copy the packet data.

But yes, it depends on the platform.

> the beginning of the packet might require you to copy the whole

We need space to add the headers at the beginning anyways. With the
trailer, we need space on both ends.

> not be in the cache anymore.

Right, this is true indeed.