RFC 1331

The Point-to-Point Protocol (PPP) for the Transmission of Multi-protocol Datagrams over Point-to-Point Links

๐Ÿ“… published May 1992, from ietf

okay bestie, this is the doc that gave us PPP ๐Ÿ’– It's a Standards Track spec from the IAB, written by W. Simpson (Daydreamer), dated May 1992. It obsoletes RFCs 1171 and 1172, which means it replaces them, so those older docs are out of the picture. Not gonna lie, I'm obsessed with how this one pulled everything together โœจ


Status of this Memo ๐Ÿ“œ

ngl this part is kinda important so read it. This RFC is an IAB standards track protocol spec for the Internet community. It's also asking people for discussion and suggestions for improvements ๐Ÿซถ For the current standardization state and status of this protocol, check the latest edition of the "IAB Official Protocol Standards" doc. And the memo can be distributed with no restrictions (distribution is unlimited) ๐ŸŒˆ

Abstract ๐Ÿฆ‹

so PPP is how you send datagrams over serial point-to-point links ๐Ÿ”Œ It has three main parts:

  1. A way to encapsulate datagrams over serial links (wrapping them up so they travel safely) ๐ŸŽ
  2. A Link Control Protocol (LCP) for establishing, configuring, and testing the data-link connection ๐Ÿงช
  3. A family of Network Control Protocols (NCPs) for establishing and configuring different network-layer protocols ๐Ÿงš

This doc defines the PPP encapsulation scheme plus LCP, which is an extensible option negotiation protocol. It can negotiate a whole bunch of configuration parameters and also does some extra management stuff. Main character energy, literally ๐Ÿ‘‘

This RFC is a product of the Point-to-Point Protocol Working Group of the IETF. If you have comments, send them to the ietf-ppp@ucdavis.edu mailing list ๐Ÿ’Œ

Table of Contents ๐Ÿ“

     1.     Introduction ..........................................    1
        1.1       Specification of Requirements ...................    3
        1.2       Terminology .....................................    3

     2.     Physical Layer Requirements ...........................    4

     3.     The Data Link Layer ...................................    5
        3.1       Frame Format ....................................    6

     4.     PPP Link Operation ....................................   10
        4.1       Overview ........................................   10
        4.2       Phase Diagram ...................................   10
        4.3       Link Dead (physical-layer not ready) ............   10
        4.4       Link Establishment Phase ........................   11
        4.5       Authentication Phase ............................   11
        4.6       Network-Layer Protocol Phase ....................   12
        4.7       Link Termination Phase ..........................   12

     5.     The Option Negotiation Automaton ......................   14
        5.1       State Diagram ...................................   15
        5.2       State Transition Table ..........................   16
        5.3       States ..........................................   18
        5.4       Events ..........................................   20
        5.5       Actions .........................................   24
        5.6       Loop Avoidance ..................................   26
        5.7       Counters and Timers .............................   27

     6.     LCP Packet Formats ....................................   28
        6.1       Configure-Request ...............................   30
        6.2       Configure-Ack ...................................   31
        6.3       Configure-Nak ...................................   32
        6.4       Configure-Reject ................................   33
        6.5       Terminate-Request and Terminate-Ack .............   35
        6.6       Code-Reject .....................................   36
        6.7       Protocol-Reject .................................   38
        6.8       Echo-Request and Echo-Reply .....................   39
        6.9       Discard-Request .................................   40

     7.     LCP Configuration Options .............................   42
        7.1       Format ..........................................   43
        7.2       Maximum-Receive-Unit ............................   44
        7.3       Async-Control-Character-Map .....................   45
        7.4       Authentication-Protocol .........................   47
        7.5       Quality-Protocol ................................   49
        7.6       Magic-Number ....................................   51
        7.7       Protocol-Field-Compression ......................   54
        7.8       Address-and-Control-Field-Compression ...........   56

     APPENDICES ...................................................   58

     A.     Asynchronous HDLC .....................................   58

     B.     Fast Frame Check Sequence (FCS) Implementation ........   61
        B.1       FCS Computation Method ..........................   61
        B.2       Fast FCS table generator ........................   63

     C.     LCP Recommended Options ...............................   64

     SECURITY CONSIDERATIONS ......................................   65

     REFERENCES ...................................................   65

     ACKNOWLEDGEMENTS .............................................   66

     CHAIR'S ADDRESS ..............................................   66

     AUTHOR'S ADDRESS .............................................   66

1. Introduction ๐ŸŒธ

Motivation

okay so the Internet has been blowing up ๐Ÿ“ˆ The number of hosts running TCP/IP has grown explosively over the last few years. Most of them sit on Local Area Networks (LANs), with Ethernet being the big one. A bunch of the others are on Wide Area Networks (WANs) like X.25 style Public Data Networks (PDNs). But relatively few hosts use simple point-to-point (serial) links, even though those are among the oldest ways to do data comms and almost every host supports them. Asynchronous RS-232-C [1] interfaces are basically everywhere ๐Ÿ™ˆ

Encapsulation

one reason there aren't many point-to-point IP links is that there's no standard encapsulation protocol ๐Ÿ˜ญ There are tons of non-standard ones (and at least one de facto standard), but nothing has been agreed on as an Internet Standard. Meanwhile, LANs have standard encapsulation schemes already, so it's kinda unfair lol ๐Ÿ’…

PPP gives you encapsulation over both bit-oriented synchronous links and asynchronous links with 8 bits of data and no parity. These links MUST be full-duplex, but they MAY be either dedicated or circuit-switched. PPP is built on HDLC for its encapsulation ๐ŸŽ€

PPP is designed to stay compatible with the hardware people actually use โœจ It also has an escape mechanism so control data like XON/XOFF can go across the link transparently, and so spurious control data that intervening hardware or software injects into the link can be removed ๐Ÿงน

The PPP encapsulation also lets you multiplex different network-layer protocols at the same time over one link. The goal is one common solution for easily connecting a wide variety of hosts, bridges and routers ๐ŸŒˆ

Some protocols need error-free transmission, and they either do error detection only conditionally or don't do it at all. PPP uses the HDLC Frame Check Sequence for error detection ๐Ÿง It's commonly available in hardware, and a software implementation is provided too.

By default, the encapsulation only adds 8 extra octets ๐Ÿฌ In environments where bandwidth is precious, it can be shrunk down to as few as 2 octets. For fast hardware, PPP makes sure the default encapsulation header and information fields land on 32-bit boundaries, and it lets the trailer get padded out to an arbitrary boundary ๐Ÿš€

here's the big deal, though: PPP is more than just an encapsulation scheme ๐Ÿ˜ค To be versatile enough to port across a wide range of environments, PPP has a Link Control Protocol (LCP). The LCP is used to automatically agree on the encapsulation format options, handle varying limits on packet sizes, authenticate the identity of the peer on the link, figure out when a link is working properly and when it's dead, detect a looped-back link and other common misconfigurations, and terminate the link ๐Ÿ’ซ

Network Control Protocols

point-to-point links make a lot of existing network protocol problems worse ๐Ÿ’€ For example, assigning and managing IP addresses is annoying even on LANs, but it's especially rough over circuit-switched links like dial-up modem servers. That's where the family of Network Control Protocols (NCPs) comes in. Each NCP handles the specific needs of its own network-layer protocol. Those NCPs are defined in other documents ๐Ÿ“š

Configuration

PPP is meant to be easy to configure ๐Ÿฅฐ The standard defaults should handle all the common setups out of the box. An implementor can specify improvements to the defaults, and those get automatically communicated to the peer with no operator babysitting. And if needed, the operator can explicitly configure link options so it works in environments where it otherwise couldn't ๐Ÿซถ

The self-configuration happens through an extensible option negotiation mechanism, where each end of the link tells the other about its capabilities and requirements. This doc specifies the option negotiation in terms of LCP, but the same facilities can be used by the Internet Protocol Control Protocol (IPCP) and the others in the NCP family ๐Ÿงš

1.1. Specification of Requirements

okay so this section explains the vocab ๐Ÿ“– A few words get used to signal the requirements of the spec, and they're often written in capitals. Here's what each one means ๐Ÿ‘‡

MUST

this word (or the adjective "required") means the definition is an absolute requirement of the spec. No wiggle room ๐Ÿ”’

MUST NOT

this phrase means the definition is an absolute prohibition of the spec. Hard no ๐Ÿšซ

SHOULD

this word (or the adjective "recommended") means there may be valid reasons in particular circumstances to ignore the item, but the full implications should be understood and carefully weighed before picking a different path ๐Ÿค”

MAY

this word (or the adjective "optional") means the item is one of an allowed set of alternatives โœจ An implementation that doesn't include this option MUST be prepared to interoperate with another implementation that does include it. So be nice to your bestie's implementation, periodt ๐Ÿ’–


Note to self: the next part of this doc picks up at Section 1.2 (Terminology), so stay tuned! ๐Ÿงš

1.2. Terminology ๐Ÿ“–

okay so this doc keeps using a couple of terms over and over, so let's lock them in first ๐Ÿ’…

  • peer: The other end of the point-to-point link. ๐Ÿซถ
  • silently discard: This means the implementation throws the packet away without any further processing. The implementation SHOULD provide the capability of logging the error, including the contents of the silently discarded packet, and SHOULD record the event in a statistics counter. ๐Ÿ™ˆ

2. Physical Layer Requirements ๐Ÿ”Œโœจ

PPP is literally so chill about hardware ๐Ÿ˜ญ It works over any DTE/DCE interface (for example EIA RS-232-C, EIA RS-422, EIA RS-423 and CCITT V.35). The one hard requirement is a full-duplex circuit, either dedicated or circuit-switched, that can run in asynchronous (start/stop) or synchronous bit-serial mode, as long as it's transparent to PPP Data Link Layer frames. PPP doesn't put any limits on transmission rate, other than whatever the particular DTE/DCE interface you're using already imposes. ๐Ÿš€

PPP does not require any particular synchronous encoding, such as FM, NRZ, or NRZI. ๐ŸŒˆ

Implementation Note: NRZ is currently the most widely available, so on that basis it is recommended as a default. When configuring the encoding is allowed, NRZI is recommended as an alternative, because of its relative immunity to signal inversion configuration errors. ๐Ÿ’–

PPP does not require the use of modem control signals, such as Request To Send (RTS), Clear To Send (CTS), Data Carrier Detect (DCD), and Data Terminal Ready (DTR). ๐Ÿ“

Implementation Note: When they're available, using these signals can allow greater functionality and performance. In particular, such signals SHOULD be used to signal the Up and Down events in the Option Negotiation Automaton (described below). โญ

okay this part is the foundation, so pay attention bestie ๐ŸŽ€ PPP borrows the principles, terminology, and frame structure of the International Organization For Standardization's (ISO) High-level Data Link Control (HDLC) procedures (ISO 3309-1979 [2]), as modified by ISO 3309:1984/PDAD1 "Addendum 1: Start/stop transmission" [5]. ISO 3309-1979 covers the HDLC frame structure for synchronous environments. ISO 3309:1984/PDAD1 proposes changes to ISO 3309-1979 so it can work in asynchronous environments. ๐Ÿฆ‹

The PPP control procedures use the definitions and Control field encodings standardized in ISO 4335-1979 [3] and ISO 4335-1979/Addendum 1-1979 [4]. The PPP frame structure is also consistent with CCITT Recommendation X.25 LAPB [6], since that one is based on HDLC too. ๐Ÿงš

The purpose of this memo is NOT to re-document what's already standardized in ISO 3309 (sorry, I mean it's not the point of this doc ๐Ÿ˜…). We assume the reader already knows HDLC, or has access to a copy of [2] or [6]. Instead, this paper gives a concise summary and points out the specific options and features PPP uses. Since "Addendum 1: Start/stop transmission" isn't yet standardized and widely available, it gets summarized in Appendix A. ๐Ÿ“

To stay consistent with standard Internet practice, and to avoid confusing people who are used to reading RFCs, all binary numbers in the following descriptions are in Most Significant Bit to Least Significant Bit order, reading from left to right, unless otherwise indicated. Note that this is the opposite of standard ISO and CCITT practice, which orders bits as transmitted (i.e., network bit order). Keep this in mind when you compare this document with the international standards documents. ๐Ÿ‘€

