How Linux Handles PPPoE Connections

The Linux operating system handles Point-to-Point Protocol over Ethernet (PPPoE) through a hybrid architecture combining user-space control daemons and in-kernel packet processing. By bridging the data link layer (Ethernet) and the network layer (PPP), Linux allows systems to authenticate and communicate over broadband networks such as DSL and fiber. This article explains how Linux initiates connections, offloads packet forwarding to the kernel, and manages transmission constraints like MTU sizing.

The Two-Phase PPPoE Process

Linux processes PPPoE connections in two distinct stages: Discovery and Session.

  1. Discovery Phase: Because Ethernet is a multi-access network without built-in point-to-point semantics, Linux must first locate an Access Concentrator (AC). A user-space utility (such as pppoe from the Roaring Penguin suite or NetworkManager) broadcasts a PPPoE Active Discovery Initiation (PADI) packet. When reachable concentrators reply with Offer (PADO) packets, the Linux client selects one, sends a Request (PADR), and waits for a Session-confirmation (PADS) containing a unique 16-bit Session ID.
  2. Session Phase: Once the Session ID is established, standard Point-to-Point Protocol (PPP) encapsulation begins. The Linux pppd daemon negotiates link parameters using the Link Control Protocol (LCP), performs credential verification via PAP or CHAP, and negotiates network settings (IP addresses, default routes, DNS servers) using the Internet Protocol Control Protocol (IPCP).

User-Space Control vs. Kernel-Space Data Path

Early Linux PPPoE implementations handled all packet encapsulation in user space. This created significant CPU overhead because every network frame required a context switch between the kernel network stack and the user daemon.

Modern Linux systems use a dedicated kernel module (pppoe, often compiled as part of CONFIG_PPPOE) alongside the ppp_generic subsystem:

This separation ensures full line-rate throughput with minimal CPU overhead.

Network Interface Creation

When the session negotiation succeeds, the kernel creates a virtual point-to-point network interface, typically designated as ppp0. This interface functions identically to any other standard network interface in Linux:

Handling MTU and MSS Clamping

Standard Ethernet frames have a Maximum Transmission Unit (MTU) of 1500 bytes. Because the PPPoE header consumes 6 bytes and the PPP protocol ID consumes 2 bytes, the maximum payload for an IP packet over PPPoE is reduced to 1492 bytes.

To prevent packet fragmentation or dropped packets caused by path MTU discovery issues, the Linux kernel relies on Maximum Segment Size (MSS) clamping. Network tools or firewall configurations inject rules via iptables or nftables using the TCPMSS target:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

This instruction forces Linux to rewrite the TCP MSS option in outgoing SYN packets to match the 1492-byte limit automatically, ensuring transparent and reliable communication across the PPPoE tunnel.