Samuel Thibault wrote on Mon, Apr 17, 2023 at 12:07:04AM +0200: > The existing documentation was not telling that one has to create a PPP > channel and a PPP interface to get PPPoL2TP data offloading working. > > Also, tunnel switching was not described, so that people were thinking > it was not supported, while it actually is. > > Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx> Just passing by, thanks! The update made me ask a couple more questions so I've commented below, but I think this is already useful in itself so don't hold back for me. > --- > Documentation/networking/l2tp.rst | 59 ++++++++++++++++++++++++++++++++++++-- > 1 file changed, 56 insertions(+), 3 deletions(-) > > --- a/Documentation/networking/l2tp.rst > +++ b/Documentation/networking/l2tp.rst > @@ -387,11 +387,12 @@ Sample userspace code: > - Create session PPPoX data socket:: > > struct sockaddr_pppol2tp sax; > - int fd; > + int ret; > > /* Note, the tunnel socket must be bound already, else it > * will not be ready > */ > + int session_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); > sax.sa_family = AF_PPPOX; > sax.sa_protocol = PX_PROTO_OL2TP; > sax.pppol2tp.fd = tunnel_fd; > @@ -406,12 +407,64 @@ Sample userspace code: > /* session_fd is the fd of the session's PPPoL2TP socket. > * tunnel_fd is the fd of the tunnel UDP / L2TPIP socket. > */ > - fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax)); > - if (fd < 0 ) { > + ret = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax)); > + if (ret < 0 ) { > return -errno; > } > return 0; > > + - Create PPP channel:: > + > + int chindx; > + ret = ioctl(session_fd, PPPIOCGCHAN, &chindx); > + if (ret < 0) > + return -errno; > + > + int ppp_chan_fd = open("/dev/ppp", O_RDWR); > + > + ret = ioctl(ppp_chan_fd, PPPIOCATTCHAN, &chindx); > + if (ret < 0) > + return -errno; > + > +Non-data PPP frames will be available for read on `ppp_chan_fd`. > + > + - Create PPP interface:: > + > + int ppp_if_fd = open("/dev/ppp", O_RDWR); > + > + int ifunit; > + ret = ioctl(ppp_if_fd, PPPIOCNEWUNIT, &ifunit); > + if (ret < 0) > + return -errno; > + > + ret = ioctl(ppp_chan_fd, PPPIOCCONNECT, ifunit); > + if (ret < 0) > + return -errno; > + > +The ppp<ifunit> interface can then be configured as usual with SIOCSIFMTU, > +SIOCSIFADDR, SIOCSIFDSTADDR, SIOCSIFNETMASK, and activated by setting IFF_UP > +with SIOCSIFFLAGS (That somewhat makes it sounds like the "new" netlink interface cannot be used (e.g. ip command); although I guess sommeone implementing this would be more likely to use the ioctls than not so having the names can be a timesaver?) Also, this got me wondering if the 'if' fd can be closed immediately or if the interface will be removed when the fd is closed (probably not?) If the fd can immediately be closed, could the chan fd or another fd be used instead, saving an open? > + > + - Tunnel switching is supported by bridging channels:: > + > + int chindx; > + ret = ioctl(session_fd, PPPIOCGCHAN, &chindx); > + if (ret < 0) > + return -errno; > + > + int chindx2; > + ret = ioctl(session_fd2, PPPIOCGCHAN, &chind2x); > + if (ret < 0) > + return -errno; > + > + int ppp_chan_fd = open("/dev/ppp", O_RDWR); > + > + ret = ioctl(ppp_chan_fd, PPPIOCBRIDGECHAN, &chindx2); > + if (ret < 0) > + return -errno; > + > + close(ppp_chan_fd); > + > Old L2TPv2-only API > ------------------- > -- Dominique Martinet | Asmadeus