3.1. Frame Format ๐Ÿ–ผ๏ธ

A summary of the standard PPP frame structure is shown below. This figure does not include start/stop bits (for asynchronous links), or any bits or octets inserted for transparency. The fields are transmitted from left to right. โœจ

        +----------+----------+----------+----------+------------
        |   Flag   | Address  | Control  | Protocol | Information
        | 01111110 | 11111111 | 00000011 | 16 bits  |      *
        +----------+----------+----------+----------+------------
                ---+----------+----------+-----------------
                   |   FCS    |   Flag   | Inter-frame Fill
                   | 16 bits  | 01111110 | or next Address
                ---+----------+----------+-----------------

Inter-frame Time Fill โณ

For asynchronous links, inter-frame time fill SHOULD be done the same way as inter-octet time fill, by transmitting continuous "1" bits (mark-hold state). ๐Ÿ’ซ

For synchronous links, the Flag Sequence SHOULD be transmitted during inter-frame time fill. There is no provision for inter-octet time fill. ๐Ÿคทโ€โ™€๏ธ

Implementation Note: Mark idle (continuous ones) SHOULD NOT be used for idle synchronous inter-frame time fill. However, certain types of circuit-switched links require mark idle, particularly those that calculate accounting based on bit activity. When mark idle is used on a synchronous link, the implementation MUST ensure at least 15 consecutive "1" bits between Flags, and that the Flag Sequence is generated at the beginning and end of a frame. ๐Ÿง 

Flag Sequence ๐Ÿšฉ

The Flag Sequence is a single octet and marks the beginning or end of a frame. It's the binary sequence 01111110 (hexadecimal 0x7e). ๐ŸŒธ

The Flag is a frame separator. Only one Flag is required between two frames. Two consecutive Flags make an empty frame, which gets ignored. ๐Ÿ™ƒ

Implementation Note: The "shared zero mode" Flag Sequence "011111101111110" SHOULD NOT be used. When it can't be avoided, such an implementation MUST ensure that the first Flag Sequence detected (the end of the frame) is promptly communicated to the link layer. ๐Ÿšจ

Address Field ๐Ÿ 

The Address field is a single octet and contains the binary sequence 11111111 (hexadecimal 0xff), the All-Stations address. PPP does not assign individual station addresses. The All-Stations address MUST always be recognized and received. Other address lengths and values may be defined at a later time, or by prior agreement. Frames with unrecognized Addresses SHOULD be silently discarded, and reported through the normal network management facility. ๐Ÿ“ฃ

Control Field ๐ŸŽ›๏ธ

The Control field is a single octet and contains the binary sequence 00000011 (hexadecimal 0x03), the Unnumbered Information (UI) command with the P/F bit set to zero. Frames with other Control field values SHOULD be silently discarded. ๐Ÿซ 

Protocol Field ๐Ÿงฉ

The Protocol field is two octets, and its value tells you which protocol is encapsulated in the Information field of the frame. ๐Ÿ’…

This Protocol field is defined by PPP and is not a field defined by HDLC. However, it is consistent with the ISO 3309 extension mechanism for Address fields. All Protocols MUST be odd; the least significant bit of the least significant octet MUST equal "1". Also, all Protocols MUST be assigned such that the least significant bit of the most significant octet equals "0". Frames received that don't follow these rules MUST be considered as having an unrecognized Protocol, and handled as specified by the LCP. The Protocol field is transmitted and received most significant octet first. ๐Ÿ”ข

Protocol field values in the "0---" to "3---" range identify the network-layer protocol of specific datagrams, and values in the "8---" to "b---" range identify datagrams belonging to the associated Network Control Protocols (NCPs), if any. ๐ŸŒ

Protocol field values in the "4---" to "7---" range are used for protocols with low volume traffic that have no associated NCP. Protocol field values in the "c---" to "f---" range identify datagrams as link-layer Control Protocols (such as LCP). ๐Ÿฆ–

The most up-to-date values of the Protocol field are specified in the most recent "Assigned Numbers" RFC [11]. Current values are assigned as follows: ๐Ÿ“‹

   Value (in hex)  Protocol Name

   0001 to 001f    reserved (transparency inefficient)
   0021            Internet Protocol
   0023            OSI Network Layer
   0025            Xerox NS IDP
   0027            DECnet Phase IV
   0029            Appletalk
   002b            Novell IPX
   002d            Van Jacobson Compressed TCP/IP
   002f            Van Jacobson Uncompressed TCP/IP
   0031            Bridging PDU
   0033            Stream Protocol (ST-II)
   0035            Banyan Vines
   0037            reserved (until 1993)
   00ff            reserved (compression inefficient)

   0201            802.1d Hello Packets
   0231            Luxcom
   0233            Sigma Network Systems

   8021            Internet Protocol Control Protocol
   8023            OSI Network Layer Control Protocol
   8025            Xerox NS IDP Control Protocol
   8027            DECnet Phase IV Control Protocol
   8029            Appletalk Control Protocol
   802b            Novell IPX Control Protocol
   802d            Reserved
   802f            Reserved
   8031            Bridging NCP
   8033            Stream Protocol Control Protocol
   8035            Banyan Vines Control Protocol

   c021            Link Control Protocol
   c023            Password Authentication Protocol
   c025            Link Quality Report
   c223            Challenge Handshake Authentication Protocol

Developers of new protocols MUST obtain a number from the Internet Assigned Numbers Authority (IANA), at IANA@isi.edu. ๐ŸŒŸ

Information Field ๐Ÿ“ฆ

The Information field is zero or more octets. It contains the datagram for the protocol named in the Protocol field. The end of the Information field is found by locating the closing Flag Sequence and allowing two octets for the Frame Check Sequence field. The default maximum length of the Information field is 1500 octets. By negotiation, consenting PPP implementations may use other values for the maximum Information field length. ๐Ÿฅฐ

On transmission, the Information field may be padded with an arbitrary number of octets, up to the maximum length. It is the responsibility of each protocol to tell padding octets apart from real information. ๐Ÿซง

Frame Check Sequence (FCS) Field ๐Ÿ”

The Frame Check Sequence field is normally 16 bits (two octets). Other FCS lengths may be defined at a later time, or by prior agreement. ๐Ÿงฎ

The FCS field is calculated over all bits of the Address, Control, Protocol and Information fields, not including any start and stop bits (asynchronous) and any bits (synchronous) or octets (asynchronous) inserted for transparency. This does not include the Flag Sequences or the FCS field itself. The FCS is transmitted with the coefficient of the highest term first. โœจ

Note: When octets are received which are flagged in the Async-Control-Character-Map, they are discarded before calculating the FCS. See the description in Appendix A. ๐Ÿงน

For more information on the specification of the FCS, see ISO 3309 [2] or CCITT X.25 [6]. ๐Ÿ“š

Note: A fast, table-driven implementation of the 16-bit FCS algorithm is shown in Appendix B. This implementation is based on [7], [8], and [9]. ๐ŸŽ๏ธ

Modifications to the Basic Frame Format ๐ŸŽจ

The Link Control Protocol can negotiate modifications to the standard PPP frame structure. However, modified frames will always be clearly distinguishable from standard frames. ๐Ÿฆ„

4.1. Overview ๐ŸŽ€

okay so before PPP can do literally anything, both ends of the point-to-point link have to send LCP packets to configure and test the data link ๐Ÿ”Œโœจ. Once the link is up, the peer might get authenticated ๐Ÿ”. Then PPP sends NCP packets to pick and configure one or more network-layer protocols ๐Ÿงš. Once each chosen protocol is configured, its datagrams can finally flow over the link ๐Ÿ’Œ.

The link stays configured until explicit LCP or NCP packets shut it down, or until something outside the protocol happens, like an inactivity timer running out or a network administrator stepping in ๐Ÿ•ฐ๏ธ๐Ÿ’….

4.2. Phase Diagram ๐Ÿฆ‹

while PPP is busy configuring, maintaining, and terminating the link, it moves through a bunch of distinct phases, and this diagram shows how they connect ๐Ÿ‘‘:

+------+        +-----------+           +--------------+
|      | UP     |           | OPENED    |              | SUCCESS/NONE
| Dead |------->| Establish |---------->| Authenticate |--+
|      |        |           |           |              |  |
+------+        +-----------+           +--------------+  |
   ^          FAIL |                   FAIL |             |
   +<--------------+             +----------+             |
   |                             |                        |
   |            +-----------+    |           +---------+  |
   |       DOWN |           |    |   CLOSING |         |  |
   +------------| Terminate |<---+<----------| Network |<-+
                |           |                |         |
                +-----------+                +---------+

every link starts and ends in this phase, no exceptions ๐Ÿซถ. When something external happens, like carrier detection or a network administrator configuring the link, and tells PPP the physical layer is ready to go, PPP moves on to the Link Establishment phase ๐Ÿš€.

while we're in this phase, the LCP automaton (we'll get to it later) is sitting in its Initial or Starting states ๐Ÿ˜ด. Moving into Link Establishment sends an Up event to the automaton โšก.

Implementation Note:

Typically, a link goes back to this phase automatically after a modem disconnects ๐Ÿ“ž. On a hard-wired line, this phase might be super short, just long enough to detect that the device is there ๐Ÿ“.

the Link Control Protocol (LCP) sets up the connection by trading Configure packets back and forth ๐Ÿ’ฌ. The exchange is finished, and the LCP Opened state is reached, once a Configure-Ack packet has been both sent and received โœ…. Any non-LCP packets that show up during this phase MUST be silently discarded ๐Ÿ™ˆ.

every Configuration Option starts out at its default value unless the configuration exchange changes it ๐Ÿงธ. Check out the section on LCP Configuration Options for more details ๐Ÿ’–.

it's really important to know that LCP only configures the options that don't depend on any particular network-layer protocol ๐ŸŒธ. Configuring each network-layer protocol is the job of its own Network Control Protocol (NCP), and that happens during the Network-Layer Protocol phase ๐Ÿงšโ€โ™€๏ธ.

4.5. Authentication Phase ๐Ÿ”

sometimes a link wants the peer to prove who it is before any network-layer protocol packets are allowed to flow ๐Ÿ•ต๏ธโ€โ™€๏ธ.

by default, authentication isn't required ๐Ÿ™…โ€โ™€๏ธ. But if an implementation insists that the peer uses some specific authentication protocol, then it MUST negotiate that authentication protocol during the Link Establishment phase ๐Ÿ“‹.

authentication SHOULD happen as soon as possible after link establishment ๐Ÿƒโ€โ™€๏ธ. Link quality determination MAY happen at the same time ๐ŸŒˆ. An implementation MUST NOT let the link quality determination packets hold up authentication forever โณ.

moving from the Authentication phase to the Network-Layer Protocol phase MUST NOT happen until the peer has been successfully authenticated with the negotiated authentication protocol ๐Ÿšซ. If authentication fails, PPP SHOULD go to the Link Termination phase instead ๐Ÿ’€.

4.6. Network-Layer Protocol Phase ๐ŸŒ

once PPP has finished the earlier phases, each network-layer protocol (like IP) MUST be configured separately by its own appropriate Network Control Protocol (NCP) ๐Ÿ’….

each NCP can be Opened and Closed whenever it wants ๐Ÿ”.

Implementation Note:

Since an implementation might take a while to figure out link quality first, implementations SHOULD avoid fixed timeouts while they wait for their peers to configure an NCP โฐ.

once an NCP reaches the Opened state, PPP carries the packets for the matching network-layer protocol ๐Ÿ“ฆ. Any network-layer protocol packets that arrive while the corresponding NCP is NOT in the Opened state SHOULD be silently discarded ๐Ÿซฅ.

during this phase, the link can carry any mix of LCP, NCP, and network-layer protocol packets ๐ŸŽ‰. Any NCP or network-layer protocol packets that show up during any other phase SHOULD be silently discarded ๐Ÿ™ƒ.

Implementation Note:

There's one exception to all of that, because of the LCP Protocol-Reject (we'll cover it later) ๐Ÿฆ„. While LCP is in the Opened state, any protocol packet the implementation doesn't support MUST be sent back in a Protocol-Reject ๐Ÿ“ฎ. Only the supported protocols get silently discarded โœจ.

