mbox series

[net-next,0/1] Introducing OpenVPN Data Channel Offload

Message ID 20240106215740.14770-1-antonio@openvpn.net (mailing list archive)
Headers show
Series Introducing OpenVPN Data Channel Offload | expand

Message

Antonio Quartulli Jan. 6, 2024, 9:57 p.m. UTC
Hi all!

After several months of work, I am finally
sending a new version of the OpenVPN Data Channel Offload kernel
module (aka `ovpn`) for official review.

The OpenVPN community has since long been interested in moving the fast path
to kernel space. `ovpn` finally helps achieving this goal.

`ovpn` is essentialy a device driver that allows creating a virtual
network interface to handle the OpenVPN data channel. Any traffic
entering the interface is encrypted, encapsulated and sent to the
appropriate destination.

`ovpn` requires OpenVPN in userspace
to run along its side in order to be properly configured and maintained
during its life cycle.

The `ovpn` interface can be created/destroyed and then
configured via Netlink API.

Specifically OpenVPN in userspace will:
* create the `ovpn` interface
* establish the connection with one or more peers
* perform TLS handshake and negotiate any protocol parameter
* configure the `ovpn` interface with peer data (ip/port, keys, etc.)
* handle any subsequent control channel communication

I'd like to point out the control channel is fully handles in userspace.
The idea is to keep the `ovpn` kernel module as simple as possible and
let userspace handle all the non-data (non-fast-path) features.

NOTE: some of you may already know `ovpn-dco` the out-of-tree predecessor
of `ovpn`. However, be aware that the two are not API compatible and
therefore OpenVPN 2.6 will not work with this new `ovpn` module.
More adjustments are required.

If you want to test the `ovpn` kernel module, for the time being you can
use the testing tool `ovpn-cli` available here:
https://github.com/OpenVPN/ovpn-dco/tree/master/tests

The `ovpn` code can also be built as out-of-tree module and its code is
available here https://github.com/OpenVPN/ovpn-dco (currently in the dev
branch).

For more technical details please refer to the actual patch commit message.

Please note that the patch touches also a few files outside of the
ovpn-dco folder.
Specifically it adds a new macro named NLA_POLICY_MAX_LEN to net/netlink.h
and also adds a new constant named UDP_ENCAP_OVPNINUDP to linux/udp.h.

I tend to agree that a unique large patch is harder to review, but
splitting the code into several paches proved to be quite cumbersome,
therefore I prefered to not do it. I believe the code can still be
reviewed file by file, despite in the same patch.

** KNOWN ISSUE:
Upon module unloading something is not torn down correctly and sometimes
new packets hit dangling netdev pointers. This problem did not exist
when the RTNL API was implemented (before interface handling was moved
to Netlink). I was hoping to get some feedback from the netdev community
on anything that may look wrong.


Any comment, concern or statement will be appreciated!
Thanks a lot!!

Best Regards,

Antonio Quartulli
OpenVPN Inc.

---

