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