PPP can end the link at any time ๐ŸŒ™. Usually a human user asks for it, but it might also happen because of something physical, like losing carrier, failing authentication, failing link quality, or an idle-period timer running out โฒ๏ธ.

LCP closes the link through an exchange of Terminate packets ๐Ÿซง. While the link is closing, PPP lets the network-layer protocols know so they can do whatever they need to ๐Ÿ’œ.

after the Terminate packets have been exchanged, the implementation SHOULD signal the physical layer to disconnect so the termination actually sticks ๐Ÿ”Œ, especially if authentication failed ๐Ÿšจ. The sender of the Terminate-Request SHOULD disconnect after it gets a Terminate-Ack, or after the Restart counter runs out โฑ๏ธ. The receiver of a Terminate-Request SHOULD wait for its peer to disconnect, and MUST NOT disconnect until at least one Restart time has passed after it sent a Terminate-Ack ๐Ÿง˜โ€โ™€๏ธ. PPP SHOULD then move on to the Link Dead phase ๐ŸŒฑ.

Implementation Note:

LCP closing the link is enough ๐Ÿ™Œ. Each NCP does NOT need to send its own flurry of Terminate packets ๐ŸŒช๏ธ. And just because an NCP has Closed doesn't mean the PPP link should be terminated, even if that NCP was the only one in the Opened state ๐Ÿ›‘.

5. The Option Negotiation Automaton ๐Ÿค–

the finite-state automaton is built out of events, actions, and state transitions ๐Ÿงฉ. Events include external commands like Open and Close, the Restart timer expiring, and packets arriving from a peer ๐Ÿ“ฌ. Actions include starting the Restart timer and sending packets to the peer ๐Ÿš€.

some packet types, namely Configure-Naks and Configure-Rejects, Code-Rejects and Protocol-Rejects, and Echo-Requests, Echo-Replies and Discard-Requests, aren't told apart in the automaton descriptions ๐Ÿ‘ฏ. They do have different jobs, which we'll get into later, but they always cause the same transitions ๐Ÿ’ซ.

Events                                   Actions

Up   = lower layer is Up                 tlu = This-Layer-Up
Down = lower layer is Down               tld = This-Layer-Down
Open = administrative Open               tls = This-Layer-Start
Close= administrative Close              tlf = This-Layer-Finished

TO+  = Timeout with counter > 0          irc = initialize restart
                                              counter
TO-  = Timeout with counter expired      zrc = zero restart counter

RCR+ = Receive-Configure-Request (Good)  scr = Send-Configure-Request
RCR- = Receive-Configure-Request (Bad)
RCA  = Receive-Configure-Ack             sca = Send-Configure-Ack
RCN  = Receive-Configure-Nak/Rej         scn = Send-Configure-Nak/Rej

RTR  = Receive-Terminate-Request         str = Send-Terminate-Request
RTA  = Receive-Terminate-Ack             sta = Send-Terminate-Ack

RUC  = Receive-Unknown-Code              scj = Send-Code-Reject
RXJ+ = Receive-Code-Reject (permitted)
   or Receive-Protocol-Reject
RXJ- = Receive-Code-Reject (catastrophic)
   or Receive-Protocol-Reject
RXR  = Receive-Echo-Request              ser = Send-Echo-Reply
   or Receive-Echo-Reply
   or Receive-Discard-Request
                                         -  = illegal action

5.1. State Diagram ๐Ÿ—บ๏ธ

this simplified state diagram walks through how both ends agree on Configuration Options (which opens the PPP link) and later how the link gets terminated ๐Ÿ’–.

              RCR                    TO+
            +--sta-->+             +------->+
            |        |             |        |
      +-------+      |   RTA +-------+      | Close +-------+
      |       |<-----+<------|       |<-str-+<------|       |
      |Closed |              |Closing|              |Opened |
      |       | Open         |       |              |       |
      |       |------+       |       |              |       |
      +-------+      |       +-------+              +-------+
                     |                                ^
                     |                                |
                     |         +-sca----------------->+
                     |         |                      ^
             RCN,TO+ V    RCR+ |     RCR-         RCA |    RCN,TO+
            +------->+         |   +------->+         |   +--scr-->+
            |        |         |   |        |         |   |        |
      +-------+      |   TO+ +-------+      |       +-------+      |
      |       |<-scr-+<------|       |<-scn-+       |       |<-----+
      | Req-  |              | Ack-  |              | Ack-  |
      | Sent  | RCA          | Rcvd  |              | Sent  |
+-scn->|       |------------->|       |       +-sca->|       |
|      +-------+              +-------+       |      +-------+
|   RCR- |   | RCR+                           |   RCR+ |   | RCR-
|        |   +------------------------------->+<-------+   |
|        |                                                 |
+<-------+<------------------------------------------------+
This diagram is NOT a complete picture of the automaton ๐Ÿ™ˆ. Implementation MUST be done by consulting the actual state transition table ๐Ÿ“–.

Events are in upper case and actions are in lower case ๐Ÿ”ค. For this purpose, the state machine starts out in the Closed state ๐Ÿ›Œ. Once the Opened state is reached, both ends of the link have sent and received a Configure-Ack packet ๐Ÿฅณ.

5.2. State Transition Table โœจ

okay so here's the whole state transition table bestie ๐Ÿ’… states go across the top and events go down the side. every box reads as action/new-state, and if there's more than one action they're separated by commas (they can wrap onto the next line if they need the space). a state might have a letter after it, and that's just a little footnote ๐Ÿซถ

Rationale:

ngl the old versions used a simplified non-deterministic finite-state automaton with a ton of detail hiding in the semantics, and that caused interoperability problems because everybody read it differently ๐Ÿ˜ญ

this table works like the older versions, except the up/down flags are now explicit states and the active/passive paradigm is gone ๐Ÿฆ‹ it's believed that this table interoperates with the previous versions better than those versions do themselves ๐Ÿ’–

      | State
      |    0         1         2         3         4         5
Events| Initial   Starting  Closed    Stopped   Closing   Stopping
------+-----------------------------------------------------------
 Up   |    2     irc,scr/6     -         -         -         -
 Down |    -         -         0       tls/1       0         1
 Open |  tls/1       1     irc,scr/6     3r        5r        5r
 Close|    0         0         2         2         4         4
      |
  TO+ |    -         -         -         -       str/4     str/5
  TO- |    -         -         -         -       tlf/2     tlf/3
      |
 RCR+ |    -         -       sta/2 irc,scr,sca/8   4         5
 RCR- |    -         -       sta/2 irc,scr,scn/6   4         5
 RCA  |    -         -       sta/2     sta/3       4         5
 RCN  |    -         -       sta/2     sta/3       4         5
      |
 RTR  |    -         -       sta/2     sta/3     sta/4     sta/5
 RTA  |    -         -         2         3       tlf/2     tlf/3
      |
 RUC  |    -         -       scj/2     scj/3     scj/4     scj/5
 RXJ+ |    -         -         2         3         4         5
 RXJ- |    -         -       tlf/2     tlf/3     tlf/2     tlf/3
      |
 RXR  |    -         -         2         3         4         5

      | State
      |    6         7         8           9
Events| Req-Sent  Ack-Rcvd  Ack-Sent    Opened
------+-----------------------------------------
 Up   |    -         -         -           -
 Down |    1         1         1         tld/1
 Open |    6         7         8           9r
 Close|irc,str/4 irc,str/4 irc,str/4 tld,irc,str/4
      |
  TO+ |  scr/6     scr/6     scr/8         -
  TO- |  tlf/3p    tlf/3p    tlf/3p        -
      |
 RCR+ |  sca/8   sca,tlu/9   sca/8   tld,scr,sca/8
 RCR- |  scn/6     scn/7     scn/6   tld,scr,scn/6
 RCA  |  irc/7     scr/6x  irc,tlu/9   tld,scr/6x
 RCN  |irc,scr/6   scr/6x  irc,scr/8   tld,scr/6x
      |
 RTR  |  sta/6     sta/6     sta/6   tld,zrc,sta/5
 RTA  |    6         6         8       tld,scr/6
      |
 RUC  |  scj/6     scj/7     scj/8   tld,scj,scr/6
 RXJ+ |    6         6         8           9
 RXJ- |  tlf/3     tlf/3     tlf/3   tld,irc,str/5
      |
 RXR  |    6         7         8         ser/9

the states where the Restart timer is running are easy to spot, they're the ones with TO events ๐Ÿ‘€ only the Send-Configure-Request, Send-Terminate-Request and Zero-Restart-Counter actions start or restart the Restart timer ๐ŸŽ€ and when you move from a state where the timer is running to one where it isn't, the Restart timer SHOULD be stopped ๐Ÿ’…

[p] Passive option; see Stopped state discussion. ๐ŸŒธ

[r] Restart option; see Open event discussion. ๐Ÿงš

[x] Crossed connection; see RCA event discussion. ๐Ÿ“


5.3. States ๐ŸŒˆ

here's a more detailed look at each automaton state, bestie ๐Ÿซถ

Initial

in the Initial state the lower layer is unavailable (Down) and no Open has happened yet ๐Ÿ˜ด the Restart timer is not running in the Initial state ๐Ÿ’ค

Starting

Starting is the Open counterpart to Initial ๐Ÿฆ‹ an administrative Open has been started, but the lower layer is still unavailable (Down) ๐Ÿ˜ญ the Restart timer is not running in Starting ๐Ÿ’œ

once the lower layer becomes available (Up), a Configure-Request gets sent ๐Ÿš€

Closed

in the Closed state the link is available (Up), but no Open has occurred ๐ŸŒธ the Restart timer is not running in Closed โœจ

when Configure-Request packets come in, a Terminate-Ack gets sent ๐Ÿ’– Terminate-Acks are silently discarded so we don't end up creating a loop ๐Ÿ™ˆ

Stopped

Stopped is the Open counterpart to Closed ๐ŸŽ€ it's where the automaton lands when it's waiting for a Down event after the This-Layer-Finished action, or after sending a Terminate-Ack ๐Ÿ‘€ the Restart timer is not running in Stopped ๐Ÿซถ

when Configure-Request packets arrive, an appropriate response gets sent โœจ when other packets arrive, a Terminate-Ack gets sent ๐Ÿ’… and again, Terminate-Acks are silently discarded to avoid creating a loop ๐Ÿ”

Rationale:

Stopped is a junction state ๐Ÿ‘‘ it covers link termination, link configuration failure, and other automaton failure modes, and these potentially separate states got combined into one ๐Ÿงฉ

there's a race condition between the Down event response (from the This-Layer-Finished action) and the Receive-Configure-Request event ๐Ÿ˜ฌ if a Configure-Request shows up before the Down event, the Down event will supercede and send the automaton back to Starting ๐Ÿ’ซ this is how it prevents attack by repetition ๐Ÿ›ก๏ธ

Implementation Option:

after the peer fails to respond to Configure-Requests, an implementation MAY wait passively for the peer to send Configure-Requests ๐Ÿง˜โ€โ™€๏ธ in that case the This-Layer-Finished action isn't used for the TO- event in Req-Sent, Ack-Rcvd and Ack-Sent ๐ŸŒท

this option is useful for dedicated circuits, or circuits that have no status signals available ๐Ÿ”Œ but it SHOULD NOT be used for switched circuits ๐Ÿ™…โ€โ™€๏ธ

Closing

in Closing, the automaton tries to terminate the connection ๐Ÿšช a Terminate-Request has been sent and the Restart timer is running, but a Terminate-Ack hasn't come back yet โณ

when a Terminate-Ack is received, the Closed state gets entered ๐ŸŽ‰ when the Restart timer expires, a new Terminate-Request is sent and the Restart timer gets restarted ๐Ÿ”„ after the Restart timer has expired Max-Terminate times, this action may be skipped, and the Closed state may be entered ๐ŸŒ™

Stopping

Stopping is the Open counterpart to Closing ๐ŸŽ€ a Terminate-Request has been sent and the Restart timer is running, but a Terminate-Ack hasn't been received yet ๐Ÿซง

