sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget#/translations/zh_CN/networking/l2tpmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/zh_TW/networking/l2tpmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/it_IT/networking/l2tpmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/ja_JP/networking/l2tpmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/ko_KR/networking/l2tpmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget#/translations/sp_SP/networking/l2tpmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhh=/var/lib/git/docbuild/linux/Documentation/networking/l2tp.rsthKubhsection)}(hhh](htitle)}(hL2TPh]hL2TP}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hULayer 2 Tunneling Protocol (L2TP) allows L2 frames to be tunneled over an IP network.h]hULayer 2 Tunneling Protocol (L2TP) allows L2 frames to be tunneled over an IP network.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hX 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.h]hX 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.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hhh](h)}(hOverviewh]hOverview}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh)}(hThe 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).h]hThe 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).}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hThe 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.h]hThe 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hXAn 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.h](hAn 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. }(hjhhhNhNubhliteral)}(h``pppN``h]hpppN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh, }(hjhhhNhNubj)}(h ``l2tpethN``h]hl2tpethN}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhXE, 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.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hThis split in responsibilities leads to a natural sequence of operations when establishing tunnels and sessions. The procedure looks like this:h]hThis split in responsibilities leads to a natural sequence of operations when establishing tunnels and sessions. The procedure looks like this:}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK$hhhhubh block_quote)}(hX1) 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. h]henumerated_list)}(hhh](h list_item)}(hCreate a tunnel socket. Exchange L2TP control protocol messages with the peer over that socket in order to establish a tunnel. h]h)}(h~Create a tunnel socket. Exchange L2TP control protocol messages with the peer over that socket in order to establish a tunnel.h]h~Create a tunnel socket. Exchange L2TP control protocol messages with the peer over that socket in order to establish a tunnel.}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK(hjcubah}(h]h ]h"]h$]h&]uh1jahj^ubjb)}(huCreate a tunnel context in the kernel, using information obtained from the peer using the control protocol messages. h]h)}(htCreate a tunnel context in the kernel, using information obtained from the peer using the control protocol messages.h]htCreate a tunnel context in the kernel, using information obtained from the peer using the control protocol messages.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK+hj{ubah}(h]h ]h"]h$]h&]uh1jahj^ubjb)}(hnExchange L2TP control protocol messages with the peer over the tunnel socket in order to establish a session. h]h)}(hmExchange L2TP control protocol messages with the peer over the tunnel socket in order to establish a session.h]hmExchange L2TP control protocol messages with the peer over the tunnel socket in order to establish a session.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjubah}(h]h ]h"]h$]h&]uh1jahj^ubjb)}(huCreate a session context in the kernel using information obtained from the peer using the control protocol messages. h]h)}(htCreate a session context in the kernel using information obtained from the peer using the control protocol messages.h]htCreate a session context in the kernel using information obtained from the peer using the control protocol messages.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK1hjubah}(h]h ]h"]h$]h&]uh1jahj^ubeh}(h]h ]h"]h$]h&]enumtypearabicprefixhsuffix)uh1j\hjXubah}(h]h ]h"]h$]h&]uh1jVhhhK(hhhhubeh}(h]overviewah ]h"]overviewah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h L2TP APIsh]h L2TP APIs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK5ubh)}(h@This section documents each userspace API of the L2TP subsystem.h]h@This section documents each userspace API of the L2TP subsystem.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK7hjhhubh)}(hhh](h)}(hTunnel Socketsh]hTunnel Sockets}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK:ubh)}(h?L2TPv2 always uses UDP. L2TPv3 may use UDP or IP encapsulation.h]h?L2TPv2 always uses UDP. L2TPv3 may use UDP or IP encapsulation.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hFFor example, for a tunnel using IPv4 addresses and UDP encapsulation::h]hEFor example, for a tunnel using IPv4 addresses and UDP encapsulation:}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKAhjhhubh literal_block)}(h6int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);h]h6int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);}hj8sbah}(h]h ]h"]h$]h&]hhuh1j6hhhKChjhhubh)}(h;Or for a tunnel using IPv6 addresses and IP encapsulation::h]h:Or for a tunnel using IPv6 addresses and IP encapsulation:}(hjFhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKEhjhhubj7)}(h8int sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP);h]h8int sockfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP);}hjTsbah}(h]h ]h"]h$]h&]hhuh1j6hhhKGhjhhubh)}(h7UDP socket programming doesn't need to be covered here.h]h9UDP socket programming doesn’t need to be covered here.}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKIhjhhubh)}(hXIPPROTO_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.h](hIPPROTO_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 }(hjphhhNhNubh reference)}(h`include/uapi/linux/l2tp.h`_h]hinclude/uapi/linux/l2tp.h}(hjzhhhNhNubah}(h]h ]h"]h$]h&]nameinclude/uapi/linux/l2tp.hrefuri"../../../include/uapi/linux/l2tp.huh1jxhjpresolvedKubh. 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.}(hjphhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKKhjhhubh)}(hXIf 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.h]hXIf 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKThjhhubh)}(haAn L2TP tunnel and all of its sessions are automatically closed when its tunnel socket is closed.h]haAn L2TP tunnel and all of its sessions are automatically closed when its tunnel socket is closed.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKYhjhhubeh}(h]tunnel-socketsah ]h"]tunnel socketsah$]h&]uh1hhjhhhhhK:ubh)}(hhh](h)}(h Netlink APIh]h Netlink API}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK]ubh)}(hL2TP 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`_.h](h|L2TP applications use netlink to manage L2TP tunnel and session instances in the kernel. The L2TP netlink API is defined in }(hjhhhNhNubjy)}(h`include/uapi/linux/l2tp.h`_h]hinclude/uapi/linux/l2tp.h}(hjhhhNhNubah}(h]h ]h"]h$]h&]nameinclude/uapi/linux/l2tp.hjjuh1jxhjjKubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK_hjhhubh)}(hL2TP 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.h](h L2TP uses }(hjhhhNhNubjy)}(h`Generic Netlink`_h]hGeneric Netlink}(hjhhhNhNubah}(h]h ]h"]h$]h&]nameGeneric Netlinkjgeneric_netlink.htmluh1jxhjjKubhm (GENL). Several commands are defined: Create, Delete, Modify and Get for tunnel and session instances, e.g. }(hjhhhNhNubj)}(h``L2TP_CMD_TUNNEL_CREATE``h]hL2TP_CMD_TUNNEL_CREATE}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubhV. The API header lists the netlink attribute types that can be used with each command.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKchjhhubh)}(hXTunnel 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.h](hiTunnel and session instances are identified by a locally unique 32-bit id. L2TP tunnel ids are given by }(hj#hhhNhNubj)}(h``L2TP_ATTR_CONN_ID``h]hL2TP_ATTR_CONN_ID}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj#ubh and }(hj#hhhNhNubj)}(h``L2TP_ATTR_PEER_CONN_ID``h]hL2TP_ATTR_PEER_CONN_ID}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj#ubh. attributes and L2TP session ids are given by }(hj#hhhNhNubj)}(h``L2TP_ATTR_SESSION_ID``h]hL2TP_ATTR_SESSION_ID}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj#ubh and }(hj#hhhNhNubj)}(h``L2TP_ATTR_PEER_SESSION_ID``h]hL2TP_ATTR_PEER_SESSION_ID}(hjahhhNhNubah}(h]h ]h"]h$]h&]uh1jhj#ubh 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.}(hj#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhjhhubh)}(hXCIn 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.h](hIn the }(hjyhhhNhNubj)}(h``L2TP_CMD_TUNNEL_CREATE``h]hL2TP_CMD_TUNNEL_CREATE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh command, }(hjyhhhNhNubj)}(h``L2TP_ATTR_FD``h]h L2TP_ATTR_FD}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh 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 }(hjyhhhNhNubj)}(h``L2TP_ATTR_IP[6]_SADDR``h]hL2TP_ATTR_IP[6]_SADDR}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh, }(hjyhhhNhNubj)}(h``L2TP_ATTR_IP[6]_DADDR``h]hL2TP_ATTR_IP[6]_DADDR}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh, }(hjyhhhNhNubj)}(h``L2TP_ATTR_UDP_SPORT``h]hL2TP_ATTR_UDP_SPORT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh, }hjysbj)}(h``L2TP_ATTR_UDP_DPORT``h]hL2TP_ATTR_UDP_DPORT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubhu attributes. Kernel sockets are used to implement unmanaged L2TPv3 tunnels (iproute2’s “ip l2tp” commands). If }(hjyhhhNhNubj)}(h``L2TP_ATTR_FD``h]h L2TP_ATTR_FD}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjyubh 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.}(hjyhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKphjhhubh)}(h'``L2TP_CMD_TUNNEL_CREATE`` attributes:-h](j)}(h``L2TP_CMD_TUNNEL_CREATE``h]hL2TP_CMD_TUNNEL_CREATE}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh attributes:-}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKzhjhhubhtable)}(hhh]htgroup)}(hhh](hcolspec)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj(ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj(ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK/uh1j+hj(ubhthead)}(hhh]hrow)}(hhh](hentry)}(hhh]h)}(h Attributeh]h Attribute}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjWubah}(h]h ]h"]h$]h&]uh1jUhjRubjV)}(hhh]h)}(hRequiredh]hRequired}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjnubah}(h]h ]h"]h$]h&]uh1jUhjRubjV)}(hhh]h)}(hUseh]hUse}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK}hjubah}(h]h ]h"]h$]h&]uh1jUhjRubeh}(h]h ]h"]h$]h&]uh1jPhjMubah}(h]h ]h"]h$]h&]uh1jKhj(ubhtbody)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hYh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Sets the tunnel (connection) id.h]h Sets the tunnel (connection) id.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h PEER_CONN_IDh]h PEER_CONN_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h%Sets the peer tunnel (connection) id.h]h%Sets the peer tunnel (connection) id.}(hj.hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj+ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h PROTO_VERSIONh]h PROTO_VERSION}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjKubah}(h]h ]h"]h$]h&]uh1jUhjHubjV)}(hhh]h)}(hjh]hY}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjbubah}(h]h ]h"]h$]h&]uh1jUhjHubjV)}(hhh]h)}(hProtocol version. 2 or 3.h]hProtocol version. 2 or 3.}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjxubah}(h]h ]h"]h$]h&]uh1jUhjHubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h ENCAP_TYPEh]h ENCAP_TYPE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hEncapsulation type: UDP or IP.h]hEncapsulation type: UDP or IP.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hFDh]hFD}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hNh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hTunnel socket file descriptor.h]hTunnel socket file descriptor.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hUDP_CSUMh]hUDP_CSUM}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj3ubah}(h]h ]h"]h$]h&]uh1jUhj0ubjV)}(hhh]h)}(hjh]hN}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjJubah}(h]h ]h"]h$]h&]uh1jUhj0ubjV)}(hhh]h)}(h6Enable IPv4 UDP checksums. Used only if FD is not set.h]h6Enable IPv4 UDP checksums. Used only if FD is not set.}(hjchhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj`ubah}(h]h ]h"]h$]h&]uh1jUhj0ubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hUDP_ZERO_CSUM6_TXh]hUDP_ZERO_CSUM6_TX}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhj}ubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhj}ubjV)}(hhh]h)}(h?Zero IPv6 UDP checksum on transmit. Used only if FD is not set.h]h?Zero IPv6 UDP checksum on transmit. Used only if FD is not set.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhj}ubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hUDP_ZERO_CSUM6_RXh]hUDP_ZERO_CSUM6_RX}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h>Zero IPv6 UDP checksum on receive. Used only if FD is not set.h]h>Zero IPv6 UDP checksum on receive. Used only if FD is not set.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hIP_SADDRh]hIP_SADDR}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1ubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h0IPv4 source address. Used only if FD is not set.h]h0IPv4 source address. Used only if FD is not set.}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjGubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hIP_DADDRh]hIP_DADDR}(hjjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjgubah}(h]h ]h"]h$]h&]uh1jUhjdubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj~ubah}(h]h ]h"]h$]h&]uh1jUhjdubjV)}(hhh]h)}(h5IPv4 destination address. Used only if FD is not set.h]h5IPv4 destination address. Used only if FD is not set.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjdubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h UDP_SPORTh]h UDP_SPORT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h,UDP source port. Used only if FD is not set.h]h,UDP source port. Used only if FD is not set.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h UDP_DPORTh]h UDP_DPORT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h1UDP destination port. Used only if FD is not set.h]h1UDP destination port. Used only if FD is not set.}(hj1hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj.ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h IP6_SADDRh]h IP6_SADDR}(hjQhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjNubah}(h]h ]h"]h$]h&]uh1jUhjKubjV)}(hhh]h)}(hjh]hN}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjeubah}(h]h ]h"]h$]h&]uh1jUhjKubjV)}(hhh]h)}(h0IPv6 source address. Used only if FD is not set.h]h0IPv6 source address. Used only if FD is not set.}(hj~hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj{ubah}(h]h ]h"]h$]h&]uh1jUhjKubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h IP6_DADDRh]h IP6_DADDR}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h5IPv6 destination address. Used only if FD is not set.h]h5IPv6 destination address. Used only if FD is not set.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hDEBUGh]hDEBUG}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Debug flags.h]h Debug flags.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubeh}(h]h ]h"]h$]h&]uh1jhj(ubeh}(h]h ]h"]h$]h&]colsKuh1j&hj#ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h(``L2TP_CMD_TUNNEL_DESTROY`` attributes:-h](j)}(h``L2TP_CMD_TUNNEL_DESTROY``h]hL2TP_CMD_TUNNEL_DESTROY}(hjI hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjE ubh attributes:-}(hjE hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjd ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjd ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK)uh1j+hjd ubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hRequiredh]hRequired}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hUseh]hUse}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jKhjd ubj)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hY}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h)Identifies the tunnel id to be destroyed.h]h)Identifies the tunnel id to be destroyed.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jhjd ubeh}(h]h ]h"]h$]h&]colsKuh1j&hja ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h'``L2TP_CMD_TUNNEL_MODIFY`` attributes:-h](j)}(h``L2TP_CMD_TUNNEL_MODIFY``h]hL2TP_CMD_TUNNEL_MODIFY}(hjC hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj? ubh attributes:-}(hj? hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj^ ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj^ ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK(uh1j+hj^ ubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hRequiredh]hRequired}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hUseh]hUse}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jKhj^ ubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hY}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h(Identifies the tunnel id to be modified.h]h(Identifies the tunnel id to be modified.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hDEBUGh]hDEBUG}(hj, hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj) ubah}(h]h ]h"]h$]h&]uh1jUhj& ubjV)}(hhh]h)}(hjh]hN}(hjC hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj@ ubah}(h]h ]h"]h$]h&]uh1jUhj& ubjV)}(hhh]h)}(h Debug flags.h]h Debug flags.}(hjY hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjV ubah}(h]h ]h"]h$]h&]uh1jUhj& ubeh}(h]h ]h"]h$]h&]uh1jPhj ubeh}(h]h ]h"]h$]h&]uh1jhj^ ubeh}(h]h ]h"]h$]h&]colsKuh1j&hj[ ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h$``L2TP_CMD_TUNNEL_GET`` attributes:-h](j)}(h``L2TP_CMD_TUNNEL_GET``h]hL2TP_CMD_TUNNEL_GET}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh attributes:-}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK'uh1j+hj ubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hRequiredh]hRequired}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hUseh]hUse}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jKhj ubj)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hj& hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj# ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hN}(hj= hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj: ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hAIdentifies the tunnel id to be queried. Ignored in DUMP requests.h]hAIdentifies the tunnel id to be queried. Ignored in DUMP requests.}(hjS hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjP ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]colsKuh1j&hj ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h(``L2TP_CMD_SESSION_CREATE`` attributes:-h](j)}(h``L2TP_CMD_SESSION_CREATE``h]hL2TP_CMD_SESSION_CREATE}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj ubh attributes:-}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK*uh1j+hj ubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hRequiredh]hRequired}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hUseh]hUse}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jKhj ubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hY}(hj7 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj4 ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hThe parent tunnel id.h]hThe parent tunnel id.}(hjM hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjJ ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(h SESSION_IDh]h SESSION_ID}(hjm hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjj ubah}(h]h ]h"]h$]h&]uh1jUhjg ubjV)}(hhh]h)}(hjh]hY}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhjg ubjV)}(hhh]h)}(hSets the session id.h]hSets the session id.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhjg ubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hPEER_SESSION_IDh]hPEER_SESSION_ID}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hY}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hSets the parent session id.h]hSets the parent session id.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hPW_TYPEh]hPW_TYPE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hSets the pseudowire type.h]hSets the pseudowire type.}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hDEBUGh]hDEBUG}(hjThhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjQubah}(h]h ]h"]h$]h&]uh1jUhjNubjV)}(hhh]h)}(hjh]hN}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhubah}(h]h ]h"]h$]h&]uh1jUhjNubjV)}(hhh]h)}(h Debug flags.h]h Debug flags.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj~ubah}(h]h ]h"]h$]h&]uh1jUhjNubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hRECV_SEQh]hRECV_SEQ}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Enable rx data sequence numbers.h]h Enable rx data sequence numbers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hSEND_SEQh]hSEND_SEQ}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Enable tx data sequence numbers.h]h Enable tx data sequence numbers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hLNS_MODEh]hLNS_MODE}(hj;hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj8ubah}(h]h ]h"]h$]h&]uh1jUhj5ubjV)}(hhh]h)}(hjh]hN}(hjRhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjOubah}(h]h ]h"]h$]h&]uh1jUhj5ubjV)}(hhh]h)}(h4Enable LNS mode (auto-enable data sequence numbers).h]h4Enable LNS mode (auto-enable data sequence numbers).}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjeubah}(h]h ]h"]h$]h&]uh1jUhj5ubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(h RECV_TIMEOUTh]h RECV_TIMEOUT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h1Timeout to wait when reordering received packets.h]h1Timeout to wait when reordering received packets.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(h L2SPEC_TYPEh]h L2SPEC_TYPE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h1Sets layer2-specific-sublayer type (L2TPv3 only).h]h1Sets layer2-specific-sublayer type (L2TPv3 only).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hCOOKIEh]hCOOKIE}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hj9hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj6ubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h#Sets optional cookie (L2TPv3 only).h]h#Sets optional cookie (L2TPv3 only).}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjLubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(h PEER_COOKIEh]h PEER_COOKIE}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjlubah}(h]h ]h"]h$]h&]uh1jUhjiubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjiubjV)}(hhh]h)}(h(Sets optional peer cookie (L2TPv3 only).h]h(Sets optional peer cookie (L2TPv3 only).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjiubeh}(h]h ]h"]h$]h&]uh1jPhj ubjQ)}(hhh](jV)}(hhh]h)}(hIFNAMEh]hIFNAME}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h"Sets interface name (L2TPv3 only).h]h"Sets interface name (L2TPv3 only).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubeh}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]colsKuh1j&hj ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(hX 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.h]hXFor 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h)``L2TP_CMD_SESSION_DESTROY`` attributes:-h](j)}(h``L2TP_CMD_SESSION_DESTROY``h]hL2TP_CMD_SESSION_DESTROY}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj$ubh attributes:-}(hj$hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjCubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjCubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK.uh1j+hjCubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjjubah}(h]h ]h"]h$]h&]uh1jUhjgubjV)}(hhh]h)}(hRequiredh]hRequired}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjgubjV)}(hhh]h)}(hUseh]hUse}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjgubeh}(h]h ]h"]h$]h&]uh1jPhjdubah}(h]h ]h"]h$]h&]uh1jKhjCubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h?Identifies the parent tunnel id of the session to be destroyed.h]h?Identifies the parent tunnel id of the session to be destroyed.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h SESSION_IDh]h SESSION_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hY}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj%ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h*Identifies the session id to be destroyed.h]h*Identifies the session id to be destroyed.}(hj>hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj;ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hIFNAMEh]hIFNAME}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj[ubah}(h]h ]h"]h$]h&]uh1jUhjXubjV)}(hhh]h)}(hjh]hN}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjrubah}(h]h ]h"]h$]h&]uh1jUhjXubjV)}(hhh]h)}(hIdentifies the session by interface name. If set, this overrides any CONN_ID and SESSION_ID attributes. Currently supported for L2TPv3 Ethernet sessions only.h]hIdentifies the session by interface name. If set, this overrides any CONN_ID and SESSION_ID attributes. Currently supported for L2TPv3 Ethernet sessions only.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjXubeh}(h]h ]h"]h$]h&]uh1jPhjubeh}(h]h ]h"]h$]h&]uh1jhjCubeh}(h]h ]h"]h$]h&]colsKuh1j&hj@ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h(``L2TP_CMD_SESSION_MODIFY`` attributes:-h](j)}(h``L2TP_CMD_SESSION_MODIFY``h]hL2TP_CMD_SESSION_MODIFY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh attributes:-}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK.uh1j+hjubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hRequiredh]hRequired}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hUseh]hUse}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj,ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubah}(h]h ]h"]h$]h&]uh1jKhjubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjUubah}(h]h ]h"]h$]h&]uh1jUhjRubjV)}(hhh]h)}(hjh]hY}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjlubah}(h]h ]h"]h$]h&]uh1jUhjRubjV)}(hhh]h)}(h>Identifies the parent tunnel id of the session to be modified.h]h>Identifies the parent tunnel id of the session to be modified.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjRubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(h SESSION_IDh]h SESSION_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hY}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h)Identifies the session id to be modified.h]h)Identifies the session id to be modified.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(hIFNAMEh]hIFNAME}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hIdentifies the session by interface name. If set, this overrides any CONN_ID and SESSION_ID attributes. Currently supported for L2TPv3 Ethernet sessions only.h]hIdentifies the session by interface name. If set, this overrides any CONN_ID and SESSION_ID attributes. Currently supported for L2TPv3 Ethernet sessions only.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(hDEBUGh]hDEBUG}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj<ubah}(h]h ]h"]h$]h&]uh1jUhj9ubjV)}(hhh]h)}(hjh]hN}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjSubah}(h]h ]h"]h$]h&]uh1jUhj9ubjV)}(hhh]h)}(h Debug flags.h]h Debug flags.}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjiubah}(h]h ]h"]h$]h&]uh1jUhj9ubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(hRECV_SEQh]hRECV_SEQ}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Enable rx data sequence numbers.h]h Enable rx data sequence numbers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(hSEND_SEQh]hSEND_SEQ}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h Enable tx data sequence numbers.h]h Enable tx data sequence numbers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(hLNS_MODEh]hLNS_MODE}(hj&hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj#ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hjh]hN}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj:ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h4Enable LNS mode (auto-enable data sequence numbers).h]h4Enable LNS mode (auto-enable data sequence numbers).}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjPubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhjOubjQ)}(hhh](jV)}(hhh]h)}(h RECV_TIMEOUTh]h RECV_TIMEOUT}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjpubah}(h]h ]h"]h$]h&]uh1jUhjmubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjmubjV)}(hhh]h)}(h1Timeout to wait when reordering received packets.h]h1Timeout to wait when reordering received packets.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjmubeh}(h]h ]h"]h$]h&]uh1jPhjOubeh}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]colsKuh1j&hjubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(h%``L2TP_CMD_SESSION_GET`` attributes:-h](j)}(h``L2TP_CMD_SESSION_GET``h]hL2TP_CMD_SESSION_GET}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh attributes:-}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hjubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK)uh1j+hjubjL)}(hhh]jQ)}(hhh](jV)}(hhh]h)}(h Attributeh]h Attribute}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hRequiredh]hRequired}(hj-hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj*ubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hUseh]hUse}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjAubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhj ubah}(h]h ]h"]h$]h&]uh1jKhjubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hCONN_IDh]hCONN_ID}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjjubah}(h]h ]h"]h$]h&]uh1jUhjgubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjgubjV)}(hhh]h)}(hBIdentifies the tunnel id to be queried. Ignored for DUMP requests.h]hBIdentifies the tunnel id to be queried. Ignored for DUMP requests.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjgubeh}(h]h ]h"]h$]h&]uh1jPhjdubjQ)}(hhh](jV)}(hhh]h)}(h SESSION_IDh]h SESSION_ID}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hCIdentifies the session id to be queried. Ignored for DUMP requests.h]hCIdentifies the session id to be queried. Ignored for DUMP requests.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjdubjQ)}(hhh](jV)}(hhh]h)}(hIFNAMEh]hIFNAME}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hjh]hN}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(hIdentifies 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.h]hIdentifies 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.}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj1ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjdubeh}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]colsKuh1j&hjubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(hrApplication developers should refer to `include/uapi/linux/l2tp.h`_ for netlink command and attribute definitions.h](h'Application developers should refer to }(hjahhhNhNubjy)}(h`include/uapi/linux/l2tp.h`_h]hinclude/uapi/linux/l2tp.h}(hjihhhNhNubah}(h]h ]h"]h$]h&]nameinclude/uapi/linux/l2tp.hjjuh1jxhjajKubh/ for netlink command and attribute definitions.}(hjahhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h$Sample userspace code using libmnl_:h](hSample userspace code using }(hjhhhNhNubjy)}(hlibmnl_h]hlibmnl}(hjhhhNhNubah}(h]h ]h"]h$]h&]namelibmnlj)https://www.netfilter.org/projects/libmnluh1jxhjjKubh:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjW)}(hXN - 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); h]h bullet_list)}(hhh](jb)}(hOpen 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); h](h)}(hOpen L2TP netlink socket::h]hOpen L2TP netlink socket:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj7)}(hstruct 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);h]hstruct 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);}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjubeh}(h]h ]h"]h$]h&]uh1jahjubjb)}(hXCreate 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); h](h)}(hCreate a tunnel::h]hCreate a tunnel:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj7)}(hXqstruct 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);h]hXqstruct 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);}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjubeh}(h]h ]h"]h$]h&]uh1jahjubjb)}(hXACreate 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 */ h](h)}(hCreate a session::h]hCreate a session:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM$hjubj7)}(hXstruct 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 */h]hXstruct 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 */}hj sbah}(h]h ]h"]h$]h&]hhuh1j6hhhM&hjubeh}(h]h ]h"]h$]h&]uh1jahjubjb)}(hXDelete 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); h](h)}(hDelete a session::h]hDelete a session:}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM<hj!ubj7)}(hXstruct 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);h]hXstruct 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);}hj3sbah}(h]h ]h"]h$]h&]hhuh1j6hhhM>hj!ubeh}(h]h ]h"]h$]h&]uh1jahjubjb)}(hXDelete 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); h](h)}(h2Delete a tunnel and all of its sessions (if any)::h]h1Delete a tunnel and all of its sessions (if any):}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMNhjGubj7)}(hXstruct 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);h]hXstruct 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);}hjYsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMPhjGubeh}(h]h ]h"]h$]h&]uh1jahjubeh}(h]h ]h"]h$]h&]bullet-uh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1jVhhhMhjhhubeh}(h] netlink-apiah ]h"] netlink apiah$]h&]uh1hhjhhhhhK]ubh)}(hhh](h)}(hPPPoL2TP Session Socket APIh]hPPPoL2TP Session Socket API}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM`ubh)}(hZFor PPP session types, a PPPoL2TP socket must be opened and connected to the L2TP session.h]hZFor PPP session types, a PPPoL2TP socket must be opened and connected to the L2TP session.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMbhjhhubh)}(hX 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.h](hXWhen 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 }(hjhhhNhNubjy)}(h`include/linux/if_pppol2tp.h`_h]hinclude/linux/if_pppol2tp.h}(hjhhhNhNubah}(h]h ]h"]h$]h&]nameinclude/linux/if_pppol2tp.hj$../../../include/linux/if_pppol2tp.huh1jxhjjKubh. 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.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMehjhhubh)}(hUserspace may control behavior of the tunnel or session using setsockopt and ioctl on the PPPoX socket. The following socket options are supported:-h]hUserspace may control behavior of the tunnel or session using setsockopt and ioctl on the PPPoX socket. The following socket options are supported:-}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMnhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK uh1j+hjubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK;uh1j+hjubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hDEBUGh]hDEBUG}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMshjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]h)}(h/bitmask of debug message categories. See below.h]h/bitmask of debug message categories. See below.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMshj ubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hSENDSEQh]hSENDSEQ}(hj-hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMthj*ubah}(h]h ]h"]h$]h&]uh1jUhj'ubjV)}(hhh]j)}(hhh](jb)}(h-0 => don't send packets with sequence numbersh]h)}(hjIh]h/0 => don’t send packets with sequence numbers}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMthjGubah}(h]h ]h"]h$]h&]uh1jahjDubjb)}(h'1 => send packets with sequence numbersh]h)}(hj`h]h'1 => send packets with sequence numbers}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMuhj^ubah}(h]h ]h"]h$]h&]uh1jahjDubeh}(h]h ]h"]h$]h&]jsjtuh1jhhhMthjAubah}(h]h ]h"]h$]h&]uh1jUhj'ubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hRECVSEQh]hRECVSEQ}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMvhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]j)}(hhh](jb)}(h10 => receive packet sequence numbers are optionalh]h)}(hjh]h10 => receive packet sequence numbers are optional}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMvhjubah}(h]h ]h"]h$]h&]uh1jahjubjb)}(h21 => drop receive packets without sequence numbersh]h)}(hjh]h21 => drop receive packets without sequence numbers}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMwhjubah}(h]h ]h"]h$]h&]uh1jahjubeh}(h]h ]h"]h$]h&]jsjtuh1jhhhMvhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(hLNSMODEh]hLNSMODE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMxhjubah}(h]h ]h"]h$]h&]uh1jUhjubjV)}(hhh]j)}(hhh](jb)}(h0 => act as LAC.h]h)}(hj h]h0 => act as LAC.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMxhjubah}(h]h ]h"]h$]h&]uh1jahjubjb)}(h1 => act as LNS.h]h)}(hj h]h1 => act as LNS.}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMyhjubah}(h]h ]h"]h$]h&]uh1jahjubeh}(h]h ]h"]h$]h&]jsjtuh1jhhhMxhjubah}(h]h ]h"]h$]h&]uh1jUhjubeh}(h]h ]h"]h$]h&]uh1jPhjubjQ)}(hhh](jV)}(hhh]h)}(h REORDERTOh]h REORDERTO}(hjMhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMzhjJubah}(h]h ]h"]h$]h&]uh1jUhjGubjV)}(hhh]h)}(h;reorder timeout (in millisecs). If 0, don't try to reorder.h]h=reorder timeout (in millisecs). If 0, don’t try to reorder.}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMzhjaubah}(h]h ]h"]h$]h&]uh1jUhjGubeh}(h]h ]h"]h$]h&]uh1jPhjubeh}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]colsKuh1j&hjubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubh)}(hIn 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.h]hIn 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM}hjhhubh)}(hSample userspace code:h]hSample userspace code:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjW)}(hX- 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; h]j)}(hhh]jb)}(hXiCreate 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; h](h)}(h"Create session PPPoX data socket::h]h!Create session PPPoX data socket:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj7)}(hX/* 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;h]hX/* 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;}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjubeh}(h]h ]h"]h$]h&]uh1jahjubah}(h]h ]h"]h$]h&]jsjtuh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1jVhhhMhjhhubh)}(hEL2TP control packets will still be available for read on `tunnel_fd`.h](h9L2TP control packets will still be available for read on }(hjhhhNhNubhtitle_reference)}(h `tunnel_fd`h]h tunnel_fd}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjW)}(hXB- 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; h]j)}(hhh]jb)}(hXCreate 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; h](h)}(hCreate PPP channel::h]hCreate PPP channel:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj7)}(hX/* 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;h]hX/* 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;}hj!sbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjubeh}(h]h ]h"]h$]h&]uh1jahj ubah}(h]h ]h"]h$]h&]jsjtuh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1jVhhhMhjhhubh)}(h;LCP PPP frames will be available for read on `ppp_chan_fd`.h](h-LCP PPP frames will be available for read on }(hjAhhhNhNubj)}(h `ppp_chan_fd`h]h ppp_chan_fd}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjAubh.}(hjAhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjW)}(hX]- 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; h]j)}(hhh]jb)}(hX3Create 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; h](h)}(hCreate PPP interface::h]hCreate PPP interface:}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhubj7)}(hX/* 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;h]hX/* 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;}hjzsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjhubeh}(h]h ]h"]h$]h&]uh1jahjeubah}(h]h ]h"]h$]h&]jsjtuh1jhhhMhjaubah}(h]h ]h"]h$]h&]uh1jVhhhMhjhhubh)}(hAIPCP/IPv6CP PPP frames will be available for read on `ppp_if_fd`.h](h5IPCP/IPv6CP PPP frames will be available for read on }(hjhhhNhNubj)}(h `ppp_if_fd`h]h ppp_if_fd}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hThe ppp 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.h](hThe ppp 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 }(hjhhhNhNubj)}(h`ip`h]hip}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh command.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubjW)}(hX- 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; h]j)}(hhh]jb)}(hXBridging 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; h](h)}(hBridging 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::h]hBridging 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:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubj7)}(hX/* 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;h]hX/* 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;}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMhjubeh}(h]h ]h"]h$]h&]uh1jahjubah}(h]h ]h"]h$]h&]jsjtuh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1jVhhhMhjhhubh)}(hIt 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.h]hIt 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hiThe PPP channel does not need to be kept open. Only the session PPPoX data sockets need to be kept open.h]hiThe PPP channel does not need to be kept open. Only the session PPPoX data sockets need to be kept open.}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hMore 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.h]hMore 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.}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h5See more details for the PPP side in ppp_generic.rst.h]h5See more details for the PPP side in ppp_generic.rst.}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]pppol2tp-session-socket-apiah ]h"]pppol2tp session socket apiah$]h&]uh1hhjhhhhhM`ubh)}(hhh](h)}(hOld L2TPv2-only APIh]hOld L2TPv2-only API}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjShhhhhMubh)}(hXWhen 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:h]hXWhen 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:}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjShhubjW)}(hX- 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. h]j)}(hhh](jb)}(hXTunnels 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. h]h)}(hXTunnels 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.h]hXTunnels 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.}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM%hjyubah}(h]h ]h"]h$]h&]uh1jahjvubjb)}(hSession 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. h]h)}(hSession 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.h]hSession 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM+hjubah}(h]h ]h"]h$]h&]uh1jahjvubeh}(h]h ]h"]h$]h&]jsjtuh1jhhhM%hjrubah}(h]h ]h"]h$]h&]uh1jVhhhM%hjShhubh)}(hThis 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.h]hThis 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM0hjShhubeh}(h]old-l2tpv2-only-apiah ]h"]old l2tpv2-only apiah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hUnmanaged L2TPv3 tunnelsh]hUnmanaged L2TPv3 tunnels}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhM5ubh)}(hXlThe 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.h](hXThe 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 }(hjhhhNhNubj)}(h``L2TP_CMD_TUNNEL_CREATE``h]hL2TP_CMD_TUNNEL_CREATE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh netlink request. The }(hjhhhNhNubj)}(h``ip``h]hip}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh utility of }(hjhhhNhNubj)}(h ``iproute2``h]hiproute2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh5 has commands for managing static L2TPv3 tunnels; do }(hjhhhNhNubj)}(h``ip l2tp help``h]h ip l2tp help}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh for more information.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM7hjhhubeh}(h]unmanaged-l2tpv3-tunnelsah ]h"]unmanaged l2tpv3 tunnelsah$]h&]uh1hhjhhhhhM5ubh)}(hhh](h)}(h Debuggingh]h Debugging}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj:hhhhhMCubh)}(hYThe L2TP subsystem offers a range of debugging interfaces through the debugfs filesystem.h]hYThe L2TP subsystem offers a range of debugging interfaces through the debugfs filesystem.}(hjKhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMEhj:hhubh)}(hJTo access these interfaces, the debugfs filesystem must first be mounted::h]hITo access these interfaces, the debugfs filesystem must first be mounted:}(hjYhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMHhj:hhubj7)}(h!# mount -t debugfs debugfs /debugh]h!# mount -t debugfs debugfs /debug}hjgsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMJhj:hhubh)}(hFiles under the l2tp directory can then be accessed, providing a summary of the current population of tunnel and session contexts existing in the kernel::h]hFiles under the l2tp directory can then be accessed, providing a summary of the current population of tunnel and session contexts existing in the kernel:}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMLhj:hhubj7)}(h# cat /debug/l2tp/tunnelsh]h# cat /debug/l2tp/tunnels}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhMPhj:hhubh)}(hXThe 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.h]hXThe 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMRhj:hhubh)}(hIn addition the L2TP subsystem implements tracepoints using the standard kernel event tracing API. The available L2TP events can be reviewed as follows::h]hIn addition the L2TP subsystem implements tracepoints using the standard kernel event tracing API. The available L2TP events can be reviewed as follows:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMWhj:hhubj7)}(h!# find /debug/tracing/events/l2tph]h!# find /debug/tracing/events/l2tp}hjsbah}(h]h ]h"]h$]h&]hhuh1j6hhhM[hj:hhubh)}(hFinally, /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.h]hFinally, /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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM]hj:hhubeh}(h] debuggingah ]h"] debuggingah$]h&]uh1hhjhhhhhMCubeh}(h] l2tp-apisah ]h"] l2tp apisah$]h&]uh1hhhhhhhhK5ubh)}(hhh](h)}(hInternal Implementationh]hInternal Implementation}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMbubh)}(h6This section is for kernel developers and maintainers.h]h6This section is for kernel developers and maintainers.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMdhjhhubh)}(hhh](h)}(hSocketsh]hSockets}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMgubh)}(hXgUDP 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.h]hXgUDP 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.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMihjhhubh)}(hSL2TPIP sockets are implemented in `net/l2tp/l2tp_ip.c`_ and `net/l2tp/l2tp_ip6.c`_.h](h"L2TPIP sockets are implemented in }(hjhhhNhNubjy)}(h`net/l2tp/l2tp_ip.c`_h]hnet/l2tp/l2tp_ip.c}(hjhhhNhNubah}(h]h ]h"]h$]h&]namenet/l2tp/l2tp_ip.cj../../../net/l2tp/l2tp_ip.cuh1jxhjjKubh and }(hjhhhNhNubjy)}(h`net/l2tp/l2tp_ip6.c`_h]hnet/l2tp/l2tp_ip6.c}(hj4hhhNhNubah}(h]h ]h"]h$]h&]namenet/l2tp/l2tp_ip6.cj../../../net/l2tp/l2tp_ip6.cuh1jxhjjKubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMphjhhubeh}(h]socketsah ]h"]socketsah$]h&]uh1hhjhhhhhMgubh)}(hhh](h)}(hTunnelsh]hTunnels}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjWhhhhhMtubh)}(hXhThe 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.h]hXjThe 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.}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMvhjWhhubh)}(hTunnels 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.h]hTunnels 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.}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM}hjWhhubh)}(hqTunnels are kept in a per-net list, indexed by tunnel id. The tunnel id namespace is shared by L2TPv2 and L2TPv3.h]hqTunnels are kept in a per-net list, indexed by tunnel id. The tunnel id namespace is shared by L2TPv2 and L2TPv3.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjWhhubh)}(hXHandling 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.h]hXHandling 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjWhhubeh}(h]tunnelsah ]h"]tunnelsah$]h&]uh1hhjhhhhhMtubh)}(hhh](h)}(hSessionsh]hSessions}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hXThe 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.h]hXThe 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hhSome L2TP session types also have a socket (PPP pseudowires) while others do not (Ethernet pseudowires).h]hhSome L2TP session types also have a socket (PPP pseudowires) while others do not (Ethernet pseudowires).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hLike 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.h]hLike 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h{Sessions hold a ref on their parent tunnel to ensure that the tunnel stays extant while one or more sessions references it.h]h{Sessions hold a ref on their parent tunnel to ensure that the tunnel stays extant while one or more sessions references it.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hX3Sessions 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.h]hX3Sessions 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hXAlthough 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.h]hXAlthough 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]sessionsah ]h"]sessionsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hPPPh]hPPP}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(he`net/l2tp/l2tp_ppp.c`_ implements the PPPoL2TP socket family. Each PPP session has a PPPoL2TP socket.h](jy)}(h`net/l2tp/l2tp_ppp.c`_h]hnet/l2tp/l2tp_ppp.c}(hj*hhhNhNubah}(h]h ]h"]h$]h&]namenet/l2tp/l2tp_ppp.cj../../../net/l2tp/l2tp_ppp.cuh1jxhj&jKubhO implements the PPPoL2TP socket family. Each PPP session has a PPPoL2TP socket.}(hj&hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h?The PPPoL2TP socket's sk_user_data references the l2tp_session.h]hAThe PPPoL2TP socket’s sk_user_data references the l2tp_session.}(hjEhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hX2Userspace 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.h](hUserspace 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 }(hjShhhNhNubj)}(h``pppN``h]hpppN}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjSubhF netdev through the PPP channel interface of the kernel PPP subsystem.}(hjShhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hXThe 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.h]hXThe 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.}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]pppah ]h"]pppah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hEtherneth]hEthernet}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hd`net/l2tp/l2tp_eth.c`_ implements L2TPv3 Ethernet pseudowires. It manages a netdev for each session.h](jy)}(h`net/l2tp/l2tp_eth.c`_h]hnet/l2tp/l2tp_eth.c}(hjhhhNhNubah}(h]h ]h"]h$]h&]namenet/l2tp/l2tp_eth.cj../../../net/l2tp/l2tp_eth.cuh1jxhjjKubhN implements L2TPv3 Ethernet pseudowires. It manages a netdev for each session.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(hL2TP 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.h]hL2TP 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.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubeh}(h]ethernetah ]h"]ethernetah$]h&]uh1hhjhhhhhMubeh}(h]internal-implementationah ]h"]internal implementationah$]h&]uh1hhhhhhhhMbubh)}(hhh](h)}(h Miscellaneoush]h Miscellaneous}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hRFCsh]hRFCs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhMubh)}(hQThe kernel code implements the datapath features specified in the following RFCs:h]hQThe kernel code implements the datapath features specified in the following RFCs:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthKuh1j+hj ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK#uh1j+hj ubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hRFC2661h]hRFC2661}(hj4 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj1 ubah}(h]h ]h"]h$]h&]uh1jUhj. ubjV)}(hhh]h)}(hL2TPv2h]hL2TPv2}(hjK hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjH ubah}(h]h ]h"]h$]h&]uh1jUhj. ubjV)}(hhh]h)}(h#https://tools.ietf.org/html/rfc2661h]jy)}(hjd h]h#https://tools.ietf.org/html/rfc2661}(hjf hhhNhNubah}(h]h ]h"]h$]h&]refurijd uh1jxhjb ubah}(h]h ]h"]h$]h&]uh1hhhhMhj_ ubah}(h]h ]h"]h$]h&]uh1jUhj. ubeh}(h]h ]h"]h$]h&]uh1jPhj+ ubjQ)}(hhh](jV)}(hhh]h)}(hRFC3931h]hRFC3931}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hL2TPv3h]hL2TPv3}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h#https://tools.ietf.org/html/rfc3931h]jy)}(hj h]h#https://tools.ietf.org/html/rfc3931}(hj hhhNhNubah}(h]h ]h"]h$]h&]refurij uh1jxhj ubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj+ ubjQ)}(hhh](jV)}(hhh]h)}(hRFC4719h]hRFC4719}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(hL2TPv3 Etherneth]hL2TPv3 Ethernet}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jUhj ubjV)}(hhh]h)}(h#https://tools.ietf.org/html/rfc4719h]jy)}(hj!h]h#https://tools.ietf.org/html/rfc4719}(hj!hhhNhNubah}(h]h ]h"]h$]h&]refurij!uh1jxhj!ubah}(h]h ]h"]h$]h&]uh1hhhhMhj!ubah}(h]h ]h"]h$]h&]uh1jUhj ubeh}(h]h ]h"]h$]h&]uh1jPhj+ ubeh}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]colsKuh1j&hj ubah}(h]h ]h"]h$]h&]uh1j!hjhhhhhNubeh}(h]rfcsah ]h"]rfcsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hImplementationsh]hImplementations}(hjT!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjQ!hhhhhMubh)}(hCA number of open source applications use the L2TP kernel subsystem:h]hCA number of open source applications use the L2TP kernel subsystem:}(hjb!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjQ!hhubj")}(hhh]j')}(hhh](j,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK uh1j+hjs!ubj,)}(hhh]h}(h]h ]h"]h$]h&]colwidthK.uh1j+hjs!ubj)}(hhh](jQ)}(hhh](jV)}(hhh]h)}(hiproute2h]hiproute2}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj!ubah}(h]h ]h"]h$]h&]uh1jUhj!ubjV)}(hhh]h)}(h&https://github.com/shemminger/iproute2h]jy)}(hj!h]h&https://github.com/shemminger/iproute2}(hj!hhhNhNubah}(h]h ]h"]h$]h&]refurij!uh1jxhj!ubah}(h]h ]h"]h$]h&]uh1hhhhMhj!ubah}(h]h ]h"]h$]h&]uh1jUhj!ubeh}(h]h ]h"]h$]h&]uh1jPhj!ubjQ)}(hhh](jV)}(hhh]h)}(hgo-l2tph]hgo-l2tp}(hj!hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj!ubah}(h]h ]h"]h$]h&]uh1jUhj!ubjV)}(hhh]h)}(h"https://github.com/katalix/go-l2tph]jy)}(hj!h]h"https://github.com/katalix/go-l2tp}(hj!hhhNhNubah}(h]h ]h"]h$]h&]refurij!uh1jxhj!ubah}(h]h ]h"]h$]h&]uh1hhhhMhj!ubah}(h]h ]h"]h$]h&]uh1jUhj!ubeh}(h]h ]h"]h$]h&]uh1jPhj!ubjQ)}(hhh](jV)}(hhh]h)}(h tunneldiggerh]h tunneldigger}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj"ubah}(h]h ]h"]h$]h&]uh1jUhj"ubjV)}(hhh]h)}(h-https://github.com/wlanslovenija/tunneldiggerh]jy)}(hj."h]h-https://github.com/wlanslovenija/tunneldigger}(hj0"hhhNhNubah}(h]h ]h"]h$]h&]refurij."uh1jxhj,"ubah}(h]h ]h"]h$]h&]uh1hhhhMhj)"ubah}(h]h ]h"]h$]h&]uh1jUhj"ubeh}(h]h ]h"]h$]h&]uh1jPhj!ubjQ)}(hhh](jV)}(hhh]h)}(hxl2tpdh]hxl2tpd}(hjV"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjS"ubah}(h]h ]h"]h$]h&]uh1jUhjP"ubjV)}(hhh]h)}(h#https://github.com/xelerance/xl2tpdh]jy)}(hjo"h]h#https://github.com/xelerance/xl2tpd}(hjq"hhhNhNubah}(h]h ]h"]h$]h&]refurijo"uh1jxhjm"ubah}(h]h ]h"]h$]h&]uh1hhhhMhjj"ubah}(h]h ]h"]h$]h&]uh1jUhjP"ubeh}(h]h ]h"]h$]h&]uh1jPhj!ubeh}(h]h ]h"]h$]h&]uh1jhjs!ubeh}(h]h ]h"]h$]h&]colsKuh1j&hjp!ubah}(h]h ]h"]h$]h&]uh1j!hjQ!hhhhhNubeh}(h]implementationsah ]h"]implementationsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(h Limitationsh]h Limitations}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj"hhhhhMubh)}(h7The current implementation has a number of limitations:h]h7The current implementation has a number of limitations:}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj"hhubjW)}(hX 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. h]j])}(hhh](jb)}(h~Interfacing with openvswitch is not yet implemented. It may be useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels. h]h)}(h}Interfacing with openvswitch is not yet implemented. It may be useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels.h]h}Interfacing with openvswitch is not yet implemented. It may be useful to map OVS Ethernet and VLAN ports into L2TPv3 tunnels.}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhj"ubah}(h]h ]h"]h$]h&]uh1jahj"ubjb)}(hXqVLAN 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. h]h)}(hXpVLAN 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.h](h*VLAN pseudowires are implemented using an }(hj"hhhNhNubj)}(h ``l2tpethN``h]hl2tpethN}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj"ubh 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 }(hj"hhhNhNubj)}(h ``l2tpethN``h]hl2tpethN}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj"ubh and }(hj"hhhNhNubj)}(h ``l2tpethN``h]hl2tpethN}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj"ubh0:M pair per VLAN session. The netlink attribute }(hj"hhhNhNubj)}(h``L2TP_ATTR_VLAN_ID``h]hL2TP_ATTR_VLAN_ID}(hj,#hhhNhNubah}(h]h ]h"]h$]h&]uh1jhj"ubh2 was added for this, but it was never implemented.}(hj"hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj"ubah}(h]h ]h"]h$]h&]uh1jahj"ubeh}(h]h ]h"]h$]h&]jjjhjjuh1j\hj"ubah}(h]h ]h"]h$]h&]uh1jVhhhMhj"hhubeh}(h] limitationsah ]h"] limitationsah$]h&]uh1hhjhhhhhMubh)}(hhh](h)}(hTestingh]hTesting}(hja#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj^#hhhhhMubh)}(h}Unmanaged L2TPv3 Ethernet features are tested by the kernel's built-in selftests. See `tools/testing/selftests/net/l2tp.sh`_.h](hXUnmanaged L2TPv3 Ethernet features are tested by the kernel’s built-in selftests. See }(hjo#hhhNhNubjy)}(h&`tools/testing/selftests/net/l2tp.sh`_h]h#tools/testing/selftests/net/l2tp.sh}(hjw#hhhNhNubah}(h]h ]h"]h$]h&]name#tools/testing/selftests/net/l2tp.shj,../../../tools/testing/selftests/net/l2tp.shuh1jxhjo#jKubh.}(hjo#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj^#hhubh)}(hAnother 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.h](hAnother test suite, }(hj#hhhNhNubjy)}(h l2tp-ktest_h]h l2tp-ktest}(hj#hhhNhNubah}(h]h ]h"]h$]h&]name l2tp-ktestj%https://github.com/katalix/l2tp-ktestuh1jxhj#jKubh, 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.+}(hj#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj^#hhubh)}(hLinksh]hLinks}hj#sbah}(h]h ]h"]h$]h&]hhuh1hhj^#hhhhhMubhtarget)}(h).. _Generic Netlink: generic_netlink.htmlh]h}(h]generic-netlinkah ]h"]generic netlinkah$]h&]jjuh1j#hM hj^#hhhh referencedKubj#)}(h5.. _libmnl: https://www.netfilter.org/projects/libmnlh]h}(h]libmnlah ]h"]libmnlah$]h&]jjuh1j#hM hj^#hhhhj#Kubj#)}(hA.. _include/uapi/linux/l2tp.h: ../../../include/uapi/linux/l2tp.hh]h}(h]include-uapi-linux-l2tp-hah ]h"]include/uapi/linux/l2tp.hah$]h&]jjuh1j#hM hj^#hhhhj#Kubj#)}(hE.. _include/linux/if_pppol2tp.h: ../../../include/linux/if_pppol2tp.hh]h}(h]include-linux-if-pppol2tp-hah ]h"]include/linux/if_pppol2tp.hah$]h&]jjuh1j#hM hj^#hhhhj#Kubj#)}(h3.. _net/l2tp/l2tp_ip.c: ../../../net/l2tp/l2tp_ip.ch]h}(h]net-l2tp-l2tp-ip-cah ]h"]net/l2tp/l2tp_ip.cah$]h&]jj/uh1j#hM hj^#hhhhj#Kubj#)}(h5.. _net/l2tp/l2tp_ip6.c: ../../../net/l2tp/l2tp_ip6.ch]h}(h]net-l2tp-l2tp-ip6-cah ]h"]net/l2tp/l2tp_ip6.cah$]h&]jjDuh1j#hMhj^#hhhhj#Kubj#)}(h5.. _net/l2tp/l2tp_ppp.c: ../../../net/l2tp/l2tp_ppp.ch]h}(h]net-l2tp-l2tp-ppp-cah ]h"]net/l2tp/l2tp_ppp.cah$]h&]jj:uh1j#hMhj^#hhhhj#Kubj#)}(h5.. _net/l2tp/l2tp_eth.c: ../../../net/l2tp/l2tp_eth.ch]h}(h]net-l2tp-l2tp-eth-cah ]h"]net/l2tp/l2tp_eth.cah$]h&]jjuh1j#hMhj^#hhhhj#Kubj#)}(hU.. _tools/testing/selftests/net/l2tp.sh: ../../../tools/testing/selftests/net/l2tp.shh]h}(h]#tools-testing-selftests-net-l2tp-shah ]h"]#tools/testing/selftests/net/l2tp.shah$]h&]jj#uh1j#hMhj^#hhhhj#Kubj#)}(h5.. _l2tp-ktest: https://github.com/katalix/l2tp-ktesth]h}(h] l2tp-ktestah ]h"] l2tp-ktestah$]h&]jj#uh1j#hMhj^#hhhhj#Kubeh}(h]testingah ]h"]testingah$]h&]uh1hhjhhhhhMubeh}(h] miscellaneousah ]h"] miscellaneousah$]h&]uh1hhhhhhhhMubeh}(h]l2tpah ]h"]l2tpah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksjUfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjx$error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}(include/uapi/linux/l2tp.h](jzjjiegeneric netlink]jalibmnl]jainclude/linux/if_pppol2tp.h]janet/l2tp/l2tp_ip.c]janet/l2tp/l2tp_ip6.c]j4anet/l2tp/l2tp_ppp.c]j*anet/l2tp/l2tp_eth.c]ja#tools/testing/selftests/net/l2tp.sh]jw#a l2tp-ktest]j#aurefids}nameids}(jS$jP$jjjjjjjj}jPjMjjj7j4jjjjjTjQjjjjjjjjjK$jH$jN!jK!j"j"j[#jX#jC$j@$j#j#j#j#j#j#j#j#j#j#j $j$j$j$j#$j $j/$j,$j;$j8$u nametypes}(jS$jjjjjPjj7jjjTjjjjjK$jN!j"j[#jC$j#j#j#j#j#j $j$j#$j/$j;$uh}(jP$hjhjjjjj}jjMjjjSj4jjj:jjjQjjjWjjjjjjjH$jjK!jj"jQ!jX#j"j@$j^#j#j#j#j#j#j#j#j#j#j#j$j$j$j$j $j$j,$j&$j8$j2$u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.