Antonio Quartulli (1):
  net: introduce OpenVPN Data Channel Offload (ovpn)

 MAINTAINERS                    |    8 +
 drivers/net/Kconfig            |   13 +
 drivers/net/Makefile           |    1 +
 drivers/net/ovpn/Makefile      |   21 +
 drivers/net/ovpn/addr.h        |   41 ++
 drivers/net/ovpn/bind.c        |   62 ++
 drivers/net/ovpn/bind.h        |   69 ++
 drivers/net/ovpn/crypto.c      |  154 +++++
 drivers/net/ovpn/crypto.h      |  144 +++++
 drivers/net/ovpn/crypto_aead.c |  367 +++++++++++
 drivers/net/ovpn/crypto_aead.h |   27 +
 drivers/net/ovpn/io.c          |  579 +++++++++++++++++
 drivers/net/ovpn/io.h          |   43 ++
 drivers/net/ovpn/main.c        |  307 +++++++++
 drivers/net/ovpn/main.h        |   39 ++
 drivers/net/ovpn/netlink.c     | 1072 ++++++++++++++++++++++++++++++++
 drivers/net/ovpn/netlink.h     |   23 +
 drivers/net/ovpn/ovpnstruct.h  |   65 ++
 drivers/net/ovpn/peer.c        |  928 +++++++++++++++++++++++++++
 drivers/net/ovpn/peer.h        |  175 ++++++
 drivers/net/ovpn/pktid.c       |  127 ++++
 drivers/net/ovpn/pktid.h       |  116 ++++
 drivers/net/ovpn/proto.h       |  101 +++
 drivers/net/ovpn/rcu.h         |   20 +
 drivers/net/ovpn/skb.h         |   51 ++
 drivers/net/ovpn/sock.c        |  144 +++++
 drivers/net/ovpn/sock.h        |   59 ++
 drivers/net/ovpn/stats.c       |   20 +
 drivers/net/ovpn/stats.h       |   67 ++
 drivers/net/ovpn/tcp.c         |  473 ++++++++++++++
 drivers/net/ovpn/tcp.h         |   41 ++
 drivers/net/ovpn/udp.c         |  357 +++++++++++
 drivers/net/ovpn/udp.h         |   25 +
 include/uapi/linux/ovpn.h      |  174 ++++++
 include/uapi/linux/udp.h       |    1 +
 35 files changed, 5914 insertions(+)
 create mode 100644 drivers/net/ovpn/Makefile
 create mode 100644 drivers/net/ovpn/addr.h
 create mode 100644 drivers/net/ovpn/bind.c
 create mode 100644 drivers/net/ovpn/bind.h
 create mode 100644 drivers/net/ovpn/crypto.c
 create mode 100644 drivers/net/ovpn/crypto.h
 create mode 100644 drivers/net/ovpn/crypto_aead.c
 create mode 100644 drivers/net/ovpn/crypto_aead.h
 create mode 100644 drivers/net/ovpn/io.c
 create mode 100644 drivers/net/ovpn/io.h
 create mode 100644 drivers/net/ovpn/main.c
 create mode 100644 drivers/net/ovpn/main.h
 create mode 100644 drivers/net/ovpn/netlink.c
 create mode 100644 drivers/net/ovpn/netlink.h
 create mode 100644 drivers/net/ovpn/ovpnstruct.h
 create mode 100644 drivers/net/ovpn/peer.c
 create mode 100644 drivers/net/ovpn/peer.h
 create mode 100644 drivers/net/ovpn/pktid.c
 create mode 100644 drivers/net/ovpn/pktid.h
 create mode 100644 drivers/net/ovpn/proto.h
 create mode 100644 drivers/net/ovpn/rcu.h
 create mode 100644 drivers/net/ovpn/skb.h
 create mode 100644 drivers/net/ovpn/sock.c
 create mode 100644 drivers/net/ovpn/sock.h
 create mode 100644 drivers/net/ovpn/stats.c
 create mode 100644 drivers/net/ovpn/stats.h
 create mode 100644 drivers/net/ovpn/tcp.c
 create mode 100644 drivers/net/ovpn/tcp.h
 create mode 100644 drivers/net/ovpn/udp.c
 create mode 100644 drivers/net/ovpn/udp.h
 create mode 100644 include/uapi/linux/ovpn.h

Comments

Sergey Ryazanov Jan. 6, 2024, 10:29 p.m. UTC | #1
Hi Antonio,

On 06.01.2024 23:57, Antonio Quartulli wrote:
> I tend to agree that a unique large patch is harder to review, but
> splitting the code into several paches proved to be quite cumbersome,
> therefore I prefered to not do it. I believe the code can still be
> reviewed file by file, despite in the same patch.

I am happy to know that project is ongoing. But I had stopped the review 
after reading these lines. You need AI to review at once "35 files 
changed, 5914 insertions(+)". Last time I checked, I was human. Sorry.

Or you can see it like this: if submitter does not care, then why anyone 
else should?

> ** KNOWN ISSUE:
> Upon module unloading something is not torn down correctly and sometimes
> new packets hit dangling netdev pointers. This problem did not exist
> when the RTNL API was implemented (before interface handling was moved
> to Netlink). I was hoping to get some feedback from the netdev community
> on anything that may look wrong.

A small hint, if the series is not going to be merged, then it is better 
to mark it as RFC.

--
Sergey
Antonio Quartulli Jan. 7, 2024, 11:32 p.m. UTC | #2
Hi Sergey,

Thanks for jumping in

On 06/01/2024 23:29, Sergey Ryazanov wrote:
> Hi Antonio,
> 
> On 06.01.2024 23:57, Antonio Quartulli wrote:
>> I tend to agree that a unique large patch is harder to review, but
>> splitting the code into several paches proved to be quite cumbersome,
>> therefore I prefered to not do it. I believe the code can still be
>> reviewed file by file, despite in the same patch.
> 
> I am happy to know that project is ongoing. But I had stopped the review 
> after reading these lines. You need AI to review at once "35 files 
> changed, 5914 insertions(+)". Last time I checked, I was human. Sorry.
> 
> Or you can see it like this: if submitter does not care, then why anyone 
> else should?