Rationale:

Stopping gives you a well defined chance to terminate a link before any new traffic gets through ๐Ÿšง once the link has terminated, a new configuration can happen via the Stopped or Starting states ๐Ÿ’–

Request-Sent

in Request-Sent the automaton tries to configure the connection ๐Ÿ› ๏ธ a Configure-Request has been sent and the Restart timer is running, but a Configure-Ack hasn't been received yet, and one hasn't been sent either ๐Ÿ“ฎ

Ack-Received

in Ack-Received, a Configure-Request has been sent and a Configure-Ack has been received ๐Ÿฅณ the Restart timer is still running because a Configure-Ack hasn't been sent yet โฑ๏ธ

Ack-Sent

in Ack-Sent, both a Configure-Request and a Configure-Ack have been sent, but a Configure-Ack hasn't been received yet ๐Ÿ“ฌ the Restart timer is always running in Ack-Sent ๐Ÿƒโ€โ™€๏ธ

Opened

Opened is the big moment ๐ŸŽŠ here a Configure-Ack has been both sent and received ๐Ÿฅ‚ the Restart timer is not running in Opened โœจ

when the automaton enters Opened, the implementation SHOULD signal the upper layers that it is now Up ๐Ÿ†™ and when it leaves Opened, the implementation SHOULD signal the upper layers that it is now Down โฌ‡๏ธ iconic behaviour, no notes ๐Ÿ‘‘

5.4. Events โœจ

okay so, the whole automaton runs on events ๐ŸŽ€ Every transition and action happens because something triggered it, so let's go through the cast one by one bestie ๐Ÿ’…

Up

The Up event happens when a lower layer says "hey, I'm ready to carry packets!" ๐Ÿฆ‹ Usually this is how LCP finds out the link is entering the Link Establishment phase ๐ŸŒธ, or how an NCP learns the link is entering the Network-Layer Protocol phase โœจ

Down

The Down event is the opposite energy ๐Ÿ˜ญ It happens when a lower layer says it's no longer ready to carry packets. Usually LCP gets this to know the link is heading into the Link Dead phase ๐Ÿ’€, or an NCP gets it to know the link is leaving the Network-Layer Protocol phase ๐Ÿฅ€

Open

The Open event means the link is administratively available for traffic ๐Ÿ“ In other words, the network admin (a human or a program) has said "yep, this link is allowed to be Opened" ๐Ÿ‘‘ When Open happens and the link is not already in the Opened state, the automaton tries to send configuration packets to the peer ๐Ÿงš

If the automaton can't start configuring yet (the lower layer is Down, or a previous Close hasn't finished), the link's establishment just gets automatically delayed โณ no drama, it just waits its turn ๐Ÿซถ

When a Terminate-Request gets received, or other stuff happens that makes the link unavailable, the automaton moves to a state where the link is ready to re-open ๐Ÿฆ‹ No extra admin intervention should be necessary, which is lowkey iconic ๐Ÿ’–

Implementation Note:

Experience has shown that users will run an extra Open command when they want to renegotiate the link ๐Ÿ™ˆ But that's not what the Open event is for! So it's suggested that when an Open user command gets run while in the Opened, Closing, Stopping, or Stopped states, the implementation issues a Down event, immediately followed by an Up event โœจ That makes the link renegotiate without any harmful side effects ๐ŸŒˆ

Close

The Close event means the link is not available for traffic ๐Ÿ™…โ€โ™€๏ธ The network admin (human or program) has said the link is not allowed to be Opened. When Close happens and the link isn't already in the Closed state, the automaton tries to terminate the connection ๐Ÿ’œ Further attempts to re-configure the link get denied until a brand new Open event shows up ๐Ÿ”’

Timeout (TO+,TO-)

This one is the Restart timer going off โฐ The Restart timer is what times the responses to Configure-Request and Terminate-Request packets ๐ŸŒธ

The TO+ event means the Restart counter is still greater than zero, so the matching Configure-Request or Terminate-Request gets retransmitted ๐Ÿ”

The TO- event means the Restart counter is not greater than zero, so there are no more packets to retransmit, and we're done with that one ๐Ÿง

Receive-Configure-Request (RCR+,RCR-)

This event happens when a Configure-Request packet arrives from the peer ๐Ÿ“ฌ It says "I want to open a connection!" and it may include Configuration Options ๐ŸŽ€ We'll get into the Configure-Request packet in more detail in a later section ๐Ÿ‘€

The RCR+ event means the Configure-Request was acceptable, so it triggers sending back a matching Configure-Ack โœ…

The RCR- event means the Configure-Request was unacceptable, so it triggers sending back a matching Configure-Nak or Configure-Reject ๐Ÿ™…โ€โ™€๏ธ

Implementation Note:

These events can happen on a connection that's already in the Opened state ๐Ÿ˜ณ So the implementation MUST be prepared to immediately renegotiate the Configuration Options ๐Ÿ’…

Receive-Configure-Ack (RCA)

This event happens when a valid Configure-Ack packet arrives from the peer ๐Ÿฅฐ A Configure-Ack is the positive reply to a Configure-Request. If a packet is out of sequence or otherwise invalid, it gets silently discarded ๐Ÿซฅ

Implementation Note:

By the time we reach the Ack-Rcvd or Opened states, the correct packet has already been received, so it's extremely unlikely that another one shows up ๐Ÿคทโ€โ™€๏ธ As specified, all invalid Ack/Nak/Rej packets are silently discarded and don't affect the automaton's transitions ๐Ÿ™Œ
That said, it's not impossible for a correctly formed packet to arrive through a coincidentally-timed cross-connection ๐ŸŒ€ It's way more likely to be an implementation error though ๐Ÿ™ˆ At the very least, this occurrence should be logged ๐Ÿ“

Receive-Configure-Nak/Rej (RCN)

This event happens when a valid Configure-Nak or Configure-Reject packet arrives from the peer ๐Ÿ’” Both are negative replies to a Configure-Request. Out of sequence or otherwise invalid packets get silently discarded, same as before ๐Ÿซ 

Implementation Note:

Even though Configure-Nak and Configure-Reject cause the same state transition in the automaton, they have seriously different effects on the Configuration Options sent in the resulting Configure-Request packet ๐Ÿ‘€ So don't treat them as twins, bestie ๐Ÿ’–

Receive-Terminate-Request (RTR)

This event happens when a Terminate-Request packet arrives ๐Ÿšช It means the peer wants to close the connection.

Implementation Note:

This event is not the same as the Close event, and it does NOT override the Open commands of the local network administrator ๐Ÿ™…โ€โ™€๏ธ The implementation MUST be prepared to receive a new Configure-Request without any network administrator intervention ๐Ÿฆ‹

Receive-Terminate-Ack (RTA)

This event happens when a Terminate-Ack packet arrives from the peer ๐ŸŒท A Terminate-Ack is usually the reply to a Terminate-Request. It can also mean the peer is in the Closed or Stopped states, and it helps re-synchronize the link configuration ๐Ÿ”„

Receive-Unknown-Code (RUC)

This event happens when an un-interpretable packet arrives from the peer ๐Ÿคจ When that happens, a Code-Reject packet gets sent back in response ๐Ÿ“ค

Receive-Code-Reject, Receive-Protocol-Reject (RXJ+,RXJ-)

This event happens when a Code-Reject or a Protocol-Reject packet arrives from the peer ๐Ÿ™ƒ

The RXJ+ event happens when the rejected value is acceptable, like a Code-Reject for an extended code, or a Protocol-Reject for an NCP ๐ŸŒฟ These are totally within the scope of normal operation, so no panic ๐Ÿซถ The implementation MUST stop sending the offending packet type ๐Ÿ›‘

The RXJ- event happens when the rejected value is catastrophic, like a Code-Reject of Configure-Request, or a Protocol-Reject of LCP!! ๐Ÿ˜ฑ This one communicates an unrecoverable error that terminates the connection ๐Ÿ’€

Receive-Echo-Request, Receive-Echo-Reply, Receive-Discard-Request (RXR)

This event happens when an Echo-Request, Echo-Reply or Discard-Request packet arrives from the peer ๐Ÿ“จ The Echo-Reply is the response to an Echo-Request ๐Ÿชž There is no reply to an Echo-Reply or a Discard-Request, so that's the end of that conversation ๐Ÿค

5.5. Actions

okay bestie, actions are what the automaton actually does ๐Ÿ’… They get triggered by events, and they usually mean sending packets and/or starting or stopping the Restart timer โฑ๏ธ๐Ÿฆ‹

Illegal-Event (-)

this one's the "wait, that's not supposed to happen" action ๐Ÿ™ˆ It indicates an event that SHOULD NOT occur. The implementation probably has an internal error ๐Ÿ’€

This-Layer-Up (tlu)

this one tells the upper layers that the automaton is entering the Opened state โœจ

Typically, this action MAY be used by the LCP to signal the Up event to a NCP, Authentication Protocol, or Link Quality Protocol, or MAY be used by a NCP to indicate that the link is available for its traffic. ๐ŸŒธ

This-Layer-Down (tld)

the opposite energy ๐Ÿฅ€ It tells the upper layers that the automaton is leaving the Opened state.

Typically, this action MAY be used by the LCP to signal the Down event to a NCP, Authentication Protocol, or Link Quality Protocol, or MAY be used by a NCP to indicate that the link is no longer available for its traffic. ๐Ÿ’”

This-Layer-Start (tls)

this one talks to the lower layers ๐Ÿงš It means the automaton is entering the Starting state and the lower layer is needed for the link. The lower layer SHOULD respond with an Up event when it's available.

This action is highly implementation dependent. ๐Ÿคทโ€โ™€๏ธ

This-Layer-Finished (tlf)

also a lower-layer chat ๐Ÿซถ It means the automaton is entering the Stopped or Closed states, and the lower layer is no longer needed for the link. The lower layer SHOULD respond with a Down event when it has terminated.

Typically, this action MAY be used by the LCP to advance to the Link Dead phase, or MAY be used by a NCP to indicate to the LCP that the link may terminate when there are no other NCPs open. ๐Ÿ‘‘

This action is highly implementation dependent. ๐ŸŒˆ

Initialize-Restart-Counter (irc)

this one sets the Restart counter to the appropriate value (Max-Terminate or Max-Configure) ๐Ÿ”ฅ The counter is decremented for each transmission, including the first one.

Zero-Restart-Counter (zrc)

this one sets the Restart counter to zero ๐Ÿ“

Implementation Note: This action lets the FSA pause before it moves on to the desired final state. In addition to zeroing the Restart counter, the implementation MUST set the timeout period to an appropriate value. โณโœจ

Send-Configure-Request (scr)

this one transmits a Configure-Request packet ๐Ÿ“จ That's the "hey, I'd like to open a connection with this specific set of Configuration Options" move ๐Ÿ’– The Restart timer starts when the Configure-Request is sent, to guard against packet loss. The Restart counter gets decremented each time a Configure-Request goes out.

Send-Configure-Ack (sca)

this one transmits a Configure-Ack packet ๐ŸŽ€ It acknowledges that a Configure-Request came in with an acceptable set of Configuration Options. Yes queen ๐Ÿ‘‘

Send-Configure-Nak (scn)

this one transmits a Configure-Nak or Configure-Reject packet, whichever is appropriate ๐Ÿ™…โ€โ™€๏ธ It's the negative response for a Configure-Request with an unacceptable set of Configuration Options. Configure-Nak packets are used to refuse a Configuration Option value and to suggest a new, acceptable one. Configure-Reject packets are used to refuse all negotiation about a Configuration Option, typically because it isn't recognized or implemented. The difference between Configure-Nak and Configure-Reject is covered more fully in the section on LCP Packet Formats ๐Ÿฆ‹

Send-Terminate-Request (str)

this one transmits a Terminate-Request packet ๐Ÿ‘‹ That's the "okay, I'd like to close this connection" message. The Restart timer starts when the Terminate-Request is sent, to guard against packet loss. The Restart counter gets decremented each time a Terminate-Request is sent. ๐Ÿฅน

Send-Terminate-Ack (sta)

this one transmits a Terminate-Ack packet ๐Ÿซก It acknowledges a Terminate-Request, or otherwise helps synchronize the state machines. Teamwork makes the dream work ๐Ÿงš

Send-Code-Reject (scj)

this one transmits a Code-Reject packet ๐Ÿ™ˆ It indicates that an unknown type of packet came in. Not it ๐Ÿ’…

Send-Echo-Reply (ser)

this one transmits an Echo-Reply packet ๐Ÿ“ It acknowledges that an Echo-Request came in. Hi, I'm here, hbu? ๐Ÿ’œ

5.6. Loop Avoidance

okay so the protocol makes a reasonable attempt at avoiding Configuration Option negotiation loops ๐ŸŒ€ BUT it does NOT guarantee that loops won't happen ๐Ÿ˜ญ Like with any negotiation, you can configure two PPP implementations with conflicting policies that will literally never converge ๐Ÿ’€ It's also possible to configure policies that do converge, but take significant time to do it ๐Ÿข Implementors should keep this in mind and should implement loop detection mechanisms or higher level timeouts. Be prepared, bestie ๐Ÿ›ก๏ธโœจ

5.7. Counters and Timers

Restart Timer

there's one special timer used by the automaton โฐ The Restart timer times transmissions of Configure-Request and Terminate-Request packets. When it expires, it causes a Timeout event and retransmission of the corresponding Configure-Request or Terminate-Request packet. The Restart timer MUST be configurable, but MAY default to three (3) seconds ๐Ÿ’–

Implementation Note: The Restart timer SHOULD be based on the speed of the link. The default value is designed for low speed (19,200 bps or less), high switching latency links (typical telephone lines) ๐Ÿ“ž Higher speed links, or links with low switching latency, SHOULD have correspondingly faster retransmission times. โšก

Max-Terminate

there's one required restart counter for Terminate-Requests ๐ŸŽฏ Max-Terminate is the number of Terminate-Request packets sent without receiving a Terminate-Ack before assuming the peer is unable to respond. Max-Terminate MUST be configurable, but should default to two (2) transmissions. ๐ŸŒท

Max-Configure

a similar counter is recommended for Configure-Requests ๐Ÿง Max-Configure is the number of Configure-Request packets sent without receiving a valid Configure-Ack, Configure-Nak or Configure-Reject before assuming the peer is unable to respond. Max-Configure MUST be configurable, but should default to ten (10) transmissions. ๐Ÿ”Ÿ

Max-Failure

a related counter is recommended for Configure-Nak ๐Ÿ™ƒ Max-Failure is the number of Configure-Nak packets sent without sending a Configure-Ack before assuming the configuration isn't converging. Any further Configure-Nak packets get converted to Configure-Reject packets. Max-Failure MUST be configurable, but should default to ten (10) transmissions. ๐Ÿšซโžก๏ธ๐Ÿ™…โ€โ™€๏ธ


6. LCP Packet Formats โœจ

okay so there are three classes of LCP packets ๐ŸŽ€

  1. Link Configuration packets used to establish and configure a link (Configure-Request, Configure-Ack, Configure-Nak and Configure-Reject).
  2. Link Termination packets used to terminate a link (Terminate-Request and Terminate-Ack).
  3. Link Maintenance packets used to manage and debug a link (Code-Reject, Protocol-Reject, Echo-Request, Echo-Reply, and Discard-Request).

This document describes Version 1 of the Link Control Protocol ๐Ÿฆ‹ In the interest of simplicity, there's no version field in the LCP packet. If a new version of LCP is ever needed, the intention is that a new Data Link Layer Protocol field value will be used to tell Version 1 LCP apart from all other versions ๐ŸŒˆ A correctly functioning Version 1 LCP implementation will always respond to unknown Protocols (including other versions) with an easily recognizable Version 1 packet, which gives other versions a deterministic fallback mechanism. Clever, right? ๐Ÿง ๐Ÿ’…

Regardless of which Configuration Options are enabled, all LCP Link Configuration, Link Termination, and Code-Reject packets (codes 1 through 7) are always sent in the full, standard form, as if no Configuration Options were enabled ๐Ÿ›ก๏ธ This makes sure LCP Configure-Request packets are always recognizable, even when one end of the link mistakenly thinks the link is open. ๐Ÿซถ

Exactly one Link Control Protocol packet is encapsulated in the Information field of PPP Data Link Layer frames where the Protocol field indicates type hex c021 (Link Control Protocol) ๐Ÿ“ฆ

A summary of the Link Control Protocol packet format is shown below. The fields are transmitted from left to right. ๐Ÿ‘€

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

the Code field is one octet and identifies the kind of LCP packet ๐Ÿท๏ธ When a packet is received with an invalid Code field, a Code-Reject packet is transmitted. ๐Ÿ™…โ€โ™€๏ธ

The most up-to-date values of the LCP Code field are specified in the most recent "Assigned Numbers" RFC [11]. Current values are assigned as follows: ๐Ÿ“œ

   1       Configure-Request
   2       Configure-Ack
   3       Configure-Nak
   4       Configure-Reject
   5       Terminate-Request
   6       Terminate-Ack
   7       Code-Reject
   8       Protocol-Reject
   9       Echo-Request
   10      Echo-Reply
   11      Discard-Request
   12      RESERVED

Identifier

the Identifier field is one octet and helps match requests with replies ๐Ÿ”— When a packet is received with an invalid Identifier field, the packet is silently discarded. ๐Ÿคซ

Length

the Length field is two octets and indicates the length of the LCP packet, including the Code, Identifier, Length and Data fields ๐Ÿ“ Octets outside the range of the Length field should be treated as Data Link Layer padding and should be ignored on reception. When a packet is received with an invalid Length field, the packet is silently discarded. ๐Ÿงน

Data

the Data field is zero or more octets, as indicated by the Length field ๐Ÿ“ฆ The format of the Data field is determined by the Code field. โœจ

6.1. Configure-Request ๐Ÿ’–

Description

okay so, if a LCP implementation wants to open a connection, it MUST send a LCP packet with the Code field set to 1 (Configure-Request) and the Options field filled with whatever default link Configuration Options it wants to change. ๐ŸŽ€

When a Configure-Request comes in, an appropriate reply MUST be sent back. no skipping the reply, bestie ๐Ÿซถ

Here's the Configure-Request packet format. Fields go left to right, like reading a text ๐Ÿ’…

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code

1 for Configure-Request. it's giving "first message in the chat" ๐Ÿ’ฌ

Identifier

The Identifier field SHOULD be changed on every transmission โœจ On reception, the Identifier field should be copied into the Identifier field of the appropriate reply packet. that's how the replies know who they're answering ๐Ÿงš

Options

The Options field is variable in length and holds a list of zero or more Configuration Options the sender wants to negotiate. All Configuration Options get negotiated at the same time, no splitting them up ๐ŸŒธ The format of Configuration Options gets its own section later, so stay tuned ๐Ÿ‘‘

6.2. Configure-Ack ๐Ÿฆ‹

Description

If every Configuration Option in a Configure-Request is both recognizable and acceptable, then a LCP implementation should send a LCP packet with the Code field set to 2 (Configure-Ack), the Identifier field copied from the Configure-Request, and the Options field copied from the Configure-Request too. ๐Ÿ“ The acknowledged Configuration Options MUST NOT be reordered or modified in any way. hands off, they're perfect as they are ๐Ÿ™…โ€โ™€๏ธ

When a Configure-Ack comes in, the Identifier field must match the last Configure-Request that was sent. Also, the Configuration Options in a Configure-Ack must exactly match the ones in that last Configure-Request. if anything's off, the packet gets silently discarded ๐Ÿ™ˆ

Here's the Configure-Ack packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code

2 for Configure-Ack. the "yes, slay" packet ๐Ÿ’–

Identifier

The Identifier field is a copy of the Identifier field from the Configure-Request that caused this Configure-Ack ๐ŸŽ€

Options

The Options field is variable in length and holds a list of zero or more Configuration Options the sender is acknowledging. All Configuration Options are acknowledged at once, every time ๐Ÿ’…

6.3. Configure-Nak ๐ŸŒˆ

Description

If every element of a received Configuration Option is recognizable but some of them aren't acceptable, then a LCP implementation should send a LCP packet with the Code field set to 3 (Configure-Nak), the Identifier field copied from the Configure-Request, and the Options field filled with only the unacceptable Configuration Options from that Configure-Request. the acceptable ones get filtered out of the Configure-Nak, but the leftover options MUST NOT be reordered. no shuffling allowed ๐Ÿ™…โ€โ™€๏ธ

Each of the Nak'd Configuration Options MUST be modified to a value the Configure-Nak sender finds acceptable ๐Ÿซถ Options with no value fields (boolean options) use the Configure-Reject reply instead, so they don't get Nak'd ๐Ÿงš

Finally, an implementation may be configured to request negotiation of a specific option. If that option isn't on the list, then it may be added to the list of Nak'd Configuration Options, so the peer knows to list that option in its next Configure-Request packet โœจ Any value fields for the option MUST indicate values acceptable to the Configure-Nak sender. no sneaky values ๐Ÿ‘‘

When a Configure-Nak comes in, the Identifier field must match the last Configure-Request that was sent. Invalid packets are silently discarded ๐Ÿ’€

Getting a valid Configure-Nak means a new Configure-Request MAY be sent, with the Configuration Options changed the way the Configure-Nak said ๐Ÿฆ‹

Some Configuration Options have a variable length. Since the peer modified the Nak'd Option, the implementation MUST be able to handle an Option length that's different from the original Configure-Request. be flexible, it's a whole vibe ๐ŸŒธ

Here's the Configure-Nak packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code

3 for Configure-Nak. the "close, but no" packet ๐Ÿ“

Identifier

The Identifier field is a copy of the Identifier field from the Configure-Request that caused this Configure-Nak โœจ

Options

The Options field is variable in length and holds a list of zero or more Configuration Options the sender is Nak'ing. All Configuration Options get Nak'd simultaneously ๐Ÿ’œ

6.4. Configure-Reject ๐Ÿšซ

Description

If some Configuration Options in a Configure-Request aren't recognizable, or they aren't acceptable for negotiation (as set by a network administrator), then a LCP implementation should send a LCP packet with the Code field set to 4 (Configure-Reject), the Identifier field copied from the Configure-Request, and the Options field filled with only the unacceptable Configuration Options from that Configure-Request. the recognizable and negotiable ones get filtered out, but the Configuration Options MUST NOT be reordered or modified in any way. ๐ŸŽ€

When a Configure-Reject comes in, the Identifier field must match the last Configure-Request that was sent. Also, the Configuration Options in a Configure-Reject must be a proper subset of the ones in that last Configure-Request. Invalid packets get silently discarded ๐Ÿ™ˆ

Getting a valid Configure-Reject means a new Configure-Request SHOULD be sent, one that doesn't include any of the Configuration Options listed in the Configure-Reject ๐Ÿงš

Here's the Configure-Reject packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Options ...
   +-+-+-+-+

Code

4 for Configure-Reject. the "not for us" packet ๐Ÿ’…

Identifier

The Identifier field is a copy of the Identifier field from the Configure-Request that caused this Configure-Reject ๐ŸŒธ

Options

The Options field is variable in length and holds a list of zero or more Configuration Options the sender is rejecting. All Configuration Options are rejected together, as a group ๐Ÿ‘‘

6.5. Terminate-Request and Terminate-Ack ๐ŸŒ™

Description

LCP has Terminate-Request and Terminate-Ack Codes so there's a proper way to close a connection ๐Ÿฆ‹

A LCP implementation that wants to close a connection should send a LCP packet with the Code field set to 5 (Terminate-Request) and the Data field filled with whatever data it wants. Terminate-Request packets should keep getting sent until a Terminate-Ack is received, the lower layer says it has gone down, or enough of them have been sent that the peer is definitely down (with reasonable certainty) ๐Ÿงš

When a Terminate-Request comes in, a LCP packet MUST be sent with the Code field set to 6 (Terminate-Ack), the Identifier field copied from the Terminate-Request, and the Data field filled with any data the sender wants ๐Ÿซถ

Getting a Terminate-Ack nobody asked for means the peer is in the Closed or Stopped states, or it otherwise needs to renegotiate ๐Ÿ’€

Here's the format for Terminate-Request and Terminate-Ack packets. Fields go left to right:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

  • 5 for Terminate-Request
  • 6 for Terminate-Ack

Identifier

The Identifier field is one octet and helps match requests with replies ๐ŸŽ€

Data

The Data field is zero or more octets and holds uninterpreted data for the sender to use ๐ŸŒˆ The data can be any binary value and any length from zero up to the peer's established maximum Information field length minus four. bestie, that's a whole range ๐Ÿ“

6.6. Code-Reject ๐Ÿšจ

Description

Getting a LCP packet with an unknown Code means one of the LCP implementations talking to each other is faulty or incomplete ๐Ÿ˜ญ That error MUST be reported back to the sender of the unknown Code by sending a LCP packet with the Code field set to 7 (Code-Reject), and the inducing packet copied into the Rejected-Information field ๐Ÿ’œ

When a Code-Reject comes in, the implementation SHOULD report the error. the situation probably can't get fixed automatically, so someone needs to look at it ๐Ÿ™ˆ

Here's the Code-Reject packet format:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Rejected-Packet ...
   +-+-+-+-+-+-+-+-+

Code

7 for Code-Reject ๐Ÿงš

Identifier

The Identifier field is one octet and is for the transmitter to use ๐ŸŒธ

Rejected-Information

The Rejected-Information field has a copy of the LCP packet being rejected. It begins with the Information field, and it doesn't include any PPP Data Link Layer headers or the FCS โœจ

The Rejected-Information MUST be truncated to fit the peer's established maximum Information field length. chop it down, no exceptions ๐Ÿซถ

6.7. Protocol-Reject

Description

Okay bestie, so when a PPP frame shows up with a Data Link Layer Protocol we don't recognise ๐Ÿ™ˆ, the peer is basically knocking on the door for a protocol we don't speak. This usually happens when they're trying to set up a brand-new protocol ๐Ÿงš. If the LCP state machine is in the Opened state, you MUST report it back by sending an LCP packet with the Code field set to 8 (Protocol-Reject), the Rejected-Protocol field set to the Protocol you received, and the inducing packet copied into the Rejected-Information field ๐Ÿ’Œ.

When a Protocol-Reject comes in, your LCP implementation SHOULD stop sending frames of the rejected protocol ๐Ÿ’….

Protocol-Reject packets may only be sent in the LCP Opened state. Any Protocol-Reject received in a state other than Opened SHOULD be silently discarded ๐Ÿซถ.

Packet Format

A summary of the Protocol-Reject packet format is shown below. The fields go from left to right โœจ.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Rejected-Protocol       |      Rejected-Information ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Code

8 for Protocol-Reject.

Identifier

The Identifier field is one octet, and it's for the transmitter to use ๐ŸŽ€.

Rejected-Protocol

The Rejected-Protocol field is two octets and holds the Protocol of the Data Link Layer frame being rejected ๐Ÿšซ.

Rejected-Information

The Rejected-Information field is a copy of the frame being rejected. It starts with the Information field and does NOT include any PPP Data Link Layer headers or the FCS. The Rejected-Information MUST be truncated so it fits the peer's established maximum Information field length ๐Ÿงƒ.


6.8. Echo-Request and Echo-Reply

Description

LCP has Echo-Request and Echo-Reply Codes that give you a Data Link Layer loopback ๐Ÿ”, so you can test both directions of the link. It's super useful for debugging, link quality checks, performance testing, and a bunch of other stuff ๐ŸŒˆ.

An Echo-Request sender transmits an LCP packet with the Code field set to 9 (Echo-Request), the Identifier field set, the local Magic-Number inserted, and the Data field filled with whatever data you want. That data can go up to, but not past, the peer's established maximum Information field length minus eight ๐Ÿ“.

When an Echo-Request is received, an LCP packet MUST be transmitted with the Code field set to 10 (Echo-Reply), the Identifier field copied from the Echo-Request, the local Magic-Number inserted, and the Data field copied from the Echo-Request. Truncate as needed so you don't go past the peer's established maximum Information field length โœ‚๏ธ.

Echo-Request and Echo-Reply packets may only be sent in the LCP Opened state. Echo-Request and Echo-Reply packets received in any other state SHOULD be silently discarded ๐Ÿคซ.

Packet Format

A summary of the Echo-Request and Echo-Reply packet formats is shown below. The fields go from left to right ๐Ÿ’–.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Magic-Number                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

9 for Echo-Request;

10 for Echo-Reply.

Identifier

The Identifier field is one octet, and it helps match Echo-Requests with Echo-Replies ๐Ÿงฉ.

Magic-Number

The Magic-Number field is four octets, and it helps detect links that are in the looped-back condition ๐Ÿ”„. Unless modified by a Configuration Option, the Magic-Number MUST be transmitted as zero and MUST be ignored on reception. See the Magic-Number Configuration Option for further explanation ๐Ÿ‘€.

Data

The Data field is zero or more octets and holds uninterpreted data for the sender to use ๐Ÿ“ฆ. The data can be any binary value and any length from zero up to the peer's established maximum Information field length minus eight ๐Ÿซง.


6.9. Discard-Request

Description

LCP includes a Discard-Request Code, which gives you a Data Link Layer data sink ๐Ÿ•ณ๏ธ. It's for exercising the local-to-remote direction of the link. It's handy for debugging, performance testing, and lots of other things ๐ŸŒธ.

A discard sender transmits an LCP packet with the Code field set to 11 (Discard-Request), the Identifier field set, the local Magic-Number inserted, and the Data field filled with whatever data you want, up to but not exceeding the peer's established maximum Information field length minus eight ๐ŸŽˆ.

A discard receiver MUST simply throw away a Discard-Request that it receives ๐Ÿ—‘๏ธ.

Discard-Request packets may only be sent in the LCP Opened state.

Packet Format

A summary of the Discard-Request packet format is shown below. The fields go from left to right ๐Ÿฆ‹.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |  Identifier   |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                         Magic-Number                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Code

11 for Discard-Request.

Identifier

The Identifier field is one octet, and it's for use by the Discard-Request transmitter ๐Ÿ“ฎ.

Magic-Number

The Magic-Number field is four octets, and it helps detect links that are in the looped-back condition ๐Ÿ”. Unless modified by a configuration option, the Magic-Number MUST be transmitted as zero and MUST be ignored on reception. See the Magic-Number Configuration Option for further explanation ๐Ÿ’œ.

Data

The Data field is zero or more octets and holds uninterpreted data for the sender to use. The data can be any binary value and any length from zero up to the peer's established maximum Information field length minus four ๐ŸŒท.


7. LCP Configuration Options

LCP Configuration Options let you negotiate changes to the standard characteristics of a point-to-point link โœจ. Things you can negotiate include the maximum receive unit, async control character mapping, the link authentication method, and more ๐ŸŽ€. If a Configuration Option isn't included in a Configure-Request packet, the default value for that option is assumed ๐Ÿ’….

The end of the list of Configuration Options is marked by the length of the LCP packet ๐Ÿ“.

Unless otherwise specified, each Configuration Option is NOT listed more than once in a Configuration Options list. Some Configuration Options MAY be listed more than once. What that does is specific to each option and is spelled out by each such option ๐Ÿง.

Also unless otherwise specified, all Configuration Options apply in a half-duplex fashion. Once negotiated, they only apply to one direction of the link. Usually that's the receive direction, seen from the point of view of the Configure-Request sender ๐Ÿ”ฅ.

7.1. Format

A summary of the Configuration Option format is shown below. The fields go from left to right ๐ŸŒˆ.

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |    Data ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

The Type field is one octet and tells you what type of Configuration Option it is ๐Ÿท๏ธ. The most up-to-date values of the LCP Option Type field are in the most recent "Assigned Numbers" RFC [11]. The current values are assigned like this:

         1       Maximum-Receive-Unit
         2       Async-Control-Character-Map
         3       Authentication-Protocol
         4       Quality-Protocol
         5       Magic-Number
         6       RESERVED
         7       Protocol-Field-Compression
         8       Address-and-Control-Field-Compression

Length

The Length field is one octet and gives the length of this Configuration Option, counting the Type, Length and Data fields ๐Ÿ“. If a negotiable Configuration Option shows up in a Configure-Request with an invalid Length, a Configure-Nak SHOULD be transmitted. It should include the desired Configuration Option with an appropriate Length and Data ๐Ÿ™Œ.

Data

The Data field is zero or more octets and holds the value or other info for this Configuration Option ๐Ÿซง. Its format and length are determined by the Type and Length fields ๐Ÿ’–.

7.2. Maximum-Receive-Unit

Description

This Configuration Option can be sent to tell the peer that your implementation can receive larger frames. It can also be used to ask the peer to send smaller frames ๐Ÿ“ฆ. If smaller frames are requested, an implementation MUST still be able to receive 1500 octet frames, just in case link synchronization gets lost ๐Ÿ›Ÿ.

A summary of the Maximum-Receive-Unit Configuration Option format is shown below. The fields go from left to right ๐Ÿฆ‹.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |      Maximum-Receive-Unit     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

1

Length

4

Maximum-Receive-Unit

The Maximum-Receive-Unit field is two octets and indicates the new maximum receive unit ๐Ÿ“. The Maximum-Receive-Unit covers only the Data Link Layer Information field. It does NOT include the header, padding, FCS, or any transparency bits or bytes ๐Ÿ™…โ€โ™€๏ธ.

Default

1500

7.3. Async-Control-Character-Map โœจ

Description

okay bestie so this option lets you negotiate control character mapping on async links ๐Ÿงš by default PPP maps ALL the control characters into an appropriate two character sequence ๐Ÿ˜ญ but honestly it's rarely necessary to map every single one, and often you don't need to map any ๐Ÿ’… so a PPP implementation can use this option to tell its peer which control characters must stay mapped and which ones don't need to stay mapped when the peer sends them ๐Ÿซถ the peer can still send them in mapped format if it's needed because of constraints on its end ๐ŸŒธ

here's the spicy part ๐Ÿ”ฅ some Point-to-Point links use synchronous-to-asynchronous converters (some are built right into modems ๐Ÿ“ ) so you can end up with a synchronous PPP implementation on one end and an asynchronous one on the other. the converter is responsible for doing all the mapping conversions during operation ๐Ÿ’– to make this work, synchronous PPP implementations MUST always accept an Async-Control-Character-Map Configuration Option (it MUST always respond to an LCP Configure-Request specifying this Configuration Option with an LCP Configure-Ack โœจ). BUT accepting it doesn't mean the synchronous side is going to do any character mapping, because synchronous PPP uses bit-stuffing instead of character-stuffing ๐Ÿฆ‹ all that mapping gets handled by the asynchronous-to-synchronous converter, periodt ๐Ÿ’…

A summary of the Async-Control-Character-Map Configuration Option format is shown below. The fields are transmitted from left to right. ๐ŸŽ€

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |  Async-Control-Character-Map
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             ACCM (cont)           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

2

Length

6

Async-Control-Character-Map

The Async-Control-Character-Map field is four octets and indicates the new async control character map ๐Ÿง the map is encoded in big-endian fashion, where each numbered bit corresponds to the ASCII control character of the same value. If the bit is cleared to zero, then that ASCII control character need not be mapped. If the bit is set to one, then that ASCII control character must remain mapped. E.g., if bit 19 is set to zero, then the ASCII control character 19 (DC3, Control-S) may be sent in the clear โœจ

Note: The bit ordering of the map is as described in section 3.1, Most Significant Bit to Least Significant Bit. The least significant bit of the least significant octet (the final octet transmitted) is numbered bit 0, and would map to the ASCII control character NUL. ๐Ÿ™ˆ

Default

All ones (0xffffffff). ๐Ÿ’œ


7.4. Authentication-Protocol ๐Ÿ”

Description

on some links it might be desirable to require a peer to authenticate itself before any network-layer protocol packets get exchanged ๐Ÿ‘‘ this option gives you a way to negotiate the use of a specific authentication protocol. by default, authentication is not necessary ๐ŸŒˆ

