162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci==== 462306a36Sopenharmony_ciL2TP 562306a36Sopenharmony_ci==== 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciLayer 2 Tunneling Protocol (L2TP) allows L2 frames to be tunneled over 862306a36Sopenharmony_cian IP network. 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciThis document covers the kernel's L2TP subsystem. It documents kernel 1162306a36Sopenharmony_ciAPIs for application developers who want to use the L2TP subsystem and 1262306a36Sopenharmony_ciit provides some technical details about the internal implementation 1362306a36Sopenharmony_ciwhich may be useful to kernel developers and maintainers. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciOverview 1662306a36Sopenharmony_ci======== 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciThe kernel's L2TP subsystem implements the datapath for L2TPv2 and 1962306a36Sopenharmony_ciL2TPv3. L2TPv2 is carried over UDP. L2TPv3 is carried over UDP or 2062306a36Sopenharmony_cidirectly over IP (protocol 115). 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciThe L2TP RFCs define two basic kinds of L2TP packets: control packets 2362306a36Sopenharmony_ci(the "control plane"), and data packets (the "data plane"). The kernel 2462306a36Sopenharmony_cideals only with data packets. The more complex control packets are 2562306a36Sopenharmony_cihandled by user space. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ciAn L2TP tunnel carries one or more L2TP sessions. Each tunnel is 2862306a36Sopenharmony_ciassociated with a socket. Each session is associated with a virtual 2962306a36Sopenharmony_cinetdevice, e.g. ``pppN``, ``l2tpethN``, through which data frames pass 3062306a36Sopenharmony_cito/from L2TP. Fields in the L2TP header identify the tunnel or session 3162306a36Sopenharmony_ciand whether it is a control or data packet. When tunnels and sessions 3262306a36Sopenharmony_ciare set up using the Linux kernel API, we're just setting up the L2TP 3362306a36Sopenharmony_cidata path. All aspects of the control protocol are to be handled by 3462306a36Sopenharmony_ciuser space. 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciThis split in responsibilities leads to a natural sequence of 3762306a36Sopenharmony_cioperations when establishing tunnels and sessions. The procedure looks 3862306a36Sopenharmony_cilike this: 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci 1) Create a tunnel socket. Exchange L2TP control protocol messages 4162306a36Sopenharmony_ci with the peer over that socket in order to establish a tunnel. 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci 2) Create a tunnel context in the kernel, using information 4462306a36Sopenharmony_ci obtained from the peer using the control protocol messages. 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci 3) Exchange L2TP control protocol messages with the peer over the 4762306a36Sopenharmony_ci tunnel socket in order to establish a session. 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci 4) Create a session context in the kernel using information 5062306a36Sopenharmony_ci obtained from the peer using the control protocol messages. 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ciL2TP APIs 5362306a36Sopenharmony_ci========= 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciThis section documents each userspace API of the L2TP subsystem. 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciTunnel Sockets 5862306a36Sopenharmony_ci-------------- 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciL2TPv2 always uses UDP. L2TPv3 may use UDP or IP encapsulation. 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciTo create a tunnel socket for use by L2TP, the standard POSIX 6362306a36Sopenharmony_cisocket API is used. 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ciFor example, for a tunnel using IPv4 addresses and UDP encapsulation:: 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ciOr for a tunnel using IPv6 addresses and IP encapsulation:: 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci int sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciUDP socket programming doesn't need to be covered here. 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciIPPROTO_L2TP is an IP protocol type implemented by the kernel's L2TP 7662306a36Sopenharmony_cisubsystem. The L2TPIP socket address is defined in struct 7762306a36Sopenharmony_cisockaddr_l2tpip and struct sockaddr_l2tpip6 at 7862306a36Sopenharmony_ci`include/uapi/linux/l2tp.h`_. The address includes the L2TP tunnel 7962306a36Sopenharmony_ci(connection) id. To use L2TP IP encapsulation, an L2TPv3 application 8062306a36Sopenharmony_cishould bind the L2TPIP socket using the locally assigned 8162306a36Sopenharmony_citunnel id. When the peer's tunnel id and IP address is known, a 8262306a36Sopenharmony_ciconnect must be done. 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciIf the L2TP application needs to handle L2TPv3 tunnel setup requests 8562306a36Sopenharmony_cifrom peers using L2TPIP, it must open a dedicated L2TPIP 8662306a36Sopenharmony_cisocket to listen for those requests and bind the socket using tunnel 8762306a36Sopenharmony_ciid 0 since tunnel setup requests are addressed to tunnel id 0. 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciAn L2TP tunnel and all of its sessions are automatically closed when 9062306a36Sopenharmony_ciits tunnel socket is closed. 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciNetlink API 9362306a36Sopenharmony_ci----------- 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciL2TP applications use netlink to manage L2TP tunnel and session 9662306a36Sopenharmony_ciinstances in the kernel. The L2TP netlink API is defined in 9762306a36Sopenharmony_ci`include/uapi/linux/l2tp.h`_. 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ciL2TP uses `Generic Netlink`_ (GENL). Several commands are defined: 10062306a36Sopenharmony_ciCreate, Delete, Modify and Get for tunnel and session 10162306a36Sopenharmony_ciinstances, e.g. ``L2TP_CMD_TUNNEL_CREATE``. The API header lists the 10262306a36Sopenharmony_cinetlink attribute types that can be used with each command. 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciTunnel and session instances are identified by a locally unique 10562306a36Sopenharmony_ci32-bit id. L2TP tunnel ids are given by ``L2TP_ATTR_CONN_ID`` and 10662306a36Sopenharmony_ci``L2TP_ATTR_PEER_CONN_ID`` attributes and L2TP session ids are given 10762306a36Sopenharmony_ciby ``L2TP_ATTR_SESSION_ID`` and ``L2TP_ATTR_PEER_SESSION_ID`` 10862306a36Sopenharmony_ciattributes. If netlink is used to manage L2TPv2 tunnel and session 10962306a36Sopenharmony_ciinstances, the L2TPv2 16-bit tunnel/session id is cast to a 32-bit 11062306a36Sopenharmony_civalue in these attributes. 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciIn the ``L2TP_CMD_TUNNEL_CREATE`` command, ``L2TP_ATTR_FD`` tells the 11362306a36Sopenharmony_cikernel the tunnel socket fd being used. If not specified, the kernel 11462306a36Sopenharmony_cicreates a kernel socket for the tunnel, using IP parameters set in 11562306a36Sopenharmony_ci``L2TP_ATTR_IP[6]_SADDR``, ``L2TP_ATTR_IP[6]_DADDR``, 11662306a36Sopenharmony_ci``L2TP_ATTR_UDP_SPORT``, ``L2TP_ATTR_UDP_DPORT`` attributes. Kernel 11762306a36Sopenharmony_cisockets are used to implement unmanaged L2TPv3 tunnels (iproute2's "ip 11862306a36Sopenharmony_cil2tp" commands). If ``L2TP_ATTR_FD`` is given, it must be a socket fd 11962306a36Sopenharmony_cithat is already bound and connected. There is more information about 12062306a36Sopenharmony_ciunmanaged tunnels later in this document. 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci``L2TP_CMD_TUNNEL_CREATE`` attributes:- 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci================== ======== === 12562306a36Sopenharmony_ciAttribute Required Use 12662306a36Sopenharmony_ci================== ======== === 12762306a36Sopenharmony_ciCONN_ID Y Sets the tunnel (connection) id. 12862306a36Sopenharmony_ciPEER_CONN_ID Y Sets the peer tunnel (connection) id. 12962306a36Sopenharmony_ciPROTO_VERSION Y Protocol version. 2 or 3. 13062306a36Sopenharmony_ciENCAP_TYPE Y Encapsulation type: UDP or IP. 13162306a36Sopenharmony_ciFD N Tunnel socket file descriptor. 13262306a36Sopenharmony_ciUDP_CSUM N Enable IPv4 UDP checksums. Used only if FD is 13362306a36Sopenharmony_ci not set. 13462306a36Sopenharmony_ciUDP_ZERO_CSUM6_TX N Zero IPv6 UDP checksum on transmit. Used only 13562306a36Sopenharmony_ci if FD is not set. 13662306a36Sopenharmony_ciUDP_ZERO_CSUM6_RX N Zero IPv6 UDP checksum on receive. Used only if 13762306a36Sopenharmony_ci FD is not set. 13862306a36Sopenharmony_ciIP_SADDR N IPv4 source address. Used only if FD is not 13962306a36Sopenharmony_ci set. 14062306a36Sopenharmony_ciIP_DADDR N IPv4 destination address. Used only if FD is 14162306a36Sopenharmony_ci not set. 14262306a36Sopenharmony_ciUDP_SPORT N UDP source port. Used only if FD is not set. 14362306a36Sopenharmony_ciUDP_DPORT N UDP destination port. Used only if FD is not 14462306a36Sopenharmony_ci set. 14562306a36Sopenharmony_ciIP6_SADDR N IPv6 source address. Used only if FD is not 14662306a36Sopenharmony_ci set. 14762306a36Sopenharmony_ciIP6_DADDR N IPv6 destination address. Used only if FD is 14862306a36Sopenharmony_ci not set. 14962306a36Sopenharmony_ciDEBUG N Debug flags. 15062306a36Sopenharmony_ci================== ======== === 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci``L2TP_CMD_TUNNEL_DESTROY`` attributes:- 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci================== ======== === 15562306a36Sopenharmony_ciAttribute Required Use 15662306a36Sopenharmony_ci================== ======== === 15762306a36Sopenharmony_ciCONN_ID Y Identifies the tunnel id to be destroyed. 15862306a36Sopenharmony_ci================== ======== === 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci``L2TP_CMD_TUNNEL_MODIFY`` attributes:- 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci================== ======== === 16362306a36Sopenharmony_ciAttribute Required Use 16462306a36Sopenharmony_ci================== ======== === 16562306a36Sopenharmony_ciCONN_ID Y Identifies the tunnel id to be modified. 16662306a36Sopenharmony_ciDEBUG N Debug flags. 16762306a36Sopenharmony_ci================== ======== === 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci``L2TP_CMD_TUNNEL_GET`` attributes:- 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci================== ======== === 17262306a36Sopenharmony_ciAttribute Required Use 17362306a36Sopenharmony_ci================== ======== === 17462306a36Sopenharmony_ciCONN_ID N Identifies the tunnel id to be queried. 17562306a36Sopenharmony_ci Ignored in DUMP requests. 17662306a36Sopenharmony_ci================== ======== === 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci``L2TP_CMD_SESSION_CREATE`` attributes:- 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci================== ======== === 18162306a36Sopenharmony_ciAttribute Required Use 18262306a36Sopenharmony_ci================== ======== === 18362306a36Sopenharmony_ciCONN_ID Y The parent tunnel id. 18462306a36Sopenharmony_ciSESSION_ID Y Sets the session id. 18562306a36Sopenharmony_ciPEER_SESSION_ID Y Sets the parent session id. 18662306a36Sopenharmony_ciPW_TYPE Y Sets the pseudowire type. 18762306a36Sopenharmony_ciDEBUG N Debug flags. 18862306a36Sopenharmony_ciRECV_SEQ N Enable rx data sequence numbers. 18962306a36Sopenharmony_ciSEND_SEQ N Enable tx data sequence numbers. 19062306a36Sopenharmony_ciLNS_MODE N Enable LNS mode (auto-enable data sequence 19162306a36Sopenharmony_ci numbers). 19262306a36Sopenharmony_ciRECV_TIMEOUT N Timeout to wait when reordering received 19362306a36Sopenharmony_ci packets. 19462306a36Sopenharmony_ciL2SPEC_TYPE N Sets layer2-specific-sublayer type (L2TPv3 19562306a36Sopenharmony_ci only). 19662306a36Sopenharmony_ciCOOKIE N Sets optional cookie (L2TPv3 only). 19762306a36Sopenharmony_ciPEER_COOKIE N Sets optional peer cookie (L2TPv3 only). 19862306a36Sopenharmony_ciIFNAME N Sets interface name (L2TPv3 only). 19962306a36Sopenharmony_ci================== ======== === 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciFor Ethernet session types, this will create an l2tpeth virtual 20262306a36Sopenharmony_ciinterface which can then be configured as required. For PPP session 20362306a36Sopenharmony_citypes, a PPPoL2TP socket must also be opened and connected, mapping it 20462306a36Sopenharmony_cionto the new session. This is covered in "PPPoL2TP Sockets" later. 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci``L2TP_CMD_SESSION_DESTROY`` attributes:- 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci================== ======== === 20962306a36Sopenharmony_ciAttribute Required Use 21062306a36Sopenharmony_ci================== ======== === 21162306a36Sopenharmony_ciCONN_ID Y Identifies the parent tunnel id of the session 21262306a36Sopenharmony_ci to be destroyed. 21362306a36Sopenharmony_ciSESSION_ID Y Identifies the session id to be destroyed. 21462306a36Sopenharmony_ciIFNAME N Identifies the session by interface name. If 21562306a36Sopenharmony_ci set, this overrides any CONN_ID and SESSION_ID 21662306a36Sopenharmony_ci attributes. Currently supported for L2TPv3 21762306a36Sopenharmony_ci Ethernet sessions only. 21862306a36Sopenharmony_ci================== ======== === 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci``L2TP_CMD_SESSION_MODIFY`` attributes:- 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci================== ======== === 22362306a36Sopenharmony_ciAttribute Required Use 22462306a36Sopenharmony_ci================== ======== === 22562306a36Sopenharmony_ciCONN_ID Y Identifies the parent tunnel id of the session 22662306a36Sopenharmony_ci to be modified. 22762306a36Sopenharmony_ciSESSION_ID Y Identifies the session id to be modified. 22862306a36Sopenharmony_ciIFNAME N Identifies the session by interface name. If 22962306a36Sopenharmony_ci set, this overrides any CONN_ID and SESSION_ID 23062306a36Sopenharmony_ci attributes. Currently supported for L2TPv3 23162306a36Sopenharmony_ci Ethernet sessions only. 23262306a36Sopenharmony_ciDEBUG N Debug flags. 23362306a36Sopenharmony_ciRECV_SEQ N Enable rx data sequence numbers. 23462306a36Sopenharmony_ciSEND_SEQ N Enable tx data sequence numbers. 23562306a36Sopenharmony_ciLNS_MODE N Enable LNS mode (auto-enable data sequence 23662306a36Sopenharmony_ci numbers). 23762306a36Sopenharmony_ciRECV_TIMEOUT N Timeout to wait when reordering received 23862306a36Sopenharmony_ci packets. 23962306a36Sopenharmony_ci================== ======== === 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci``L2TP_CMD_SESSION_GET`` attributes:- 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci================== ======== === 24462306a36Sopenharmony_ciAttribute Required Use 24562306a36Sopenharmony_ci================== ======== === 24662306a36Sopenharmony_ciCONN_ID N Identifies the tunnel id to be queried. 24762306a36Sopenharmony_ci Ignored for DUMP requests. 24862306a36Sopenharmony_ciSESSION_ID N Identifies the session id to be queried. 24962306a36Sopenharmony_ci Ignored for DUMP requests. 25062306a36Sopenharmony_ciIFNAME N Identifies the session by interface name. 25162306a36Sopenharmony_ci If set, this overrides any CONN_ID and 25262306a36Sopenharmony_ci SESSION_ID attributes. Ignored for DUMP 25362306a36Sopenharmony_ci requests. Currently supported for L2TPv3 25462306a36Sopenharmony_ci Ethernet sessions only. 25562306a36Sopenharmony_ci================== ======== === 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ciApplication developers should refer to `include/uapi/linux/l2tp.h`_ for 25862306a36Sopenharmony_cinetlink command and attribute definitions. 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ciSample userspace code using libmnl_: 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci - Open L2TP netlink socket:: 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci struct nl_sock *nl_sock; 26562306a36Sopenharmony_ci int l2tp_nl_family_id; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci nl_sock = nl_socket_alloc(); 26862306a36Sopenharmony_ci genl_connect(nl_sock); 26962306a36Sopenharmony_ci genl_id = genl_ctrl_resolve(nl_sock, L2TP_GENL_NAME); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci - Create a tunnel:: 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci struct nlmsghdr *nlh; 27462306a36Sopenharmony_ci struct genlmsghdr *gnlh; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci nlh = mnl_nlmsg_put_header(buf); 27762306a36Sopenharmony_ci nlh->nlmsg_type = genl_id; /* assigned to genl socket */ 27862306a36Sopenharmony_ci nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 27962306a36Sopenharmony_ci nlh->nlmsg_seq = seq; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); 28262306a36Sopenharmony_ci gnlh->cmd = L2TP_CMD_TUNNEL_CREATE; 28362306a36Sopenharmony_ci gnlh->version = L2TP_GENL_VERSION; 28462306a36Sopenharmony_ci gnlh->reserved = 0; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_FD, tunl_sock_fd); 28762306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); 28862306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid); 28962306a36Sopenharmony_ci mnl_attr_put_u8(nlh, L2TP_ATTR_PROTO_VERSION, protocol_version); 29062306a36Sopenharmony_ci mnl_attr_put_u16(nlh, L2TP_ATTR_ENCAP_TYPE, encap); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci - Create a session:: 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci struct nlmsghdr *nlh; 29562306a36Sopenharmony_ci struct genlmsghdr *gnlh; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci nlh = mnl_nlmsg_put_header(buf); 29862306a36Sopenharmony_ci nlh->nlmsg_type = genl_id; /* assigned to genl socket */ 29962306a36Sopenharmony_ci nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 30062306a36Sopenharmony_ci nlh->nlmsg_seq = seq; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); 30362306a36Sopenharmony_ci gnlh->cmd = L2TP_CMD_SESSION_CREATE; 30462306a36Sopenharmony_ci gnlh->version = L2TP_GENL_VERSION; 30562306a36Sopenharmony_ci gnlh->reserved = 0; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); 30862306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_CONN_ID, peer_tid); 30962306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid); 31062306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_PEER_SESSION_ID, peer_sid); 31162306a36Sopenharmony_ci mnl_attr_put_u16(nlh, L2TP_ATTR_PW_TYPE, pwtype); 31262306a36Sopenharmony_ci /* there are other session options which can be set using netlink 31362306a36Sopenharmony_ci * attributes during session creation -- see l2tp.h 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci - Delete a session:: 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci struct nlmsghdr *nlh; 31962306a36Sopenharmony_ci struct genlmsghdr *gnlh; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci nlh = mnl_nlmsg_put_header(buf); 32262306a36Sopenharmony_ci nlh->nlmsg_type = genl_id; /* assigned to genl socket */ 32362306a36Sopenharmony_ci nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 32462306a36Sopenharmony_ci nlh->nlmsg_seq = seq; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); 32762306a36Sopenharmony_ci gnlh->cmd = L2TP_CMD_SESSION_DELETE; 32862306a36Sopenharmony_ci gnlh->version = L2TP_GENL_VERSION; 32962306a36Sopenharmony_ci gnlh->reserved = 0; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); 33262306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_SESSION_ID, sid); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci - Delete a tunnel and all of its sessions (if any):: 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci struct nlmsghdr *nlh; 33762306a36Sopenharmony_ci struct genlmsghdr *gnlh; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci nlh = mnl_nlmsg_put_header(buf); 34062306a36Sopenharmony_ci nlh->nlmsg_type = genl_id; /* assigned to genl socket */ 34162306a36Sopenharmony_ci nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 34262306a36Sopenharmony_ci nlh->nlmsg_seq = seq; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci gnlh = mnl_nlmsg_put_extra_header(nlh, sizeof(*gnlh)); 34562306a36Sopenharmony_ci gnlh->cmd = L2TP_CMD_TUNNEL_DELETE; 34662306a36Sopenharmony_ci gnlh->version = L2TP_GENL_VERSION; 34762306a36Sopenharmony_ci gnlh->reserved = 0; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci mnl_attr_put_u32(nlh, L2TP_ATTR_CONN_ID, tid); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ciPPPoL2TP Session Socket API 35262306a36Sopenharmony_ci--------------------------- 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ciFor PPP session types, a PPPoL2TP socket must be opened and connected 35562306a36Sopenharmony_cito the L2TP session. 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ciWhen creating PPPoL2TP sockets, the application provides information 35862306a36Sopenharmony_cito the kernel about the tunnel and session in a socket connect() 35962306a36Sopenharmony_cicall. Source and destination tunnel and session ids are provided, as 36062306a36Sopenharmony_ciwell as the file descriptor of a UDP or L2TPIP socket. See struct 36162306a36Sopenharmony_cipppol2tp_addr in `include/linux/if_pppol2tp.h`_. For historical reasons, 36262306a36Sopenharmony_cithere are unfortunately slightly different address structures for 36362306a36Sopenharmony_ciL2TPv2/L2TPv3 IPv4/IPv6 tunnels and userspace must use the appropriate 36462306a36Sopenharmony_cistructure that matches the tunnel socket type. 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ciUserspace may control behavior of the tunnel or session using 36762306a36Sopenharmony_cisetsockopt and ioctl on the PPPoX socket. The following socket 36862306a36Sopenharmony_cioptions are supported:- 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci========= =========================================================== 37162306a36Sopenharmony_ciDEBUG bitmask of debug message categories. See below. 37262306a36Sopenharmony_ciSENDSEQ - 0 => don't send packets with sequence numbers 37362306a36Sopenharmony_ci - 1 => send packets with sequence numbers 37462306a36Sopenharmony_ciRECVSEQ - 0 => receive packet sequence numbers are optional 37562306a36Sopenharmony_ci - 1 => drop receive packets without sequence numbers 37662306a36Sopenharmony_ciLNSMODE - 0 => act as LAC. 37762306a36Sopenharmony_ci - 1 => act as LNS. 37862306a36Sopenharmony_ciREORDERTO reorder timeout (in millisecs). If 0, don't try to reorder. 37962306a36Sopenharmony_ci========= =========================================================== 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ciIn addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided 38262306a36Sopenharmony_cito retrieve tunnel and session statistics from the kernel using the 38362306a36Sopenharmony_ciPPPoX socket of the appropriate tunnel or session. 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ciSample userspace code: 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci - Create session PPPoX data socket:: 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci struct sockaddr_pppol2tp sax; 39062306a36Sopenharmony_ci int fd; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Note, the tunnel socket must be bound already, else it 39362306a36Sopenharmony_ci * will not be ready 39462306a36Sopenharmony_ci */ 39562306a36Sopenharmony_ci sax.sa_family = AF_PPPOX; 39662306a36Sopenharmony_ci sax.sa_protocol = PX_PROTO_OL2TP; 39762306a36Sopenharmony_ci sax.pppol2tp.fd = tunnel_fd; 39862306a36Sopenharmony_ci sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr; 39962306a36Sopenharmony_ci sax.pppol2tp.addr.sin_port = addr->sin_port; 40062306a36Sopenharmony_ci sax.pppol2tp.addr.sin_family = AF_INET; 40162306a36Sopenharmony_ci sax.pppol2tp.s_tunnel = tunnel_id; 40262306a36Sopenharmony_ci sax.pppol2tp.s_session = session_id; 40362306a36Sopenharmony_ci sax.pppol2tp.d_tunnel = peer_tunnel_id; 40462306a36Sopenharmony_ci sax.pppol2tp.d_session = peer_session_id; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* session_fd is the fd of the session's PPPoL2TP socket. 40762306a36Sopenharmony_ci * tunnel_fd is the fd of the tunnel UDP / L2TPIP socket. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_ci fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax)); 41062306a36Sopenharmony_ci if (fd < 0 ) { 41162306a36Sopenharmony_ci return -errno; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci return 0; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciOld L2TPv2-only API 41662306a36Sopenharmony_ci------------------- 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ciWhen L2TP was first added to the Linux kernel in 2.6.23, it 41962306a36Sopenharmony_ciimplemented only L2TPv2 and did not include a netlink API. Instead, 42062306a36Sopenharmony_citunnel and session instances in the kernel were managed directly using 42162306a36Sopenharmony_cionly PPPoL2TP sockets. The PPPoL2TP socket is used as described in 42262306a36Sopenharmony_cisection "PPPoL2TP Session Socket API" but tunnel and session instances 42362306a36Sopenharmony_ciare automatically created on a connect() of the socket instead of 42462306a36Sopenharmony_cibeing created by a separate netlink request: 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci - Tunnels are managed using a tunnel management socket which is a 42762306a36Sopenharmony_ci dedicated PPPoL2TP socket, connected to (invalid) session 42862306a36Sopenharmony_ci id 0. The L2TP tunnel instance is created when the PPPoL2TP 42962306a36Sopenharmony_ci tunnel management socket is connected and is destroyed when the 43062306a36Sopenharmony_ci socket is closed. 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci - Session instances are created in the kernel when a PPPoL2TP 43362306a36Sopenharmony_ci socket is connected to a non-zero session id. Session parameters 43462306a36Sopenharmony_ci are set using setsockopt. The L2TP session instance is destroyed 43562306a36Sopenharmony_ci when the socket is closed. 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ciThis API is still supported but its use is discouraged. Instead, new 43862306a36Sopenharmony_ciL2TPv2 applications should use netlink to first create the tunnel and 43962306a36Sopenharmony_cisession, then create a PPPoL2TP socket for the session. 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ciUnmanaged L2TPv3 tunnels 44262306a36Sopenharmony_ci------------------------ 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ciThe kernel L2TP subsystem also supports static (unmanaged) L2TPv3 44562306a36Sopenharmony_citunnels. Unmanaged tunnels have no userspace tunnel socket, and 44662306a36Sopenharmony_ciexchange no control messages with the peer to set up the tunnel; the 44762306a36Sopenharmony_citunnel is configured manually at each end of the tunnel. All 44862306a36Sopenharmony_ciconfiguration is done using netlink. There is no need for an L2TP 44962306a36Sopenharmony_ciuserspace application in this case -- the tunnel socket is created by 45062306a36Sopenharmony_cithe kernel and configured using parameters sent in the 45162306a36Sopenharmony_ci``L2TP_CMD_TUNNEL_CREATE`` netlink request. The ``ip`` utility of 45262306a36Sopenharmony_ci``iproute2`` has commands for managing static L2TPv3 tunnels; do ``ip 45362306a36Sopenharmony_cil2tp help`` for more information. 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ciDebugging 45662306a36Sopenharmony_ci--------- 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ciThe L2TP subsystem offers a range of debugging interfaces through the 45962306a36Sopenharmony_cidebugfs filesystem. 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciTo access these interfaces, the debugfs filesystem must first be mounted:: 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci # mount -t debugfs debugfs /debug 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ciFiles under the l2tp directory can then be accessed, providing a summary 46662306a36Sopenharmony_ciof the current population of tunnel and session contexts existing in the 46762306a36Sopenharmony_cikernel:: 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci # cat /debug/l2tp/tunnels 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ciThe debugfs files should not be used by applications to obtain L2TP 47262306a36Sopenharmony_cistate information because the file format is subject to change. It is 47362306a36Sopenharmony_ciimplemented to provide extra debug information to help diagnose 47462306a36Sopenharmony_ciproblems. Applications should instead use the netlink API. 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ciIn addition the L2TP subsystem implements tracepoints using the standard 47762306a36Sopenharmony_cikernel event tracing API. The available L2TP events can be reviewed as 47862306a36Sopenharmony_cifollows:: 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci # find /debug/tracing/events/l2tp 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ciFinally, /proc/net/pppol2tp is also provided for backwards compatibility 48362306a36Sopenharmony_ciwith the original pppol2tp code. It lists information about L2TPv2 48462306a36Sopenharmony_citunnels and sessions only. Its use is discouraged. 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ciInternal Implementation 48762306a36Sopenharmony_ci======================= 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ciThis section is for kernel developers and maintainers. 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ciSockets 49262306a36Sopenharmony_ci------- 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ciUDP sockets are implemented by the networking core. When an L2TP 49562306a36Sopenharmony_citunnel is created using a UDP socket, the socket is set up as an 49662306a36Sopenharmony_ciencapsulated UDP socket by setting encap_rcv and encap_destroy 49762306a36Sopenharmony_cicallbacks on the UDP socket. l2tp_udp_encap_recv is called when 49862306a36Sopenharmony_cipackets are received on the socket. l2tp_udp_encap_destroy is called 49962306a36Sopenharmony_ciwhen userspace closes the socket. 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ciL2TPIP sockets are implemented in `net/l2tp/l2tp_ip.c`_ and 50262306a36Sopenharmony_ci`net/l2tp/l2tp_ip6.c`_. 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ciTunnels 50562306a36Sopenharmony_ci------- 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ciThe kernel keeps a struct l2tp_tunnel context per L2TP tunnel. The 50862306a36Sopenharmony_cil2tp_tunnel is always associated with a UDP or L2TP/IP socket and 50962306a36Sopenharmony_cikeeps a list of sessions in the tunnel. When a tunnel is first 51062306a36Sopenharmony_ciregistered with L2TP core, the reference count on the socket is 51162306a36Sopenharmony_ciincreased. This ensures that the socket cannot be removed while L2TP's 51262306a36Sopenharmony_cidata structures reference it. 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ciTunnels are identified by a unique tunnel id. The id is 16-bit for 51562306a36Sopenharmony_ciL2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit 51662306a36Sopenharmony_civalue. 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ciTunnels are kept in a per-net list, indexed by tunnel id. The tunnel 51962306a36Sopenharmony_ciid namespace is shared by L2TPv2 and L2TPv3. The tunnel context can be 52062306a36Sopenharmony_ciderived from the socket's sk_user_data. 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ciHandling tunnel socket close is perhaps the most tricky part of the 52362306a36Sopenharmony_ciL2TP implementation. If userspace closes a tunnel socket, the L2TP 52462306a36Sopenharmony_citunnel and all of its sessions must be closed and destroyed. Since the 52562306a36Sopenharmony_citunnel context holds a ref on the tunnel socket, the socket's 52662306a36Sopenharmony_cisk_destruct won't be called until the tunnel sock_put's its 52762306a36Sopenharmony_cisocket. For UDP sockets, when userspace closes the tunnel socket, the 52862306a36Sopenharmony_cisocket's encap_destroy handler is invoked, which L2TP uses to initiate 52962306a36Sopenharmony_ciits tunnel close actions. For L2TPIP sockets, the socket's close 53062306a36Sopenharmony_cihandler initiates the same tunnel close actions. All sessions are 53162306a36Sopenharmony_cifirst closed. Each session drops its tunnel ref. When the tunnel ref 53262306a36Sopenharmony_cireaches zero, the tunnel puts its socket ref. When the socket is 53362306a36Sopenharmony_cieventually destroyed, its sk_destruct finally frees the L2TP tunnel 53462306a36Sopenharmony_cicontext. 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ciSessions 53762306a36Sopenharmony_ci-------- 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ciThe kernel keeps a struct l2tp_session context for each session. Each 54062306a36Sopenharmony_cisession has private data which is used for data specific to the 54162306a36Sopenharmony_cisession type. With L2TPv2, the session always carries PPP 54262306a36Sopenharmony_citraffic. With L2TPv3, the session can carry Ethernet frames (Ethernet 54362306a36Sopenharmony_cipseudowire) or other data types such as PPP, ATM, HDLC or Frame 54462306a36Sopenharmony_ciRelay. Linux currently implements only Ethernet and PPP session types. 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ciSome L2TP session types also have a socket (PPP pseudowires) while 54762306a36Sopenharmony_ciothers do not (Ethernet pseudowires). We can't therefore use the 54862306a36Sopenharmony_cisocket reference count as the reference count for session 54962306a36Sopenharmony_cicontexts. The L2TP implementation therefore has its own internal 55062306a36Sopenharmony_cireference counts on the session contexts. 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ciLike tunnels, L2TP sessions are identified by a unique 55362306a36Sopenharmony_cisession id. Just as with tunnel ids, the session id is 16-bit for 55462306a36Sopenharmony_ciL2TPv2 and 32-bit for L2TPv3. Internally, the id is stored as a 32-bit 55562306a36Sopenharmony_civalue. 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ciSessions hold a ref on their parent tunnel to ensure that the tunnel 55862306a36Sopenharmony_cistays extant while one or more sessions references it. 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ciSessions are kept in a per-tunnel list, indexed by session id. L2TPv3 56162306a36Sopenharmony_cisessions are also kept in a per-net list indexed by session id, 56262306a36Sopenharmony_cibecause L2TPv3 session ids are unique across all tunnels and L2TPv3 56362306a36Sopenharmony_cidata packets do not contain a tunnel id in the header. This list is 56462306a36Sopenharmony_citherefore needed to find the session context associated with a 56562306a36Sopenharmony_cireceived data packet when the tunnel context cannot be derived from 56662306a36Sopenharmony_cithe tunnel socket. 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ciAlthough the L2TPv3 RFC specifies that L2TPv3 session ids are not 56962306a36Sopenharmony_ciscoped by the tunnel, the kernel does not police this for L2TPv3 UDP 57062306a36Sopenharmony_citunnels and does not add sessions of L2TPv3 UDP tunnels into the 57162306a36Sopenharmony_ciper-net session list. In the UDP receive code, we must trust that the 57262306a36Sopenharmony_citunnel can be identified using the tunnel socket's sk_user_data and 57362306a36Sopenharmony_cilookup the session in the tunnel's session list instead of the per-net 57462306a36Sopenharmony_cisession list. 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ciPPP 57762306a36Sopenharmony_ci--- 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci`net/l2tp/l2tp_ppp.c`_ implements the PPPoL2TP socket family. Each PPP 58062306a36Sopenharmony_cisession has a PPPoL2TP socket. 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ciThe PPPoL2TP socket's sk_user_data references the l2tp_session. 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ciUserspace sends and receives PPP packets over L2TP using a PPPoL2TP 58562306a36Sopenharmony_cisocket. Only PPP control frames pass over this socket: PPP data 58662306a36Sopenharmony_cipackets are handled entirely by the kernel, passing between the L2TP 58762306a36Sopenharmony_cisession and its associated ``pppN`` netdev through the PPP channel 58862306a36Sopenharmony_ciinterface of the kernel PPP subsystem. 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ciThe L2TP PPP implementation handles the closing of a PPPoL2TP socket 59162306a36Sopenharmony_ciby closing its corresponding L2TP session. This is complicated because 59262306a36Sopenharmony_ciit must consider racing with netlink session create/destroy requests 59362306a36Sopenharmony_ciand pppol2tp_connect trying to reconnect with a session that is in the 59462306a36Sopenharmony_ciprocess of being closed. Unlike tunnels, PPP sessions do not hold a 59562306a36Sopenharmony_ciref on their associated socket, so code must be careful to sock_hold 59662306a36Sopenharmony_cithe socket where necessary. For all the details, see commit 59762306a36Sopenharmony_ci3d609342cc04129ff7568e19316ce3d7451a27e8. 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ciEthernet 60062306a36Sopenharmony_ci-------- 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci`net/l2tp/l2tp_eth.c`_ implements L2TPv3 Ethernet pseudowires. It 60362306a36Sopenharmony_cimanages a netdev for each session. 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ciL2TP Ethernet sessions are created and destroyed by netlink request, 60662306a36Sopenharmony_cior are destroyed when the tunnel is destroyed. Unlike PPP sessions, 60762306a36Sopenharmony_ciEthernet sessions do not have an associated socket. 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ciMiscellaneous 61062306a36Sopenharmony_ci============= 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ciRFCs 61362306a36Sopenharmony_ci---- 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ciThe kernel code implements the datapath features specified in the 61662306a36Sopenharmony_cifollowing RFCs: 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci======= =============== =================================== 61962306a36Sopenharmony_ciRFC2661 L2TPv2 https://tools.ietf.org/html/rfc2661 62062306a36Sopenharmony_ciRFC3931 L2TPv3 https://tools.ietf.org/html/rfc3931 62162306a36Sopenharmony_ciRFC4719 L2TPv3 Ethernet https://tools.ietf.org/html/rfc4719 62262306a36Sopenharmony_ci======= =============== =================================== 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ciImplementations 62562306a36Sopenharmony_ci--------------- 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ciA number of open source applications use the L2TP kernel subsystem: 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci============ ============================================== 63062306a36Sopenharmony_ciiproute2 https://github.com/shemminger/iproute2 63162306a36Sopenharmony_cigo-l2tp https://github.com/katalix/go-l2tp 63262306a36Sopenharmony_citunneldigger https://github.com/wlanslovenija/tunneldigger 63362306a36Sopenharmony_cixl2tpd https://github.com/xelerance/xl2tpd 63462306a36Sopenharmony_ci============ ============================================== 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ciLimitations 63762306a36Sopenharmony_ci----------- 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ciThe current implementation has a number of limitations: 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci 1) Multiple UDP sockets with the same 5-tuple address cannot be 64262306a36Sopenharmony_ci used. The kernel's tunnel context is identified using private 64362306a36Sopenharmony_ci data associated with the socket so it is important that each 64462306a36Sopenharmony_ci socket is uniquely identified by its address. 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci 2) Interfacing with openvswitch is not yet implemented. It may be 64762306a36Sopenharmony_ci useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels. 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci 3) VLAN pseudowires are implemented using an ``l2tpethN`` interface 65062306a36Sopenharmony_ci configured with a VLAN sub-interface. Since L2TPv3 VLAN 65162306a36Sopenharmony_ci pseudowires carry one and only one VLAN, it may be better to use 65262306a36Sopenharmony_ci a single netdevice rather than an ``l2tpethN`` and ``l2tpethN``:M 65362306a36Sopenharmony_ci pair per VLAN session. The netlink attribute 65462306a36Sopenharmony_ci ``L2TP_ATTR_VLAN_ID`` was added for this, but it was never 65562306a36Sopenharmony_ci implemented. 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ciTesting 65862306a36Sopenharmony_ci------- 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ciUnmanaged L2TPv3 Ethernet features are tested by the kernel's built-in 66162306a36Sopenharmony_ciselftests. See `tools/testing/selftests/net/l2tp.sh`_. 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciAnother test suite, l2tp-ktest_, covers all 66462306a36Sopenharmony_ciof the L2TP APIs and tunnel/session types. This may be integrated into 66562306a36Sopenharmony_cithe kernel's built-in L2TP selftests in the future. 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci.. Links 66862306a36Sopenharmony_ci.. _Generic Netlink: generic_netlink.html 66962306a36Sopenharmony_ci.. _libmnl: https://www.netfilter.org/projects/libmnl 67062306a36Sopenharmony_ci.. _include/uapi/linux/l2tp.h: ../../../include/uapi/linux/l2tp.h 67162306a36Sopenharmony_ci.. _include/linux/if_pppol2tp.h: ../../../include/linux/if_pppol2tp.h 67262306a36Sopenharmony_ci.. _net/l2tp/l2tp_ip.c: ../../../net/l2tp/l2tp_ip.c 67362306a36Sopenharmony_ci.. _net/l2tp/l2tp_ip6.c: ../../../net/l2tp/l2tp_ip6.c 67462306a36Sopenharmony_ci.. _net/l2tp/l2tp_ppp.c: ../../../net/l2tp/l2tp_ppp.c 67562306a36Sopenharmony_ci.. _net/l2tp/l2tp_eth.c: ../../../net/l2tp/l2tp_eth.c 67662306a36Sopenharmony_ci.. _tools/testing/selftests/net/l2tp.sh: ../../../tools/testing/selftests/net/l2tp.sh 67762306a36Sopenharmony_ci.. _l2tp-ktest: https://github.com/katalix/l2tp-ktest 678