| .. SPDX-License-Identifier: GPL-2.0 | |
| ==== | |
| L2TP | |
| ==== | |
| Layer 2 Tunneling Protocol (L2TP) allows L2 frames to be tunneled over | |
| an IP network. | |
| This document covers the kernel's L2TP subsystem. It documents kernel | |
| APIs for application developers who want to use the L2TP subsystem and | |
| it provides some technical details about the internal implementation | |
| which may be useful to kernel developers and maintainers. | |
| Overview | |
| ======== | |
| The kernel's L2TP subsystem implements the datapath for L2TPv2 and | |
| L2TPv3. L2TPv2 is carried over UDP. L2TPv3 is carried over UDP or | |
| directly over IP (protocol 115). | |
| The L2TP RFCs define two basic kinds of L2TP packets: control packets | |
| (the "control plane"), and data packets (the "data plane"). The kernel | |
| deals only with data packets. The more complex control packets are | |
| handled by user space. | |
| An L2TP tunnel carries one or more L2TP sessions. Each tunnel is | |
| associated with a socket. Each session is associated with a virtual | |
| netdevice, e.g. ``pppN``, ``l2tpethN``, through which data frames pass | |
| to/from L2TP. Fields in the L2TP header identify the tunnel or session | |
| and whether it is a control or data packet. When tunnels and sessions | |
| are set up using the Linux kernel API, we're just setting up the L2TP | |
| data path. All aspects of the control protocol are to be handled by | |
| user space. | |
| This split in responsibilities leads to a natural sequence of | |
| operations when establishing tunnels and sessions. The procedure looks | |
| like this: | |
| 1) Create a tunnel socket. Exchange L2TP control protocol messages | |
| with the peer over that socket in order to establish a tunnel. | |
| 2) Create a tunnel context in the kernel, using information | |
| obtained from the peer using the control protocol messages. | |
| 3) Exchange L2TP control protocol messages with the peer over the | |
| tunnel socket in order to establish a session. | |
| 4) Create a session context in the kernel using information | |
| obtained from the peer using the control protocol messages. | |
| L2TP APIs | |
| ========= | |
| This section documents each userspace API of the L2TP subsystem. | |
| Tunnel Sockets | |
| -------------- | |
| L2TPv2 always uses UDP. L2TPv3 may use UDP or IP encapsulation. | |
| To create a tunnel socket for use by L2TP, the standard POSIX | |
| socket API is used. | |
| For example, for a tunnel using IPv4 addresses and UDP encapsulation:: | |
| int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
| Or for a tunnel using IPv6 addresses and IP encapsulation:: | |
| int sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP); | |
| UDP socket programming doesn't need to be covered here. | |
| IPPROTO_L2TP is an IP protocol type implemented by the kernel's L2TP | |
| subsystem. The L2TPIP socket address is defined in struct | |
| sockaddr_l2tpip and struct sockaddr_l2tpip6 at | |
| `include/uapi/linux/l2tp.h`_. The address includes the L2TP tunnel | |
| (connection) id. To use L2TP IP encapsulation, an L2TPv3 application | |
| should bind the L2TPIP socket using the locally assigned | |
| tunnel id. When the peer's tunnel id and IP address is known, a | |
| connect must be done. | |
| If the L2TP application needs to handle L2TPv3 tunnel setup requests | |
| from peers using L2TPIP, it must open a dedicated L2TPIP | |
| socket to listen for those requests and bind the socket using tunnel | |
| id 0 since tunnel setup requests are addressed to tunnel id 0. | |
| An L2TP tunnel and all of its sessions are automatically closed when | |
| its tunnel socket is closed. | |
| Netlink API | |
| ----------- | |
| L2TP applications use netlink to manage L2TP tunnel and session | |
| instances in the kernel. The L2TP netlink API is defined in | |
| `include/uapi/linux/l2tp.h`_. | |
| L2TP uses `Generic Netlink`_ (GENL). Several commands are defined: | |
| Create, Delete, Modify and Get for tunnel and session | |
| instances, e.g. ``L2TP_CMD_TUNNEL_CREATE``. The API header lists the | |
| netlink attribute types that can be used with each command. | |
| Tunnel and session instances are identified by a locally unique | |
| 32-bit id. L2TP tunnel ids are given by ``L2TP_ATTR_CONN_ID`` and | |
| ``L2TP_ATTR_PEER_CONN_ID`` attributes and L2TP session ids are given | |
| by ``L2TP_ATTR_SESSION_ID`` and ``L2TP_ATTR_PEER_SESSION_ID`` | |
| attributes. If netlink is used to manage L2TPv2 tunnel and session | |
| instances, the L2TPv2 16-bit tunnel/session id is cast to a 32-bit | |
| value in these attributes. | |
| In the ``L2TP_CMD_TUNNEL_CREATE`` command, ``L2TP_ATTR_FD`` tells the | |
| kernel the tunnel socket fd being used. If not specified, the kernel | |
| creates a kernel socket for the tunnel, using IP parameters set in | |
| ``L2TP_ATTR_IP[6]_SADDR``, ``L2TP_ATTR_IP[6]_DADDR``, | |
| ``L2TP_ATTR_UDP_SPORT``, ``L2TP_ATTR_UDP_DPORT`` attributes. Kernel | |
| sockets are used to implement unmanaged L2TPv3 tunnels (iproute2's "ip | |
| l2tp" commands). If ``L2TP_ATTR_FD`` is given, it must be a socket fd | |
| that is already bound and connected. There is more information about | |
| unmanaged tunnels later in this document. | |
| ``L2TP_CMD_TUNNEL_CREATE`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y Sets the tunnel (connection) id. | |
| PEER_CONN_ID Y Sets the peer tunnel (connection) id. | |
| PROTO_VERSION Y Protocol version. 2 or 3. | |
| ENCAP_TYPE Y Encapsulation type: UDP or IP. | |
| FD N Tunnel socket file descriptor. | |
| UDP_CSUM N Enable IPv4 UDP checksums. Used only if FD is | |
| not set. | |
| UDP_ZERO_CSUM6_TX N Zero IPv6 UDP checksum on transmit. Used only | |
| if FD is not set. | |
| UDP_ZERO_CSUM6_RX N Zero IPv6 UDP checksum on receive. Used only if | |
| FD is not set. | |
| IP_SADDR N IPv4 source address. Used only if FD is not | |
| set. | |
| IP_DADDR N IPv4 destination address. Used only if FD is | |
| not set. | |
| UDP_SPORT N UDP source port. Used only if FD is not set. | |
| UDP_DPORT N UDP destination port. Used only if FD is not | |
| set. | |
| IP6_SADDR N IPv6 source address. Used only if FD is not | |
| set. | |
| IP6_DADDR N IPv6 destination address. Used only if FD is | |
| not set. | |
| DEBUG N Debug flags. | |
| ================== ======== === | |
| ``L2TP_CMD_TUNNEL_DESTROY`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y Identifies the tunnel id to be destroyed. | |
| ================== ======== === | |
| ``L2TP_CMD_TUNNEL_MODIFY`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y Identifies the tunnel id to be modified. | |
| DEBUG N Debug flags. | |
| ================== ======== === | |
| ``L2TP_CMD_TUNNEL_GET`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID N Identifies the tunnel id to be queried. | |
| Ignored in DUMP requests. | |
| ================== ======== === | |
| ``L2TP_CMD_SESSION_CREATE`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y The parent tunnel id. | |
| SESSION_ID Y Sets the session id. | |
| PEER_SESSION_ID Y Sets the parent session id. | |
| PW_TYPE Y Sets the pseudowire type. | |
| DEBUG N Debug flags. | |
| RECV_SEQ N Enable rx data sequence numbers. | |
| SEND_SEQ N Enable tx data sequence numbers. | |
| LNS_MODE N Enable LNS mode (auto-enable data sequence | |
| numbers). | |
| RECV_TIMEOUT N Timeout to wait when reordering received | |
| packets. | |
| L2SPEC_TYPE N Sets layer2-specific-sublayer type (L2TPv3 | |
| only). | |
| COOKIE N Sets optional cookie (L2TPv3 only). | |
| PEER_COOKIE N Sets optional peer cookie (L2TPv3 only). | |
| IFNAME N Sets interface name (L2TPv3 only). | |
| ================== ======== === | |
| For Ethernet session types, this will create an l2tpeth virtual | |
| interface which can then be configured as required. For PPP session | |
| types, a PPPoL2TP socket must also be opened and connected, mapping it | |
| onto the new session. This is covered in "PPPoL2TP Sockets" later. | |
| ``L2TP_CMD_SESSION_DESTROY`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y Identifies the parent tunnel id of the session | |
| to be destroyed. | |
| SESSION_ID Y Identifies the session id to be destroyed. | |
| IFNAME N Identifies the session by interface name. If | |
| set, this overrides any CONN_ID and SESSION_ID | |
| attributes. Currently supported for L2TPv3 | |
| Ethernet sessions only. | |
| ================== ======== === | |
| ``L2TP_CMD_SESSION_MODIFY`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID Y Identifies the parent tunnel id of the session | |
| to be modified. | |
| SESSION_ID Y Identifies the session id to be modified. | |
| IFNAME N Identifies the session by interface name. If | |
| set, this overrides any CONN_ID and SESSION_ID | |
| attributes. Currently supported for L2TPv3 | |
| Ethernet sessions only. | |
| DEBUG N Debug flags. | |
| RECV_SEQ N Enable rx data sequence numbers. | |
| SEND_SEQ N Enable tx data sequence numbers. | |
| LNS_MODE N Enable LNS mode (auto-enable data sequence | |
| numbers). | |
| RECV_TIMEOUT N Timeout to wait when reordering received | |
| packets. | |
| ================== ======== === | |
| ``L2TP_CMD_SESSION_GET`` attributes:- | |
| ================== ======== === | |
| Attribute Required Use | |
| ================== ======== === | |
| CONN_ID N Identifies the tunnel id to be queried. | |
| Ignored for DUMP requests. | |
| SESSION_ID N Identifies the session id to be queried. | |
| Ignored for DUMP requests. | |
| IFNAME N Identifies the session by interface name. | |
| If set, this overrides any CONN_ID and | |
| SESSION_ID attributes. Ignored for DUMP | |
| requests. Currently supported for L2TPv3 | |
| Ethernet sessions only. | |
| ================== ======== === | |
| Application developers should refer to `include/uapi/linux/l2tp.h`_ for | |
| netlink command and attribute definitions. | |
| Sample userspace code using libmnl_: | |
| - Open L2TP netlink socket:: | |
| struct nl_sock *nl_sock; | |
| int l2tp_nl_family_id; | |
| nl_sock = nl_socket_alloc(); | |
| genl_connect(nl_sock); | |
| genl_id = genl_ctrl_resolve(nl_sock, L2TP_GENL_NAME); | |
| - Create a tunnel:: | |
| struct nlmsghdr *nlh; | |
| struct genlmsghdr *gnlh; | |
| nlh = mnl_nlmsg_put_header(buf); | |
| nlh->nlmsg_type = genl_id; /* assigned to genl socket */ | |
| nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; | |
| nlh->nlmsg_seq = seq; | |
| gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); | |
| gnlh->cmd = L2TP_CMD_TUNNEL_CREATE; | |
| gnlh->version = L2TP_GENL_VERSION; | |
| gnlh->reserved = 0; | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_FD, tunl_sock_fd); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid); | |
| mnl_attr_put_u8(nlh, L2TP_ATTR_PROTO_VERSION, protocol_version); | |
| mnl_attr_put_u16(nlh, L2TP_ATTR_ENCAP_TYPE, encap); | |
| - Create a session:: | |
| struct nlmsghdr *nlh; | |
| struct genlmsghdr *gnlh; | |
| nlh = mnl_nlmsg_put_header(buf); | |
| nlh->nlmsg_type = genl_id; /* assigned to genl socket */ | |
| nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; | |
| nlh->nlmsg_seq = seq; | |
| gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); | |
| gnlh->cmd = L2TP_CMD_SESSION_CREATE; | |
| gnlh->version = L2TP_GENL_VERSION; | |
| gnlh->reserved = 0; | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_SESSION_ID, peer_sid); | |
| mnl_attr_put_u16(nlh, L2TP_ATTR_PW_TYPE, pwtype); | |
| /* there are other session options which can be set using netlink | |
| * attributes during session creation -- see l2tp.h | |
| */ | |
| - Delete a session:: | |
| struct nlmsghdr *nlh; | |
| struct genlmsghdr *gnlh; | |
| nlh = mnl_nlmsg_put_header(buf); | |
| nlh->nlmsg_type = genl_id; /* assigned to genl socket */ | |
| nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; | |
| nlh->nlmsg_seq = seq; | |
| gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); | |
| gnlh->cmd = L2TP_CMD_SESSION_DELETE; | |
| gnlh->version = L2TP_GENL_VERSION; | |
| gnlh->reserved = 0; | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid); | |
| - Delete a tunnel and all of its sessions (if any):: | |
| struct nlmsghdr *nlh; | |
| struct genlmsghdr *gnlh; | |
| nlh = mnl_nlmsg_put_header(buf); | |
| nlh->nlmsg_type = genl_id; /* assigned to genl socket */ | |
| nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; | |
| nlh->nlmsg_seq = seq; | |
| gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); | |
| gnlh->cmd = L2TP_CMD_TUNNEL_DELETE; | |
| gnlh->version = L2TP_GENL_VERSION; | |
| gnlh->reserved = 0; | |
| mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); | |
| PPPoL2TP Session Socket API | |
| --------------------------- | |
| For PPP session types, a PPPoL2TP socket must be opened and connected | |
| to the L2TP session. | |
| When creating PPPoL2TP sockets, the application provides information | |
| to the kernel about the tunnel and session in a socket connect() | |
| call. Source and destination tunnel and session ids are provided, as | |
| well as the file descriptor of a UDP or L2TPIP socket. See struct | |
| pppol2tp_addr in `include/linux/if_pppol2tp.h`_. For historical reasons, | |
| there are unfortunately slightly different address structures for | |
| L2TPv2/L2TPv3 IPv4/IPv6 tunnels and userspace must use the appropriate | |
| structure that matches the tunnel socket type. | |
| Userspace may control behavior of the tunnel or session using | |
| setsockopt and ioctl on the PPPoX socket. The following socket | |
| options are supported:- | |
| ========= =========================================================== | |
| DEBUG bitmask of debug message categories. See below. | |
| SENDSEQ - 0 => don't send packets with sequence numbers | |
| - 1 => send packets with sequence numbers | |
| RECVSEQ - 0 => receive packet sequence numbers are optional | |
| - 1 => drop receive packets without sequence numbers | |
| LNSMODE - 0 => act as LAC. | |
| - 1 => act as LNS. | |
| REORDERTO reorder timeout (in millisecs). If 0, don't try to reorder. | |
| ========= =========================================================== | |
| In addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided | |
| to retrieve tunnel and session statistics from the kernel using the | |
| PPPoX socket of the appropriate tunnel or session. | |
| Sample userspace code: | |
| - Create session PPPoX data socket:: | |
| /* Input: the L2TP tunnel UDP socket `tunnel_fd`, which needs to be | |
| * bound already (both sockname and peername), otherwise it will not be | |
| * ready. | |
| */ | |
| struct sockaddr_pppol2tp sax; | |
| int session_fd; | |
| int ret; | |
| session_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP); | |
| if (session_fd < 0) | |
| return -errno; | |
| sax.sa_family = AF_PPPOX; | |
| sax.sa_protocol = PX_PROTO_OL2TP; | |
| sax.pppol2tp.fd = tunnel_fd; | |
| sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr; | |
| sax.pppol2tp.addr.sin_port = addr->sin_port; | |
| sax.pppol2tp.addr.sin_family = AF_INET; | |
| sax.pppol2tp.s_tunnel = tunnel_id; | |
| sax.pppol2tp.s_session = session_id; | |
| sax.pppol2tp.d_tunnel = peer_tunnel_id; | |
| sax.pppol2tp.d_session = peer_session_id; | |
| /* session_fd is the fd of the session's PPPoL2TP socket. | |
| * tunnel_fd is the fd of the tunnel UDP / L2TPIP socket. | |
| */ | |
| ret = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax)); | |
| if (ret < 0 ) { | |
| close(session_fd); | |
| return -errno; | |
| } | |
| return session_fd; | |
| L2TP control packets will still be available for read on `tunnel_fd`. | |
| - Create PPP channel:: | |
| /* Input: the session PPPoX data socket `session_fd` which was created | |
| * as described above. | |
| */ | |
| int ppp_chan_fd; | |
| int chindx; | |
| int ret; | |
| ret = ioctl(session_fd, PPPIOCGCHAN, &chindx); | |
| if (ret < 0) | |
| return -errno; | |
| ppp_chan_fd = open("/dev/ppp", O_RDWR); | |
| if (ppp_chan_fd < 0) | |
| return -errno; | |
| ret = ioctl(ppp_chan_fd, PPPIOCATTCHAN, &chindx); | |
| if (ret < 0) { | |
| close(ppp_chan_fd); | |
| return -errno; | |
| } | |
| return ppp_chan_fd; | |
| LCP PPP frames will be available for read on `ppp_chan_fd`. | |
| - Create PPP interface:: | |
| /* Input: the PPP channel `ppp_chan_fd` which was created as described | |
| * above. | |
| */ | |
| int ifunit = -1; | |
| int ppp_if_fd; | |
| int ret; | |
| ppp_if_fd = open("/dev/ppp", O_RDWR); | |
| if (ppp_if_fd < 0) | |
| return -errno; | |
| ret = ioctl(ppp_if_fd, PPPIOCNEWUNIT, &ifunit); | |
| if (ret < 0) { | |
| close(ppp_if_fd); | |
| return -errno; | |
| } | |
| ret = ioctl(ppp_chan_fd, PPPIOCCONNECT, &ifunit); | |
| if (ret < 0) { | |
| close(ppp_if_fd); | |
| return -errno; | |
| } | |
| return ppp_if_fd; | |
| IPCP/IPv6CP PPP frames will be available for read on `ppp_if_fd`. | |
| The ppp<ifunit> interface can then be configured as usual with netlink's | |
| RTM_NEWLINK, RTM_NEWADDR, RTM_NEWROUTE, or ioctl's SIOCSIFMTU, SIOCSIFADDR, | |
| SIOCSIFDSTADDR, SIOCSIFNETMASK, SIOCSIFFLAGS, or with the `ip` command. | |
| - Bridging L2TP sessions which have PPP pseudowire types (this is also called | |
| L2TP tunnel switching or L2TP multihop) is supported by bridging the PPP | |
| channels of the two L2TP sessions to be bridged:: | |
| /* Input: the session PPPoX data sockets `session_fd1` and `session_fd2` | |
| * which were created as described further above. | |
| */ | |
| int ppp_chan_fd; | |
| int chindx1; | |
| int chindx2; | |
| int ret; | |
| ret = ioctl(session_fd1, PPPIOCGCHAN, &chindx1); | |
| if (ret < 0) | |
| return -errno; | |
| ret = ioctl(session_fd2, PPPIOCGCHAN, &chindx2); | |
| if (ret < 0) | |
| return -errno; | |
| ppp_chan_fd = open("/dev/ppp", O_RDWR); | |
| if (ppp_chan_fd < 0) | |
| return -errno; | |
| ret = ioctl(ppp_chan_fd, PPPIOCATTCHAN, &chindx1); | |
| if (ret < 0) { | |
| close(ppp_chan_fd); | |
| return -errno; | |
| } | |
| ret = ioctl(ppp_chan_fd, PPPIOCBRIDGECHAN, &chindx2); | |
| close(ppp_chan_fd); | |
| if (ret < 0) | |
| return -errno; | |
| return 0; | |
| It can be noted that when bridging PPP channels, the PPP session is not locally | |
| terminated, and no local PPP interface is created. PPP frames arriving on one | |
| channel are directly passed to the other channel, and vice versa. | |
| The PPP channel does not need to be kept open. Only the session PPPoX data | |
| sockets need to be kept open. | |
| More generally, it is also possible in the same way to e.g. bridge a PPPoL2TP | |
| PPP channel with other types of PPP channels, such as PPPoE. | |
| See more details for the PPP side in ppp_generic.rst. | |
| Old L2TPv2-only API | |
| ------------------- | |
| When L2TP was first added to the Linux kernel in 2.6.23, it | |
| implemented only L2TPv2 and did not include a netlink API. Instead, | |
| tunnel and session instances in the kernel were managed directly using | |
| only PPPoL2TP sockets. The PPPoL2TP socket is used as described in | |
| section "PPPoL2TP Session Socket API" but tunnel and session instances | |
| are automatically created on a connect() of the socket instead of | |
| being created by a separate netlink request: | |
| - Tunnels are managed using a tunnel management socket which is a | |
| dedicated PPPoL2TP socket, connected to (invalid) session | |
| id 0. The L2TP tunnel instance is created when the PPPoL2TP | |
| tunnel management socket is connected and is destroyed when the | |
| socket is closed. | |
| - Session instances are created in the kernel when a PPPoL2TP | |
| socket is connected to a non-zero session id. Session parameters | |
| are set using setsockopt. The L2TP session instance is destroyed | |
| when the socket is closed. | |
| This API is still supported but its use is discouraged. Instead, new | |
| L2TPv2 applications should use netlink to first create the tunnel and | |
| session, then create a PPPoL2TP socket for the session. | |
| Unmanaged L2TPv3 tunnels | |
| ------------------------ | |
| The kernel L2TP subsystem also supports static (unmanaged) L2TPv3 | |
| tunnels. Unmanaged tunnels have no userspace tunnel socket, and | |
| exchange no control messages with the peer to set up the tunnel; the | |
| tunnel is configured manually at each end of the tunnel. All | |
| configuration is done using netlink. There is no need for an L2TP | |
| userspace application in this case -- the tunnel socket is created by | |
| the kernel and configured using parameters sent in the | |
| ``L2TP_CMD_TUNNEL_CREATE`` netlink request. The ``ip`` utility of | |
| ``iproute2`` has commands for managing static L2TPv3 tunnels; do ``ip | |
| l2tp help`` for more information. | |
| Debugging | |
| --------- | |
| The L2TP subsystem offers a range of debugging interfaces through the | |
| debugfs filesystem. | |
| To access these interfaces, the debugfs filesystem must first be mounted:: | |
| # mount -t debugfs debugfs /debug | |
| Files under the l2tp directory can then be accessed, providing a summary | |
| of the current population of tunnel and session contexts existing in the | |
| kernel:: | |
| # cat /debug/l2tp/tunnels | |
| The debugfs files should not be used by applications to obtain L2TP | |
| state information because the file format is subject to change. It is | |
| implemented to provide extra debug information to help diagnose | |
| problems. Applications should instead use the netlink API. | |
| In addition the L2TP subsystem implements tracepoints using the standard | |
| kernel event tracing API. The available L2TP events can be reviewed as | |
| follows:: | |
| # find /debug/tracing/events/l2tp | |
| Finally, /proc/net/pppol2tp is also provided for backwards compatibility | |
| with the original pppol2tp code. It lists information about L2TPv2 | |
| tunnels and sessions only. Its use is discouraged. | |
| Internal Implementation | |
| ======================= | |
| This section is for kernel developers and maintainers. | |
| Sockets | |
| ------- | |
| UDP sockets are implemented by the networking core. When an L2TP | |
| tunnel is created using a UDP socket, the socket is set up as an | |
| encapsulated UDP socket by setting encap_rcv and encap_destroy | |
| callbacks on the UDP socket. l2tp_udp_encap_recv is called when | |
| packets are received on the socket. l2tp_udp_encap_destroy is called | |
| when userspace closes the socket. | |
| L2TPIP sockets are implemented in `net/l2tp/l2tp_ip.c`_ and | |
| `net/l2tp/l2tp_ip6.c`_. | |
| Tunnels | |
| ------- | |
| The kernel keeps a struct l2tp_tunnel context per L2TP tunnel. The | |
| l2tp_tunnel is always associated with a UDP or L2TP/IP socket and | |
| keeps a list of sessions in the tunnel. When a tunnel is first | |
| registered with L2TP core, the reference count on the socket is | |
| increased. This ensures that the socket cannot be removed while L2TP's | |
| data structures reference it. | |
| Tunnels are identified by a unique tunnel id. The id is 16-bit for | |
| L2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit | |
| value. | |
| Tunnels are kept in a per-net list, indexed by tunnel id. The | |
| tunnel id namespace is shared by L2TPv2 and L2TPv3. | |
| Handling tunnel socket close is perhaps the most tricky part of the | |
| L2TP implementation. If userspace closes a tunnel socket, the L2TP | |
| tunnel and all of its sessions must be closed and destroyed. Since the | |
| tunnel context holds a ref on the tunnel socket, the socket's | |
| sk_destruct won't be called until the tunnel sock_put's its | |
| socket. For UDP sockets, when userspace closes the tunnel socket, the | |
| socket's encap_destroy handler is invoked, which L2TP uses to initiate | |
| its tunnel close actions. For L2TPIP sockets, the socket's close | |
| handler initiates the same tunnel close actions. All sessions are | |
| first closed. Each session drops its tunnel ref. When the tunnel ref | |
| reaches zero, the tunnel drops its socket ref. | |
| Sessions | |
| -------- | |
| The kernel keeps a struct l2tp_session context for each session. Each | |
| session has private data which is used for data specific to the | |
| session type. With L2TPv2, the session always carries PPP | |
| traffic. With L2TPv3, the session can carry Ethernet frames (Ethernet | |
| pseudowire) or other data types such as PPP, ATM, HDLC or Frame | |
| Relay. Linux currently implements only Ethernet and PPP session types. | |
| Some L2TP session types also have a socket (PPP pseudowires) while | |
| others do not (Ethernet pseudowires). | |
| Like tunnels, L2TP sessions are identified by a unique | |
| session id. Just as with tunnel ids, the session id is 16-bit for | |
| L2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit | |
| value. | |
| Sessions hold a ref on their parent tunnel to ensure that the tunnel | |
| stays extant while one or more sessions references it. | |
| Sessions are kept in a per-net list. L2TPv2 sessions and L2TPv3 | |
| sessions are stored in separate lists. L2TPv2 sessions are keyed | |
| by a 32-bit key made up of the 16-bit tunnel ID and 16-bit | |
| session ID. L2TPv3 sessions are keyed by the 32-bit session ID, since | |
| L2TPv3 session ids are unique across all tunnels. | |
| Although the L2TPv3 RFC specifies that L2TPv3 session ids are not | |
| scoped by the tunnel, the Linux implementation has historically | |
| allowed this. Such session id collisions are supported using a per-net | |
| hash table keyed by sk and session ID. When looking up L2TPv3 | |
| sessions, the list entry may link to multiple sessions with that | |
| session ID, in which case the session matching the given sk (tunnel) | |
| is used. | |
| PPP | |
| --- | |
| `net/l2tp/l2tp_ppp.c`_ implements the PPPoL2TP socket family. Each PPP | |
| session has a PPPoL2TP socket. | |
| The PPPoL2TP socket's sk_user_data references the l2tp_session. | |
| Userspace sends and receives PPP packets over L2TP using a PPPoL2TP | |
| socket. Only PPP control frames pass over this socket: PPP data | |
| packets are handled entirely by the kernel, passing between the L2TP | |
| session and its associated ``pppN`` netdev through the PPP channel | |
| interface of the kernel PPP subsystem. | |
| The L2TP PPP implementation handles the closing of a PPPoL2TP socket | |
| by closing its corresponding L2TP session. This is complicated because | |
| it must consider racing with netlink session create/destroy requests | |
| and pppol2tp_connect trying to reconnect with a session that is in the | |
| process of being closed. PPP sessions hold a ref on their associated | |
| socket in order that the socket remains extants while the session | |
| references it. | |
| Ethernet | |
| -------- | |
| `net/l2tp/l2tp_eth.c`_ implements L2TPv3 Ethernet pseudowires. It | |
| manages a netdev for each session. | |
| L2TP Ethernet sessions are created and destroyed by netlink request, | |
| or are destroyed when the tunnel is destroyed. Unlike PPP sessions, | |
| Ethernet sessions do not have an associated socket. | |
| Miscellaneous | |
| ============= | |
| RFCs | |
| ---- | |
| The kernel code implements the datapath features specified in the | |
| following RFCs: | |
| ======= =============== =================================== | |
| RFC2661 L2TPv2 https://tools.ietf.org/html/rfc2661 | |
| RFC3931 L2TPv3 https://tools.ietf.org/html/rfc3931 | |
| RFC4719 L2TPv3 Ethernet https://tools.ietf.org/html/rfc4719 | |
| ======= =============== =================================== | |
| Implementations | |
| --------------- | |
| A number of open source applications use the L2TP kernel subsystem: | |
| ============ ============================================== | |
| iproute2 https://github.com/shemminger/iproute2 | |
| go-l2tp https://github.com/katalix/go-l2tp | |
| tunneldigger https://github.com/wlanslovenija/tunneldigger | |
| xl2tpd https://github.com/xelerance/xl2tpd | |
| ============ ============================================== | |
| Limitations | |
| ----------- | |
| The current implementation has a number of limitations: | |
| 1) Interfacing with openvswitch is not yet implemented. It may be | |
| useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels. | |
| 2) VLAN pseudowires are implemented using an ``l2tpethN`` interface | |
| configured with a VLAN sub-interface. Since L2TPv3 VLAN | |
| pseudowires carry one and only one VLAN, it may be better to use | |
| a single netdevice rather than an ``l2tpethN`` and ``l2tpethN``:M | |
| pair per VLAN session. The netlink attribute | |
| ``L2TP_ATTR_VLAN_ID`` was added for this, but it was never | |
| implemented. | |
| Testing | |
| ------- | |
| Unmanaged L2TPv3 Ethernet features are tested by the kernel's built-in | |
| selftests. See `tools/testing/selftests/net/l2tp.sh`_. | |
| Another test suite, l2tp-ktest_, covers all | |
| of the L2TP APIs and tunnel/session types. This may be integrated into | |
| the kernel's built-in L2TP selftests in the future. | |
| .. Links | |
| .. _Generic Netlink: generic_netlink.html | |
| .. _libmnl: https://www.netfilter.org/projects/libmnl | |
| .. _include/uapi/linux/l2tp.h: ../../../include/uapi/linux/l2tp.h | |
| .. _include/linux/if_pppol2tp.h: ../../../include/linux/if_pppol2tp.h | |
| .. _net/l2tp/l2tp_ip.c: ../../../net/l2tp/l2tp_ip.c | |
| .. _net/l2tp/l2tp_ip6.c: ../../../net/l2tp/l2tp_ip6.c | |
| .. _net/l2tp/l2tp_ppp.c: ../../../net/l2tp/l2tp_ppp.c | |
| .. _net/l2tp/l2tp_eth.c: ../../../net/l2tp/l2tp_eth.c | |
| .. _tools/testing/selftests/net/l2tp.sh: ../../../tools/testing/selftests/net/l2tp.sh | |
| .. _l2tp-ktest: https://github.com/katalix/l2tp-ktest |