okay here's the vibe check โœจ an implementation SHOULD NOT include multiple Authentication-Protocol Configuration Options in its Configure-Request packets. instead, it SHOULD attempt to configure the most desirable protocol first. if that protocol gets Rejected, then the implementation could attempt the next most desirable protocol in the next Configure-Request ๐Ÿฆ‹

now for the receiving side ๐Ÿซถ an implementation that gets a Configure-Request specifying Authentication-Protocols MAY choose at most one of the negotiable authentication protocols, and MUST send a Configure-Reject including the other specified authentication protocols. the implementation MAY reject all of the proposed authentication protocols too ๐Ÿ’…

if an implementation sends a Configure-Ack with this Configuration Option, then it's agreeing to authenticate with the specified protocol ๐Ÿ’– and an implementation that receives a Configure-Ack with this Configuration Option SHOULD expect the peer to authenticate with the acknowledged protocol ๐ŸŒธ

there is no requirement that authentication be full duplex, or that the same protocol be used in both directions. it's perfectly acceptable for different protocols to be used in each direction ๐ŸŽ€ this will, of course, depend on the specific protocols negotiated โœจ

A summary of the Authentication-Protocol Configuration Option format is shown below. The fields are transmitted from left to right. ๐Ÿงš

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |     Authentication-Protocol   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Type

3

Length

>= 4

Authentication-Protocol

The Authentication-Protocol field is two octets and indicates the authentication protocol desired. Values for this field are always the same as the PPP Data Link Layer Protocol field values for that same authentication protocol ๐Ÿ“

the most up-to-date values of the Authentication-Protocol field are specified in the most recent "Assigned Numbers" RFC [11]. current values are assigned as follows ๐Ÿ‘€

Value (in hex)          Protocol

c023                    Password Authentication Protocol
c223                    Challenge Handshake Authentication
                        Protocol

Data

The Data field is zero or more octets and contains additional data as determined by the particular protocol ๐Ÿ’œ

Default

No authentication protocol necessary. ๐ŸŒธ


7.5. Quality-Protocol ๐Ÿ“Š

Description

on some links it might be desirable to figure out when, and how often, the link is dropping data ๐Ÿ˜ญ this process is called link quality monitoring โœจ

this option gives you a way to negotiate the use of a specific protocol for link quality monitoring ๐Ÿ’… by default, link quality monitoring is disabled ๐Ÿฆ‹

there is no requirement that quality monitoring be full duplex, or that the same protocol be used in both directions. it's perfectly acceptable for different protocols to be used in each direction ๐Ÿซถ this will, of course, depend on the specific protocols negotiated ๐ŸŒˆ

A summary of the Quality-Protocol Configuration Option format is shown below. The fields are transmitted from left to right. ๐ŸŽ€

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |        Quality-Protocol       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |    Data ...
   +-+-+-+-+

Type

4

Length

>= 4

Quality-Protocol

The Quality-Protocol field is two octets and indicates the link quality monitoring protocol desired. Values for this field are always the same as the PPP Data Link Layer Protocol field values for that same monitoring protocol ๐Ÿง

the most up-to-date values of the Quality-Protocol field are specified in the most recent "Assigned Numbers" RFC [11]. current values are assigned as follows ๐Ÿ‘€

Value (in hex)          Protocol

c025                    Link Quality Report

Data

The Data field is zero or more octets and contains additional data as determined by the particular protocol ๐Ÿ’–

Default

None ๐Ÿ™ˆ

7.6. Magic-Number โœจ

Description

Okay bestie, this Configuration Option is how you catch looped-back links and other Data Link Layer weirdness ๐Ÿ•ต๏ธโ€โ™€๏ธ. Some other Configuration Options, like the Monitoring-Protocol Configuration Option, MAY be required to have it. Lowkey iconic. ๐Ÿ”

Before you even request this option, you have to pick your Magic-Number ๐Ÿ’…. It is recommended that the Magic-Number be chosen in the most random manner possible, so that an implementation will arrive at a unique number with very high probability. A good way to pick a unique random number is to start with an unique seed ๐ŸŒฑ. Suggested sources of uniqueness include machine serial numbers, other network hardware addresses, time-of-day clocks, etc. โฐ The really slay seeds are precise measurements of the inter-arrival time of physical events, like packet reception on other connected networks, server response time, or the typing rate of a human user โŒจ๏ธ. And it's also suggested that you use as many sources as possible at the same time. Main character energy ๐Ÿ‘‘.

Now, when a Configure-Request comes in with a Magic-Number Configuration Option, you compare the received Magic-Number with the Magic-Number of the last Configure-Request you sent to the peer ๐Ÿ‘€. If they're different, the link is NOT looped-back, and the Magic-Number should be acknowledged. ๐ŸŽ€ If they're equal, then it's possible (but not certain) that the link is looped-back and that this Configure-Request is actually the one you last sent ๐Ÿ˜ญ. To check, a Configure-Nak should be sent specifying a different Magic-Number value. And you should not send a new Configure-Request to the peer until normal processing would cause it to be sent (i.e., until a Configure-Nak is received or the Restart timer runs out) โณ.

Receiving a Configure-Nak with a Magic-Number different from the one in the last Configure-Nak you sent to the peer proves the link is not looped-back, and it indicates a unique Magic-Number ๐Ÿฆ‹. If the Magic-Number is equal to the one in the last Configure-Nak you sent, the looped-back possibility goes up, so you should choose a new Magic-Number ๐ŸŒ€. Either way, a new Configure-Request should be sent with the new Magic-Number โœจ.

If the link is actually looped-back, this sequence (transmit Configure-Request, receive Configure-Request, transmit Configure-Nak, receive Configure-Nak) will repeat over and over again ๐Ÿ”๐Ÿ’€. If the link is NOT looped-back, the sequence might happen a few times, but it's extremely unlikely to happen repeatedly. Way more likely, the Magic-Numbers picked at either end will quickly diverge, and that ends the sequence ๐Ÿ™Œ. The table below shows the probability of collisions, assuming both ends of the link pick Magic-Numbers with a perfectly uniform distribution ๐Ÿ“Š:

   Number of Collisions        Probability
   --------------------   ---------------------
           1              1/2**32    = 2.3 E-10
           2              1/2**32**2 = 5.4 E-20
           3              1/2**32**3 = 1.3 E-29

Good sources of uniqueness or randomness are required for this divergence to happen ๐Ÿซถ. If you can't find a good source of uniqueness, it is recommended that this Configuration Option NOT be enabled. In that case, Configure-Requests with the option SHOULD NOT be transmitted, and any Magic-Number Configuration Options the peer sends SHOULD be either acknowledged or rejected ๐Ÿ™ˆ. Here's the tea: loop-backs can't be reliably detected by the implementation in this case, although the peer might still be able to detect them ๐Ÿซ .

If an implementation DOES transmit a Configure-Request with a Magic-Number Configuration Option, then it MUST NOT respond with a Configure-Reject if its peer also transmits a Configure-Request with a Magic-Number Configuration Option ๐Ÿค. Basically, if you want to use Magic Numbers, you MUST also let your peer do the same, no drama. If an implementation does receive a Configure-Reject in response to a Configure-Request, it can only mean that the link is not looped-back, and that its peer will not be using Magic-Numbers ๐Ÿงš. In this case, an implementation should act as if the negotiation had been successful (as if it had instead received a Configure-Ack) ๐ŸŒˆ.

The Magic-Number can also be used to detect looped-back links during normal operation, not just during Configuration Option negotiation ๐Ÿ•ต๏ธ. All LCP Echo-Request, Echo-Reply, and Discard-Request packets have a Magic-Number field, which MUST normally be zero, and MUST normally be ignored on reception ๐Ÿซฅ. If Magic-Number has been successfully negotiated, an implementation MUST transmit these packets with the Magic-Number field set to its negotiated Magic-Number ๐Ÿ’–.

The Magic-Number field of these packets SHOULD be inspected on reception ๐Ÿ‘€. All received Magic-Number fields MUST be equal to either zero or the peer's unique Magic-Number, depending on whether or not the peer negotiated one ๐ŸŽ€.

Receiving a Magic-Number field equal to the negotiated local Magic-Number means you've got a looped-back link ๐Ÿ”. Receiving a Magic-Number that's neither the negotiated local Magic-Number nor the peer's negotiated Magic-Number (or zero, if the peer didn't negotiate one) means the link has been (mis)configured to talk to a different peer ๐Ÿ™ƒ.

The procedures for recovering from either case are unspecified and may vary from implementation to implementation ๐Ÿคทโ€โ™€๏ธ. A somewhat pessimistic procedure is to assume an LCP Down event ๐Ÿ˜ฌ. A further Open event will start the process of re-establishing the link, which can't finish until the loop-back condition ends and Magic-Numbers are successfully negotiated ๐Ÿ”ง. A more optimistic procedure (in the case of a loop-back) is to start transmitting LCP Echo-Request packets until an appropriate Echo-Reply is received, which indicates the loop-back condition has ended ๐ŸŒธ.

Format

A summary of the Magic-Number Configuration Option format is shown below. The fields are transmitted from left to right ๐Ÿ“ฆ.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |          Magic-Number
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         Magic-Number (cont)       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

5 ๐Ÿ”ข

Length

6 ๐Ÿ“

Magic-Number

The Magic-Number field is four octets and indicates a number which is very likely to be unique to one end of the link ๐Ÿ’œ. A Magic-Number of zero is illegal and MUST always be Nak'd, if it isn't Rejected outright ๐Ÿšซ.

Default

None. ๐Ÿซง


7.7. Protocol-Field-Compression ๐Ÿฆ„

Description

This Configuration Option lets you negotiate the compression of the Data Link Layer Protocol field ๐Ÿ—œ๏ธ. By default, all implementations MUST transmit standard PPP frames with two octet Protocol fields. But PPP Protocol field numbers are picked so that some values can be squished into a single octet form that's clearly different from the two octet form ๐Ÿงฉ. This Configuration Option is sent to tell the peer that your implementation can receive those single octet Protocol fields ๐Ÿ“ฌ. Compressed Protocol fields MUST NOT be transmitted unless this Configuration Option has been negotiated ๐Ÿšซ.

As mentioned before, the Protocol field uses an extension mechanism that's consistent with the ISO 3309 extension mechanism for the Address field ๐Ÿง . The Least Significant Bit (LSB) of each octet is used to show whether the Protocol field keeps going. A binary "0" as the LSB means the Protocol field continues with the following octet. A binary "1" as the LSB marks the last octet of the Protocol field ๐Ÿ. Here's a fun fact: any number of "0" octets can be put in front of the field and it still means the same value (look at the two versions of 3, 00000011 and 00000000 00000011) ๐Ÿค“.

To keep things simple, the standard PPP frame uses this and always sends Protocol fields in a two octet form ๐Ÿซถ. Protocol field values less than 256 (decimal) get a single zero octet in front of them, even though sending that zero (the most significant octet) isn't necessary ๐Ÿ™„.

But on low speed links, you want to save bandwidth by sending as little redundant data as possible ๐Ÿข. The Protocol Compression Configuration Option lets you trade off between simplicity of implementation and bandwidth efficiency โš–๏ธ. If it's successfully negotiated, the ISO 3309 extension mechanism can be used to compress the Protocol field down to one octet instead of two ๐Ÿ’จ. Most frames can be compressed, since data protocols usually have Protocol field values less than 256 ๐Ÿฅฐ.

Also, PPP implementations must continue to be robust, and they MUST accept PPP frames with either double-octet or single-octet Protocol fields, and they MUST NOT distinguish between them ๐Ÿซก.

The Protocol field is never compressed when sending any LCP packet. This rule makes sure LCP packets are always recognized without any confusion ๐Ÿ”’.

When a Protocol field is compressed, the Data Link Layer FCS field is calculated on the compressed frame, NOT the original uncompressed frame ๐Ÿงฎ.

A summary of the Protocol-Field-Compression Configuration Option format is shown below. The fields are transmitted from left to right ๐ŸŽ.

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |    Length     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

7 ๐ŸŒท

Length

2 โœŒ๏ธ

Default

Disabled. ๐Ÿ™…โ€โ™€๏ธ

7.8. Address-and-Control-Field-Compression โœจ

Description

okay so this option is how two peers agree to compress the Data Link Layer Address and Control fields ๐ŸŽ€ By default, every implementation MUST transmit frames with Address and Control fields and MUST use the hexadecimal values 0xff and 0x03 respectively. These fields always have the same values, so they're super easy to compress ๐Ÿ’… Sending this option just tells the other side that you're able to receive compressed Address and Control fields ๐Ÿซถ

Compressing them is literally just leaving them out ๐Ÿฆ‹ A Protocol field is two octets, and by definition its first octet will never be 0xff. The Protocol field value 0x00ff is not allowed (reserved) to avoid ambiguity, so the receiver can tell what's going on ๐Ÿงš

When something comes in, the receiver looks at the first two octets. If they're 0xff and 0x03, those are the Address and Control fields. If not, the fields were compressed and never got sent at all ๐Ÿ‘‘

If a compressed frame shows up when Address-and-Control-Field-Compression hasn't been negotiated, the implementation MAY silently discard the frame. ๐Ÿ’€

The Address and Control fields MUST NOT be compressed when sending any LCP packet. This is the rule that keeps LCP packets 100% recognizable, no cap ๐Ÿ”ฅ

When the Address and Control fields are compressed, the Data Link Layer FCS field gets calculated on the compressed frame, not the original uncompressed frame ๐ŸŒธ

A summary of the Address-and-Control-Field-Compression configuration option format is shown below. The fields go from left to right.

 0                   1
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |    Length     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

8

Length

2

Default

Not compressed. ๐Ÿ“

A. Asynchronous HDLC ๐Ÿฆ‹

This appendix goes over the changes to ISO 3309-1979 that were proposed in ISO 3309:1984/PDAD1, as used in the Point-to-Point Protocol. These changes make it possible to use HDLC on 8-bit asynchronous links โœจ

Transmission Considerations

Every octet gets sent with one start bit, eight bits of data, and one stop bit. Neither PPP nor ISO 3309:1984/PDAD1 has anything for seven-bit asynchronous links, so those are a no-go ๐Ÿ™ˆ

Flag Sequence

The Flag Sequence is one octet, and it marks where a frame begins or ends. It's the binary sequence 01111110 (hexadecimal 0x7e) ๐Ÿ’œ

Transparency

On asynchronous links, we use a character stuffing procedure ๐Ÿงš The Control Escape octet is binary 01111101 (hexadecimal 0x7d), and the bit positions are numbered 87654321 (not 76543210, BEWARE) โš ๏ธ

After the FCS is computed, the transmitter looks at the whole frame between the two Flag Sequences. Each Flag Sequence, each Control Escape octet, and each octet with a value under hexadecimal 0x20 that's flagged in the Remote Async-Control-Character-Map gets replaced by a two-octet sequence. That sequence is the Control Escape octet followed by the original octet with bit 6 complemented (i.e., exclusive-or'd with hexadecimal 0x20) ๐ŸŽ€

Before the FCS is computed, the receiver looks at the whole frame between the two Flag Sequences. Each octet with a value under hexadecimal 0x20 gets checked. If it's flagged in the Local Async-Control-Character-Map, it just gets removed (it may have been inserted by intervening data communications equipment) ๐Ÿซถ For each Control Escape octet, that octet is removed too, but bit 6 of the octet right after it gets complemented. A Control Escape octet sitting right before the closing Flag Sequence means the frame is invalid ๐Ÿ’€

Note: Including all octets under hexadecimal 0x20 lets all ASCII control characters [10] except DEL (Delete) get passed along transparently through almost all known data communications equipment โœจ

The transmitter may also send octets in the range 0x40 through 0xff (except 0x5e) in Control Escape format. Since these octet values aren't negotiable, this doesn't fix the problem of receivers that can't handle every non-control character ๐Ÿ˜ญ And because this technique doesn't touch the 8th bit, it also doesn't solve problems for links that can only send 7-bit characters ๐Ÿ™ˆ

Here are a few examples to make it clearer. Packet data goes over the link like this:

0x7e is encoded as 0x7d, 0x5e.
0x7d is encoded as 0x7d, 0x5d.
0x01 is encoded as 0x7d, 0x21.

Some modems with software flow control might intercept outgoing DC1 and DC3 while ignoring the 8th (parity) bit. That data would go over the link like this:

0x11 is encoded as 0x7d, 0x31.
0x13 is encoded as 0x7d, 0x33.
0x91 is encoded as 0x7d, 0xb1.
0x93 is encoded as 0x7d, 0xb3.

Aborting a Transmission

On asynchronous links, a frame can be aborted by sending a "0" stop bit where a "1" bit is expected (framing error), or by sending a Control Escape octet followed right away by a closing Flag Sequence ๐Ÿ“

Time Fill

On asynchronous links, inter-octet and inter-frame time fill MUST be done by sending continuous "1" bits (mark-hold state) ๐Ÿ’–

Note: On asynchronous links, inter-frame time fill can be thought of as extended inter-octet time fill. Doing that can save one octet per frame, which means less delay and more bandwidth ๐ŸŒˆ This works because a Flag Sequence can act as both a frame close and a frame begin. After any frame has been received, an idle receiver is always in a frame begin state.
Robust transmitters should avoid using this trick too zealously, because the price of less delay is less reliability ๐Ÿ˜ฌ Noisy links can make the receiver take in garbage characters and read them as part of an incoming frame. If the transmitter doesn't send a new opening Flag Sequence before the next frame, that frame gets tacked onto the noise characters and becomes an invalid frame (with high reliability). To avoid this, transmitters should send an opening Flag Sequence whenever "appreciable time" has passed since the prior closing Flag Sequence. It's suggested that implementations get the best results by always sending an opening Flag Sequence when the new frame isn't back-to-back with the last one. The maximum value for "appreciable time" is likely no greater than the typing rate of a slow-to-average typist, say 1 second โŒจ๏ธ

B. Fast Frame Check Sequence (FCS) Implementation ๐Ÿงฎ

B.1. FCS Computation Method

The following code does a table lookup to calculate the Frame Check Sequence as data arrives at the interface. This implementation is based on [7], [8], and [9]. The table is created by the code in section B.2.

/*
 * u16 represents an unsigned 16-bit number.  Adjust the typedef for
 * your hardware.
 */
typedef unsigned short u16;


/*
 * FCS lookup table as calculated by the table generator in section
 * B.2.
 */
static u16 fcstab[256] = {
   0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
   0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
   0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
   0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
   0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
   0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
   0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
   0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
   0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
   0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
   0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
   0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
   0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
   0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
   0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
   0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
   0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
   0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
   0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
   0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
   0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
   0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
   0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
   0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
   0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
   0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
   0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
   0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
   0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
   0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
   0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
   0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};

#define PPPINITFCS      0xffff  /* Initial FCS value */
#define PPPGOODFCS      0xf0b8  /* Good final FCS value */

/*
 * Calculate a new fcs given the current fcs and the new data.
 */
u16 pppfcs(fcs, cp, len)
    register u16 fcs;
    register unsigned char *cp;
    register int len;
{
    ASSERT(sizeof (u16) == 2);
    ASSERT(((u16) -1) > 0);
    while (len--)
        fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];

    return (fcs);
}

B.2. Fast FCS table generator ๐Ÿ”ง

The following code builds the lookup table used to calculate the FCS.

/*
 * Generate a FCS table for the HDLC FCS.
 *
 * Drew D. Perkins at Carnegie Mellon University.
 *
 * Code liberally borrowed from Mohsen Banan and D. Hugh Redelmeier.
 */

/*
 * The HDLC polynomial: x**0 + x**5 + x**12 + x**16 (0x8408).
 */
#define P       0x8408


main()
{
    register unsigned int b, v;
    register int i;

    printf("typedef unsigned short u16;\n");
    printf("static u16 fcstab[256] = {");
    for (b = 0; ; ) {
        if (b % 8 == 0)
            printf("\n");

        v = b;
        for (i = 8; i--; )
            v = v & 1 ? (v >> 1) ^ P : v >> 1;

        printf("0x%04x", v & 0xFFFF);
        if (++b == 256)
            break;
        printf(",");
    }
    printf("\n};\n");
}

The following Configurations Options are recommended:

SYNC LINES

  • Magic Number
  • Link Quality Monitoring
  • No Address and Control Field Compression
  • No Protocol Field Compression

ASYNC LINES

  • Async Control Character Map
  • Magic Number
  • Address and Control Field Compression
  • Protocol Field Compression

Security Considerations โœจ

okay so security gets its own little moment bestie ๐Ÿ”’๐Ÿ˜ญ the big takeaways are sprinkled through the parts about the Authentication Phase and the Authentication-Protocol Configuration Option ๐Ÿ’…. there's also a whole separate doc planned called PPP Authentication Protocols, so stay tuned for that one ๐Ÿฆ‹

References ๐Ÿ“š

Here's the reading list, bestie ๐Ÿซถ

  • [1] Electronic Industries Association, EIA Standard RS-232-C, "Interface Between Data Terminal Equipment and Data Communications Equipment Employing Serial Binary Data Interchange", August 1969.
  • [2] International Organization For Standardization, ISO Standard 3309-1979, "Data communication - High-level data link control procedures - Frame structure", 1979.
  • [3] International Organization For Standardization, ISO Standard 4335-1979, "Data communication - High-level data link control procedures - Elements of procedures", 1979.
  • [4] International Organization For Standardization, ISO Standard 4335-1979/Addendum 1, "Data communication - High-level data link control procedures - Elements of procedures - Addendum 1", 1979.
  • [5] International Organization For Standardization, Proposed Draft International Standard ISO 3309:1983/PDAD1, "Information processing systems - Data communication - High-level data link control procedures - Frame structure - Addendum 1: Start/stop transmission", 1984.
  • [6] International Telecommunication Union, CCITT Recommendation X.25, "Interface Between Data Terminal Equipment (DTE) and Data Circuit Terminating Equipment (DCE) for Terminals Operating in the Packet Mode on Public Data Networks", CCITT Red Book, Volume VIII, Fascicle VIII.3, Rec. X.25., October 1984.
  • [7] Perez, "Byte-wise CRC Calculations", IEEE Micro, June, 1983.
  • [8] Morse, G., "Calculating CRC's by Bits and Bytes", Byte, September 1986.
  • [9] LeVan, J., "A Fast CRC", Byte, November 1987.
  • [10] American National Standards Institute, ANSI X3.4-1977, "American National Standard Code for Information Interchange", 1977.
  • [11] Reynolds, J., and J. Postel, "Assigned Numbers", RFC 1060, USC/Information Sciences Institute, March 1990.

Acknowledgments ๐Ÿ™Œ

okay the credit list is giving main character energy ๐Ÿ‘‘ this doc is built on the WG Requirements (unpublished) and RFCs 1171 & 1172, by Drew Perkins of Carnegie Mellon University, and by Russ Hobby of the University of California at Davis ๐ŸŒธ

so many people put serious time into helping build the Point-to-Point Protocol ๐ŸŽ€ the full list is way too long to write out, but the special shoutouts go to: Rick Adams (UUNET), Ken Adelman (TGV), Fred Baker (ACC), Mike Ballard (Telebit), Craig Fox (NSC), Karl Fox (Morning Star Technologies), Phill Gross (NRI), former WG chair Russ Hobby (UC Davis), David Kaufman (Proteon), former WG chair Steve Knowles (FTP Software), John LoVerso (Xylogics), Bill Melohn (Sun Microsystems), Mike Patton (MIT), former WG chair Drew Perkins (CMU), Greg Satz (cisco systems) and Asher Waldfogel (Wellfleet) ๐Ÿ’–โœจ

Chair's Address ๐Ÿงš

if you want to reach the working group, go through the current chair:

Brian Lloyd
Lloyd & Associates
3420 Sudbury Road
Cameron Park, California 95682

Phone: (916) 676-1147

EMail: brian@ray.lloyd.com

Author's Address ๐Ÿ’œ

questions about this memo can also go to:

William Allen Simpson
Daydreamer
Computer Systems Consulting Services
P O Box 6205
East Lansing, MI  48826-6025

EMail: bsimpson@ray.lloyd.com
๐Ÿ“ฆ where this page comes from