Subject: Re: [PATCH net] l2tp: Allow duplicate session creation with UDP

From: Guillaume Nault <[email-masked]>
Date: Fri, 17 Jan 2020 14:43:27 +0100

On Thu, Jan 16, 2020 at 09:05:01PM +0000, Tom Parkin wrote:
> On  Thu, Jan 16, 2020 at 20:28:27 +0100, Guillaume Nault wrote:
> > On Thu, Jan 16, 2020 at 12:31:43PM +0000, Tom Parkin wrote:
> > > However, there's nothing to prevent user space from using the same UDP
> > > port for multiple tunnels, at which point this relaxation of the RFC
> > > rules would break down again.
> > > 
> > Multiplexing L2TP tunnels on top of non-connected UDP sockets might be
> > a nice optimisation for someone using many tunnels (like hundred of
> > thouthands), but I'm afraid the rest of the L2TP code is not ready to
> > handle such load anyway. And the current implementation only allows
> > one tunnel for each UDP socket anyway.
> 
> TBH I was thinking more of the case where multiple sockets are bound and
> connected to the same address/port (SO_REUSEADDR).  There's still a
> 1:1 mapping of tunnel:socket, but it's possible to have packets for tunnel
> A arrive on tunnel B's socket and vice versa.
> 
> It's a bit of a corner case, I grant you.
> 
Creating several sockets to handle the same tunnel (as identified by
its 5-tuple) may be doable with SO_REUSEPORT, with an ebpf program to
direct the packet to the right socket depending on the session ID. The
session ID would be local to the so_reuseport group. So I guess that
even this kind of setup can be achieved with non-global session IDs (I
haven't tried though, so I might have missed something).

> > > Since UDP-encap can also be broken in the face of duplicated L2TPv3
> > > session IDs, I think its better that the kernel continue to enforce
> > > the RFC.
> > How is UDP-encap broken with duplicate session IDs (as long as a UDP
> > socket can only one have one tunnel associated with it and that no
> > duplicate session IDs are allowed inside the same tunnel)?
> > 
> > It all boils down to what's the scope of a session ID. For me it has
> > always been the parent tunnel. But if that's in contradiction with
> > RFC 3931, I'd be happy to know.
> 
> For RFC 2661 the session ID is scoped to the tunnel.  Section 3.1
> says:
> 
>   "Session ID indicates the identifier for a session within a tunnel."
> 
> Control and data packets share the same header which includes both the
> tunnel and session ID with 16 bits allocated to each.  So it's always
> possible to tell from the data packet header which tunnel the session is
> associated with.
> 
> RFC 3931 changed the scheme.  Control packets now include a 32-bit
> "Control Connection ID" (analogous to the Tunnel ID).  Data packets
> have a session header specific to the packet-switching network in use:
> the RFC describes schemes for both IP and UDP, both of which employ a
> 32-bit session ID.  Section 4.1 says:
> 
>   "The Session ID alone provides the necessary context for all further
>   packet processing"
> 
> Since neither UDP nor IP encapsulated data packets include the control
> connection ID, the session ID must be unique to the LCCE to allow
> identification of the session.

Well my understanding was that the tunnel was implicitely given by the
UDP and IP headers. I don't think that multiplexing tunnels over the
same UDP connection made any sense with L2TPv2, and the kernel never
supported it natively (it might be possible with SO_REUSEPORT). Given
that the tunnel ID field was redundant with the lower headers, it made
sense to me that L2TPv3 dropped it (note that the kernel ignores the
L2TPv2 tunnel ID field on Rx). At least that was my understanding.

But as your quote says, the session ID _alone_ should provide all the
L2TP context. So I guess the spirit of the RFC is that there's a single
global namespace for session IDs. Now, practically speaking, I don't
see how scoped session IDs makes us incompatible, unless we consider
that a given session can be shared between several remote hosts (the
cross-talk case in my other email). Also, sharing a session over
several hosts would mean that L2TPv3 sessions aren't point-to-point,
which the control plane doesn't seem to take into account.