Skip to content
Thomas Mangin edited this page Jun 15, 2026 · 7 revisions

Pre-Alpha. This page describes behavior that may change.

Ze includes a native L2TPv2 (RFC 2661) LNS/LAC implementation for use as a BNG (Broadband Network Gateway) component. It terminates L2TP tunnels over UDP, runs PPP negotiation (LCP, authentication, IPCP/IPv6CP), assigns peer IPs, and hands the kernel data plane to the l2tp_ppp module via netlink. Subscriber routes are tracked for redistribution into BGP.

The reliable delivery engine supports control message priority: Hello keepalives and StopCCN teardowns are sent ahead of bulk ICRQ/ICRP session-setup traffic, preventing tunnel liveness issues under high session churn.

Configuration

l2tp {
    enabled true;
    shared-secret <secret>;       // CHAP-MD5 tunnel auth (RFC 2661 S4.2)
    auth-method chap-md5;          // PPP Auth-Protocol first advertised
    allow-no-auth false;           // explicit opt-in required for no-auth
    hello-interval 60;             // seconds of peer silence before HELLO
    max-tunnels 1024;              // 0 = unbounded (16-bit ceiling)
    max-sessions 1024;             // per-tunnel, 0 = unbounded
}

environment {
    l2tp {
        server main {
            ip 0.0.0.0;
            port 1701;
        }
    }
}

Presence of l2tp {} with any content implies the subsystem is enabled. Set enabled false to disable explicitly.

PPP negotiation

When a session is established (ICRQ/ICRP/ICCN exchange), the subsystem creates kernel L2TP tunnel and session resources via Generic Netlink, opens a PPPoL2TP socket, and attaches a /dev/ppp channel and unit. The kernel creates a pppN interface.

PPP negotiation proceeds through these phases:

  1. LCP (RFC 1661): MRU, authentication method, magic number, echo keepalive. LCP proxy (RFC 2661 S18) is supported.
  2. Authentication: PAP (RFC 1334), CHAP-MD5 (RFC 1994), or MS-CHAPv2 (RFC 2759). Dispatched to the registered auth handler.
  3. IPCP (RFC 1332): IPv4 address assignment + DNS options (RFC 1877).
  4. IPv6CP (RFC 5072): interface identifier negotiation. Runs in parallel with IPCP when both NCPs are enabled.

LCP Auth-Protocol Nak/Reject fallback is supported. Periodic re-auth is configurable via the reauth-interval YANG leaf under l2tp > auth (the former ze.l2tp.auth.reauth-interval env var has been promoted to YANG config). NCP-related env vars (ze.l2tp.ncp.*) have also been promoted to YANG config leaves.

Authentication

Ze separates PPP auth wire format from credential validation. Two auth handlers ship:

l2tp-auth-local

Built-in static user list:

l2tp {
    auth {
        local {
            user alice {
                password hunter2;
            }
        }
    }
}

l2tp-auth-radius

RADIUS client plugin providing:

  • Access-Request: PAP/CHAP-MD5/MS-CHAPv2 credential forwarding with failover and retry.
  • Accounting: Start, Stop, and Interim-Update records (RFC 2866).
  • CoA/DM: Change of Authorization and Disconnect-Message listener (RFC 5176) for RADIUS-initiated session changes and disconnects.
l2tp {
    auth {
        radius {
            nas-identifier ze-lns;
            timeout 3;
            retries 3;
            acct-interval 300;
            server 10.0.0.10 {
                port 1812;
                shared-key radiussecret;
            }
        }
    }
}

IP address pool

Bitmap-backed IPv4 address pools:

l2tp {
    pool {
        ipv4 {
            gateway 10.100.0.1;
            start 10.100.0.2;
            end 10.100.255.254;
            dns-primary 8.8.8.8;
            dns-secondary 8.8.4.4;
        }
    }
}

Session-down events release allocated addresses back to the pool.

Traffic shaping

The l2tp-shaper plugin applies TC rules on pppN interfaces. RADIUS CoA can update the rate dynamically after the session is up.

l2tp {
    shaper {
        qdisc-type tbf;            // tbf or htb
        default-rate 10mbit;       // download rate for new sessions
        upload-rate 2mbit;         // upload rate (defaults to default-rate)
    }
}