I am sorry - I did not mean to be careless/sloppy.

I totally understand, but I truly burnt so much time on finding a 
reasonable way to split this patch that I had to give up at some point.

I get your input, but do you think that turning it into 35 patches of 1 
file each (just as a random example), will make it easier to digest?

Anyway, I will give it another try (the test robot complained about 
something, so it seems I need to resend the patch anyway) and I'll see 
where I land.

Cheers!

> 
>> ** KNOWN ISSUE:
>> Upon module unloading something is not torn down correctly and sometimes
>> new packets hit dangling netdev pointers. This problem did not exist
>> when the RTNL API was implemented (before interface handling was moved
>> to Netlink). I was hoping to get some feedback from the netdev community
>> on anything that may look wrong.
> 
> A small hint, if the series is not going to be merged, then it is better 
> to mark it as RFC.
> 
> -- 
> Sergey
Sergey Ryazanov Jan. 8, 2024, 1:42 a.m. UTC | #3
Hi Antonio,

On 08.01.2024 01:32, Antonio Quartulli wrote:
> Hi Sergey,
> 
> Thanks for jumping in
> 
> On 06/01/2024 23:29, Sergey Ryazanov wrote:
>> Hi Antonio,
>>
>> On 06.01.2024 23:57, Antonio Quartulli wrote:
>>> I tend to agree that a unique large patch is harder to review, but
>>> splitting the code into several paches proved to be quite cumbersome,
>>> therefore I prefered to not do it. I believe the code can still be
>>> reviewed file by file, despite in the same patch.
>>
>> I am happy to know that project is ongoing. But I had stopped the 
>> review after reading these lines. You need AI to review at once "35 
>> files changed, 5914 insertions(+)". Last time I checked, I was human. 
>> Sorry.
>>
>> Or you can see it like this: if submitter does not care, then why 
>> anyone else should?
> 
> I am sorry - I did not mean to be careless/sloppy.

Sure. I would not say this, I just gave you a hint how it can be look 
like. Looks like you did a great job implementing it, lets do a final 
good review before merging it.

> I totally understand, but I truly burnt so much time on finding a 
> reasonable way to split this patch that I had to give up at some point.

Yep, but if submitter did not properly split it, then a reviewer have to 
do this. Right?

> I get your input, but do you think that turning it into 35 patches of 1 
> file each (just as a random example), will make it easier to digest?

It is a pleasure to review a good arranged series that in step-by-step 
manner explains how a functional should be implemented and will work.

Splitting some huge driver into item files is neither a good approach. 
As you already mentioned, it gives almost nothing in terms of the review 
simplification. E.g. some file can contain a set of library functions, 
so checking them without calling examples is nonsense, etc.

Thus, I would suggest to choose a regular approach and turn the code 
into implementation steps. Just imagine a set of steps you would take to 
implement the functionality if you were do it from scratch. You can also 
think of it as a presentation.

Just an example of how I would break such work into separate patches:
1. changes to common kernel components: one patch per changed subsystem 
(e.g. netlink, socket helpers, whatever);
2. skeleton of the future module: initialization, deinitialization, 
registration in the necessary subsystems (genetlink), most of the 
required callbacks are just stubs;
3. basic tunnel management implementation: tunnel creation and 
destroying, network interface creation, etc, again minimalistic, no 
actual packet processing, just drop packets at this stage;
4. tx path implementation: bare minimal data processing;
5. rx path implementation: again bare minimal;
6. various service functions: keepalive, rekeying, peer source address 
updating, etc. better in one-patch-per-feature manner.

This was just a clue. You, as the author, for sure know better how to 
present this in the most understandable way.

Just a couple of general tips. Common changes to other parts of the 
kernel (e.g. mentioned NLA_POLICY_MAX_LEN) should come as a dedicated 
patch with justification for how it makes life easier. Exception here is 
identifiers that the code is going to use (e.g. UDP_ENCAP_OVPNINUDP), it 
is better to add them together with the implementation. Each item patch 
must not break the kernel build. If you use any macro or call any 
routine, they should be added in the same patch or before. Build bot 
will be strongly against patches that break something. As you have 
already seen, it is even intolerant of new compilation warnings :)

> Anyway, I will give it another try (the test robot complained about 
> something, so it seems I need to resend the patch anyway) and I'll see 
> where I land.
> 
> Cheers!

Cheers!

--
Sergey