CQM (Call Quality Metrics)

Firebrick-style CQM monitoring for L2TP sessions:

  • Per-session event ring: circular buffer of state transitions (tunnel-up, session-up, session-down, echo-rtt, disconnect-requested). Disconnect events include the actor, reason text, and optional cause code.
  • Per-login CQM sample ring: 100-second aggregated buckets with echo RTT statistics (min, avg, max), echo count and loss ratio, and session state. 24h retention (864 buckets) by default.

LCP echo probes measure RTT. Each 100s bucket is closed and appended to the sample ring. The web UI streams new buckets via SSE for live chart updates.

Prometheus metrics

L2TP metrics

Metric Type Description
ze_l2tp_sessions_active gauge Sessions in established state
ze_l2tp_sessions_starting gauge Sessions in negotiation
ze_l2tp_sessions_finishing gauge Sessions being torn down
ze_l2tp_tunnels_active gauge Active tunnels
ze_l2tp_session_rx_bytes_total counter RX bytes on pppN interface
ze_l2tp_session_tx_bytes_total counter TX bytes on pppN interface
ze_l2tp_lcp_echo_rtt_seconds histogram LCP echo round-trip time
ze_l2tp_lcp_echo_loss_ratio gauge Current 100s bucket echo loss ratio

RADIUS metrics

Metric Type Description
ze_radius_up gauge Server reachability (1=up, 0=down)
ze_radius_auth_sent_total counter Access-Request packets sent
ze_radius_acct_sent_total counter Accounting-Request packets sent
ze_radius_interim_sent_total counter Interim-Update packets sent

Web UI

The web interface at /l2tp provides session management and CQM graphing (requires authentication).

URL Purpose
/l2tp Session list with sortable columns
/l2tp/<sid> Session detail: state, PPP options, CQM chart, event timeline, disconnect
/l2tp/<login>/samples CQM buckets as columnar JSON
/l2tp/<login>/samples.csv CQM buckets as CSV download
/l2tp/<login>/samples/stream SSE stream pushing new CQM buckets every 100s
/l2tp/<sid>/disconnect Disconnect session (requires reason; optional cause code)

The CQM chart renders 24h of historical data, then appends new 100-second buckets in real time via SSE.

CLI commands

Read commands

Command Output
show l2tp Aggregate counters: tunnel count, session count, listener count.
show l2tp tunnels Array of tunnel summaries.
show l2tp tunnel <id> One tunnel's detail (AVPs, capabilities, session list).
show l2tp sessions Array of session summaries (flattened across tunnels).
show l2tp session <id> One session's detail (PPP state, assigned IP, speeds).
show l2tp statistics Protocol counters.
show l2tp listeners Bound UDP endpoints.
show l2tp config Effective runtime config; shared-secret redacted.

Destructive commands

Command Effect
clear l2tp tunnel teardown <id> Sends StopCCN Result Code 6 (administrative).
clear l2tp tunnel teardown-all Same, for every live tunnel.
clear l2tp session teardown <id> [reason <text>] [cause <code>] Sends CDN Result Code 3 (administrative).
clear l2tp session teardown-all Same, for every live session.

Route redistribution

When a PPP NCP completes, the subsystem emits a route-change event with the assigned peer IP as a /32 (IPv4) or /128 (IPv6) prefix:

redistribute {
    destination bgp {
        import l2tp {
            family [ ipv4/unicast ipv6/unicast ];
        }
    }
}

Reload semantics

Field Reload behaviour
shared-secret Hot-apply; takes effect on new SCCRQs.
hello-interval Hot-apply; new tunnels use the new interval.
max-tunnels Hot-apply at next admission decision.
max-sessions Hot-apply at next admission decision.
auth-method Hot-apply to new PPP sessions.
allow-no-auth Hot-apply to new PPP sessions.
enabled flip Rejected with WARN. Restart required.
Listener endpoint change Rejected with WARN. Restart required.

See also

  • PPPoE for direct-attach subscriber access (alternative to L2TP).
  • Firewall for subscriber traffic filtering.
  • Policy Routing for per-subscriber traffic steering.
  • Plugins for the plugin list.

Adapted from main/docs/guide/l2tp.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally