RFC 1662

PPP in HDLC-like Framing

๐Ÿ“… published July 1994, from ietf

RFC 1662: PPP in HDLC-like Framing ๐ŸŽ€

okay bestie, this is RFC 1662 and it's giving STANDARDS TRACK ๐Ÿ’… (part 1 of 5, so hang tight ๐Ÿซถ). It's STD 51 and the category is Standards Track. The editor is W. Simpson from Daydreamer, and the doc is dated July 1994 ๐ŸŒธ. It obsoletes RFC 1549, so 1549 is retired and this one is the new hotness โœจ.


Status of This Memo

okay so this part is the fine print ๐Ÿ™ˆ It says this is an Internet standards track protocol for the Internet community, and it wants your discussion and suggestions for improvements ๐Ÿ’œ. For the official standardization state and status, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“–. Distribution of this memo is unlimited ๐Ÿฆ‹.

Abstract

the whole point is that the Point-to-Point Protocol (PPP) [1] gives us a standard way to carry multi-protocol datagrams over point-to-point links ๐Ÿงš. This document is all about how to use HDLC-like framing for PPP encapsulated packets ๐Ÿ“.

Table of Contents

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

  2.     Physical Layer Requirements ...........................    3

  3.     The Data Link Layer ...................................    4
     3.1       Frame Format ....................................    5
     3.2       Modification of the Basic Frame .................    7

  4.     Octet-stuffed framing .................................    8
     4.1       Flag Sequence ...................................    8
     4.2       Transparency ....................................    8
     4.3       Invalid Frames ..................................    9
     4.4       Time Fill .......................................    9
        4.4.1  Octet-synchronous ...............................    9
        4.4.2  Asynchronous ....................................    9
     4.5       Transmission Considerations .....................   10
        4.5.1  Octet-synchronous ...............................   10
        4.5.2  Asynchronous ....................................   10

  5.     Bit-stuffed framing ...................................   11
     5.1       Flag Sequence ...................................   11
     5.2       Transparency ....................................   11
     5.3       Invalid Frames ..................................   11
     5.4       Time Fill .......................................   11
     5.5       Transmission Considerations .....................   12

  6.     Asynchronous to Synchronous Conversion ................   13

  7.     Additional LCP Configuration Options ..................   14
     7.1       Async-Control-Character-Map (ACCM) ..............   14

  APPENDICES ...................................................   17
  A.     Recommended LCP Options ...............................   17
  B.     Automatic Recognition of PPP Frames ...................   17
  C.     Fast Frame Check Sequence (FCS) Implementation ........   18
     C.1       FCS table generator .............................   18
     C.2       16-bit FCS Computation Method ...................   19
     C.3       32-bit FCS Computation Method ...................   21

  SECURITY CONSIDERATIONS ......................................   24
  REFERENCES ...................................................   24
  ACKNOWLEDGEMENTS .............................................   25
  CHAIR'S ADDRESS ..............................................   25
  EDITOR'S ADDRESS .............................................   25

1. Introduction โœจ

okay so this spec covers framing over bit-oriented and octet-oriented synchronous links, plus 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 ๐Ÿ’–.

there's an escape mechanism so control data like XON/XOFF can get sent through the link transparently, and so spurious control data that gets injected by in-between hardware and software can be removed ๐Ÿซถ.

some protocols expect error-free transmission and only do error detection on a conditional basis, or skip it entirely ๐Ÿ˜ญ. PPP uses the HDLC Frame Check Sequence for error detection ๐Ÿ”ฅ. It's commonly available in hardware, and a software implementation is provided too ๐Ÿ’….

1.1. Specification of Requirements

this section explains the requirement words. They're often capitalized, so watch for them ๐Ÿ‘€

  • MUST: this word, or the adjective "required", means the definition is an absolute requirement of the spec ๐Ÿ’…
  • MUST NOT: this phrase means the definition is an absolute prohibition of the spec ๐Ÿšซ
  • SHOULD: this word, or the adjective "recommended", means there may be valid reasons in particular circumstances to ignore this item ๐ŸŒธ. But the full implications must be understood and carefully weighed before picking a different course ๐Ÿง 
  • MAY: this word, or the adjective "optional", means this 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 ๐Ÿซถ

1.2. Terminology

this doc uses these terms a lot, so here's the tea ๐Ÿต

  • datagram: the unit of transmission in the network layer (like IP) ๐ŸŒ. A datagram may be encapsulated in one or more packets passed to the data link layer ๐Ÿ“ฆ
  • frame: the unit of transmission at the data link layer ๐ŸŽ€. A frame may include a header and/or a trailer, along with some number of units of data โœจ
  • packet: the basic unit of encapsulation, passed across the interface between the network layer and the data link layer ๐Ÿ“. A packet is usually mapped to a frame, but the exceptions are when data link layer fragmentation is happening, or when multiple packets get packed into a single frame ๐Ÿงš
  • peer: the other end of the point-to-point link ๐Ÿ’œ
  • silently discard: the implementation discards the packet 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 works across most DTE/DCE interfaces, like EIA RS-232-E, EIA RS-422, and CCITT V.35 ๐Ÿ’–. The only absolute requirement PPP has is a full-duplex circuit, either dedicated or circuit-switched ๐ŸŒธ. It needs to run in asynchronous (start/stop), bit-synchronous, or octet-synchronous mode, and be transparent to PPP Data Link Layer frames ๐Ÿฆ‹.

Interface Format

PPP presents an octet interface to the physical layer ๐Ÿ“. There's no provision for sub-octets to be supplied or accepted, so no sub-octet business here ๐Ÿ™…โ€โ™€๏ธ.

Transmission Rate

PPP doesn't put any restrictions on transmission rate, other than whatever the particular DTE/DCE interface allows โšก.

Control Signals

PPP doesn't require control signals like Request To Send (RTS), Clear To Send (CTS), Data Carrier Detect (DCD), and Data Terminal Ready (DTR) ๐Ÿ’….

when they're available, using these signals can unlock more functionality and performance โœจ. Specifically, these signals SHOULD be used to signal the Up and Down events in the LCP Option Negotiation Automaton [1] ๐Ÿ”ฅ. When these signals aren't available, the implementation MUST signal the Up event to LCP upon initialization, and SHOULD NOT signal the Down event ๐Ÿซถ.

since signalling isn't required, the physical layer MAY be decoupled from the data link layer ๐Ÿฆ‹, which hides the transient details of the physical transport ๐Ÿซง. This has implications for mobility in cellular radio networks, and other rapidly switching links ๐Ÿ“ก.

when moving from cell to cell within the same zone, an implementation MAY choose to treat the entire zone as a single link, even though transmission is switched among several frequencies ๐Ÿ—ผ. The link is considered to be with the central control unit for the zone, not the individual cell transceivers ๐Ÿข. Even so, the link SHOULD re-establish its configuration whenever it's switched to a different administration ๐Ÿ”.

due to the bursty nature of data traffic, some implementations have chosen to disconnect the physical layer during periods of inactivity, then reconnect when traffic resumes, without telling the data link layer ๐Ÿ™ƒ. Robust implementations should avoid using this trick over-zealously, since the price for decreased setup latency is decreased security ๐Ÿ”. Implementations SHOULD signal the Down event whenever "significant time" has elapsed since the link was disconnected โฐ. The value for "significant time" is a matter of major debate, and it's based on the tariffs, call setup times, and security concerns of the installation ๐Ÿ’€.


PPP uses the principles described in the ISO 3309-1979 HDLC frame structure, most recently the fourth edition 3309:1991 [2] ๐ŸŒˆ. That one specifies modifications that allow HDLC to be used in asynchronous environments ๐Ÿ’œ.

the PPP control procedures use the Control field encodings described in ISO 4335-1979 HDLC elements of procedures, most recently the fourth edition 4335:1991 [4] ๐ŸŽ€.

This should not be construed to indicate that every feature of the above recommendations is included in PPP. Each feature that is included is explicitly described in the following sections. ๐Ÿ™ˆ

to stay consistent with standard Internet practice, and avoid confusion for people 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 contrary to standard ISO and CCITT practice, which orders bits as transmitted (network bit order) ๐Ÿ”„. So keep this in mind when you compare this document with the international standards documents ๐Ÿ“š.

3.1. Frame Format ๐ŸŽ€

Okay bestie, here's the PPP HDLC-like frame structure at a glance ๐Ÿ’– It leaves out the sync bits (like start and stop bits on async links) and any bits or octets that get inserted for transparency. Everything gets sent left to right โœจ

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

The Protocol, Information and Padding fields are explained in the Point-to-Point Protocol Encapsulation [1] ๐Ÿ“š

Flag Sequence ๐Ÿšฉ

Every frame starts and ends with a Flag Sequence, which is the binary sequence 01111110 (hex 0x7e). Every implementation keeps checking for this flag, because it's how frame synchronization works ๐Ÿซถ

Only one Flag Sequence is required between two frames. Two Flag Sequences back to back make an empty frame. That gets silently discarded and does not count as an FCS error ๐Ÿ™ˆ

Address Field ๐Ÿ 

The Address field is one octet holding the binary sequence 11111111 (hex 0xff), which is the All-Stations address. Individual station addresses are not assigned, so it's all about the All-Stations address ๐Ÿ’… It MUST always be recognized and received.

Other address lengths and values may be defined later, or by prior agreement. Frames with unrecognized Addresses SHOULD be silently discarded.

Control Field ๐ŸŽ›๏ธ

The Control field is one octet holding the binary sequence 00000011 (hex 0x03). That's the Unnumbered Information (UI) command with the Poll/Final (P/F) bit set to zero โœจ

Other Control field values may be defined later, or by prior agreement. Frames with unrecognized Control field values SHOULD be silently discarded.

Frame Check Sequence (FCS) Field ๐Ÿ”

The FCS field defaults to 16 bits (two octets). It's sent least significant octet first, and that octet holds the coefficient of the highest term ๐Ÿงฎ

A 32-bit (four octet) FCS is also defined. Its use may be negotiated as described in "PPP LCP Extensions" [5] ๐Ÿฆ‹

Other FCS lengths may be defined later, or by prior agreement.

The FCS is calculated over all bits of the Address, Control, Protocol, Information and Padding fields. It does not include start and stop bits (async), bits (sync) or octets (async or sync) that got inserted for transparency. The Flag Sequences and the FCS field itself are not included either ๐Ÿ’€

When octets are received which are flagged in the Async-Control-Character-Map, they are discarded before calculating the FCS.

For more on how the FCS is specified, check out the Appendices ๐Ÿ“–

The end of the Information and Padding fields is found by locating the closing Flag Sequence and removing the Frame Check Sequence field. Easy peasy ๐ŸŒธ

3.2. Modification of the Basic Frame ๐Ÿฆ‹

The Link Control Protocol can negotiate changes to the standard HDLC-like frame structure. However, modified frames will always be clearly distinguishable from standard frames ๐Ÿ‘‘

Address-and-Control-Field-Compression ๐Ÿ—œ๏ธ

When you use standard HDLC-like framing, the Address and Control fields hold the hex values 0xff and 0x03 respectively. When other Address or Control field values are in use, Address-and-Control-Field-Compression MUST NOT be negotiated ๐Ÿšซ

On transmission, compressed Address and Control fields are simply omitted โœจ

On reception, the Address and Control fields get decompressed by looking at the first two octets. If those contain 0xff and 0x03, they're assumed to be the Address and Control fields. If not, it's assumed the fields were compressed and never got transmitted ๐Ÿง 

By definition, the first octet of a two octet Protocol field will never be 0xff (since it is not even). The Protocol field value 0x00ff is not allowed (reserved) to avoid ambiguity when Protocol-Field-Compression is enabled and the first Information field octet is 0x03. ๐Ÿ™ˆ

4. Octet-stuffed framing ๐Ÿงธ

This chapter gives a quick summary of how HDLC-like framing works on 8-bit asynchronous and octet-synchronous links ๐Ÿ’œ

4.1. Flag Sequence ๐Ÿšฉ

The Flag Sequence marks the beginning or end of a frame. The octet stream gets checked one octet at a time for the value 01111110 (hex 0x7e) ๐Ÿ‘€

4.2. Transparency ๐Ÿช„

This uses an octet stuffing procedure. The Control Escape octet is defined as binary 01111101 (hex 0x7d), most significant bit first ๐Ÿ’…

As a minimum, sending implementations MUST escape the Flag Sequence and Control Escape octets.

After FCS computation, the transmitter checks the entire frame between the two Flag Sequences. Each Flag Sequence, each Control Escape octet, and any octet flagged in the sending Async-Control-Character-Map (ACCM) gets replaced by a two octet sequence. That sequence is the Control Escape octet followed by the original octet exclusive-or'd with hex 0x20 โœจ

This is bit 5 complemented, where the bit positions are numbered 76543210 (the 6th bit as used in ISO numbered 87654321 -- BEWARE when comparing documents).

Receiving implementations MUST correctly process all Control Escape sequences ๐Ÿซถ

On reception, before FCS computation, each octet with a value less than hex 0x20 gets checked. If it's flagged in the receiving ACCM, it just gets removed, because it may have been inserted by intervening data communications equipment ๐Ÿงน Each Control Escape octet is removed too, and the octet after it is exclusive-or'd with hex 0x20. The exception is when that octet is the Flag Sequence, which aborts a frame ๐Ÿ›‘

A few examples should make this clearer. Escaped data goes over the link like this:

0x7e is encoded as 0x7d, 0x5e.    (Flag Sequence)
0x7d is encoded as 0x7d, 0x5d.    (Control Escape)
0x03 is encoded as 0x7d, 0x23.    (ETX)

Some modems with software flow control may intercept outgoing DC1 and DC3 while ignoring the 8th (parity) bit. Data like that goes over the link like this:

0x11 is encoded as 0x7d, 0x31.    (XON)
0x13 is encoded as 0x7d, 0x33.    (XOFF)
0x91 is encoded as 0x7d, 0xb1.    (XON with parity set)
0x93 is encoded as 0x7d, 0xb3.    (XOFF with parity set)

4.3. Invalid Frames ๐Ÿ™…โ€โ™€๏ธ

Frames that are too short (less than 4 octets when using the 16-bit FCS) get silently discarded. The same goes for frames that end with a Control Escape octet immediately followed by a closing Flag Sequence, and frames where octet-framing is violated (by sending a "0" stop bit where a "1" bit is expected). None of those count as an FCS error ๐Ÿ’€

4.4. Time Fill โณ

4.4.1. Octet-synchronous ๐Ÿ”„

There is no provision for inter-octet time fill.

The Flag Sequence MUST be transmitted during inter-frame time fill.

4.4.2. Asynchronous ๐Ÿ“ก

Inter-octet time fill MUST be accomplished by transmitting continuous "1" bits (mark-hold state) ๐Ÿ’ซ

Inter-frame time fill can be seen as extended inter-octet time fill. Doing this can save one octet per frame, which means less delay and more bandwidth ๐Ÿš€ It works because a Flag Sequence can be both a frame end and a frame begin. After any frame has been received, an idle receiver will always be in a frame begin state.

Robust transmitters should avoid using this trick over-zealously, because the price for less delay is less reliability ๐Ÿ˜ฌ Noisy links may cause the receiver to pick up 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 stuck onto the noise characters, causing an invalid frame (with high reliability) ๐Ÿ’ฅ

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. Transmitters SHOULD send an open Flag Sequence whenever "appreciable time" has passed since the prior closing Flag Sequence. The maximum value for "appreciable time" is likely no greater than the typing rate of a slow typist, about 1 second โŒจ๏ธ

4.5. Transmission Considerations ๐Ÿ“ถ

4.5.1. Octet-synchronous ๐Ÿงฉ

The definition of the various encodings and scrambling is the responsibility of the DTE/DCE equipment in use, and it's outside the scope of this specification ๐Ÿ™Œ

4.5.2. Asynchronous ๐Ÿ”ค

All octets are transmitted least significant bit first, with one start bit, eight bits of data, and one stop bit. There is no provision for seven bit asynchronous links ๐Ÿšซ

5. Bit-stuffed framing ๐Ÿงต

This chapter gives a quick summary of how HDLC-like framing works on bit-synchronous links ๐Ÿ’–

5.1. Flag Sequence ๐Ÿšฉ

The Flag Sequence marks the beginning or end of a frame, and it's used for frame synchronization. The bit stream gets checked one bit at a time for the binary sequence 01111110 (hex 0x7e) ๐Ÿ‘€

The "shared zero mode" Flag Sequence 011111101111110 SHOULD NOT be used. When it can't be avoided, that implementation MUST ensure the first Flag Sequence detected (the end of the frame) is promptly communicated to the link layer. Shared zero mode gets in the way of interoperability with bit-synchronous to asynchronous and bit-synchronous to octet-synchronous converters ๐Ÿ˜ค

5.2. Transparency ๐Ÿชž

After FCS computation, the transmitter checks the entire frame between the two Flag Sequences. A "0" bit is inserted after every run of five contiguous "1" bits (including the last 5 bits of the FCS), so a Flag Sequence never gets faked ๐ŸŽญ

On reception, before FCS computation, any "0" bit that directly follows five contiguous "1" bits gets discarded โœ‚๏ธ

5.3. Invalid Frames ๐Ÿšซ

Frames that are too short (less than 4 octets when using the 16-bit FCS), or that end with a sequence of more than six "1" bits, get silently discarded. They don't count as an FCS error ๐Ÿ’€

5.4. Time Fill โฐ

There is no provision for inter-octet time fill.

The Flag Sequence SHOULD be transmitted during inter-frame time fill. However, certain types of circuit-switched links require mark idle (continuous ones), especially the ones that calculate accounting based on periods of bit activity ๐Ÿ’ธ When mark idle is used on a bit-synchronous link, the implementation MUST ensure at least 15 consecutive "1" bits between Flags during the idle period, and that the Flag Sequence is always generated at the beginning of a frame after an idle period ๐Ÿง 

This differs from practice in ISO 3309, which allows 7 to 14 bit mark idle. ๐ŸŒˆ

5.5. Transmission Considerations โœจ

okay bestie, first things first: every octet gets sent least significant bit first ๐Ÿซถ no cap.

The encodings and scrambling are the DTE/DCE equipment's job, which is totally outside the scope of this spec ๐Ÿ’…

Real talk though: PPP doesn't care how the bit stream is represented underneath, but if nobody agrees on transmission standards it'll wreck interoperability just as much as missing data link standards ๐Ÿ˜ญ. At 56 Kbps through 2.0 Mbps, NRZ is the most widely available option right now, so it's recommended as a default ๐ŸŒธ.

When you're allowed to configure the encoding, NRZI is recommended as an alternative ๐Ÿฆ‹ because it's relatively immune to signal inversion configuration errors, and it MAY allow connection without an expensive DSU/CSU. Plot twist though: NRZI makes the missing x1 factor of the 16-bit FCS even worse ๐Ÿ’€. So one error in 215 goes undetected (instead of one in 216), and triple errors aren't detected at all.

Heads up: when NRZI is in use, it's recommended that the 32-bit FCS gets negotiated, because that one includes the x1 factor ๐Ÿšจ

At higher speeds of up to 45 Mbps, some implementors went with the ANSI High Speed Synchronous Interface [HSSI] ๐Ÿš€. The experience is still pretty limited, so implementors are encouraged to cooperate on choosing transmission encoding ๐ŸŒˆ.

6. Asynchronous to Synchronous Conversion ๐Ÿ”

Lowkey super common: there may be some asynchronous-to-synchronous converters (some are built into modems and cellular interfaces), which means one end is async PPP and the other end is sync ๐Ÿ™ˆ. The converter is responsible for doing all the stuffing conversions during operation.

To make this work, synchronous PPP implementations MUST always respond to the Async-Control-Character-Map Configuration Option with the LCP Configure-Ack ๐Ÿซถ. But bestie, accepting the option does not imply that the synchronous side will do any ACCM mapping. All of that octet mapping gets handled by the asynchronous-to-synchronous converter instead โœจ.

7. Additional LCP Configuration Options ๐ŸŽ€

The Configuration Option format and basic options are already defined for LCP [1] ๐Ÿ“š.

Up-to-date values of the LCP Option Type field are specified in the most recent "Assigned Numbers" RFC [10]. This document is all about the following value:

      2       Async-Control-Character-Map

7.1. Async-Control-Character-Map (ACCM) ๐Ÿงš

Description

This Configuration Option gives us a way to negotiate control character transparency on asynchronous links ๐ŸŒธ.

Each end of the asynchronous link keeps two Async-Control-Character-Maps. The receiving ACCM is 32 bits, but the sending ACCM can be up to 256 bits. That gives four distinct ACCMs in total, two in each direction of the link ๐Ÿ‘‘.

For asynchronous links, the default receiving ACCM is 0xffffffff. The default sending ACCM is 0xffffffff, plus the Control Escape and Flag Sequence characters themselves, plus whatever other outgoing characters are flagged (by prior configuration) as likely to be intercepted ๐Ÿ™ˆ. For other types of links, the default value is 0, since there's no need for mapping.

The default inclusion of all octets less than 0x20 lets all ASCII control characters [6] excluding DEL (Delete) get transparently communicated through all known data communications equipment โœจ.

The transmitter MAY also send octets with values in the range 0x40 through 0xff (except 0x5e) in Control Escape format ๐Ÿ’…. Since these octet values aren't negotiable, this doesn't solve the problem of receivers that can't handle all non-control characters. Also, since the technique doesn't affect the 8th bit, it doesn't solve problems for communications links that can only send 7-bit characters ๐Ÿ˜ญ.

Note that this specification differs in detail from later amendments, such as 3309:1991/Amendment 2 [3]. However, that "extended transparency" only gets applied by "prior agreement". Using the transparency methods in this specification counts as a prior agreement with respect to PPP ๐Ÿค.

For compatibility with 3309:1991/Amendment 2, the transmitter MAY escape DEL and ACCM equivalents with the 8th (most significant) bit set. No change is required in the receiving algorithm ๐Ÿซง.

Following ACCM negotiation, the transmitter SHOULD cease escaping DEL ๐Ÿ›‘.

However, it's rarely necessary to map all control characters, and often it's unnecessary to map any control characters at all. The Configuration Option is used to inform the peer which control characters MUST remain mapped when the peer sends them ๐Ÿ“ฃ.

The peer MAY still send any other octets in mapped format, if it's necessary because of constraints known to the peer. The peer SHOULD Configure-Nak with the logical union of the sets of mapped octets, so that when such octets are spuriously introduced they can be ignored on receipt ๐Ÿงน.

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     |               ACCM
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
             ACCM (cont)           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type

2

Length

6

ACCM

The ACCM field is four octets, and it indicates the set of control characters to be mapped. The map is sent most significant octet first ๐ŸŽฏ.

Each numbered bit corresponds to the octet of the same value. If the bit is cleared to zero, then that octet need not be mapped. If the bit is set to one, then that octet MUST remain mapped. For example, if bit 19 is set to zero, then the ASCII control character 19 (DC3, Control-S) MAY be sent in the clear ๐Ÿ™Œ.

Note: 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 ๐Ÿง 

The following Configurations Options are recommended:

High Speed links

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

Low Speed or Asynchronous links

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

B. Automatic Recognition of PPP Frames ๐Ÿ”

It's sometimes desirable to detect PPP frames, for example during a login sequence. The following octet sequences all begin valid PPP LCP frames:

   7e ff 03 c0 21
   7e ff 7d 23 c0 21
   7e 7d df 7d 23 c0 21

Note that the first two forms are not a valid username for Unix. However, only the third form generates a correctly checksummed PPP frame, whenever 03 and ff are taken as the control characters ETX and DEL without regard to parity (they are correct for an even parity link) and discarded ๐Ÿ™ƒ.

Many implementations deal with this by putting the interface into packet mode when one of the above username patterns is detected during login, without examining the initial PPP checksum. The initial incoming PPP frame is discarded, but a Configure-Request is sent immediately ๐Ÿš€.

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

The FCS was originally designed with hardware implementations in mind. A serial bit stream is transmitted on the wire, the FCS is calculated over the serial data as it goes out, and the complement of the resulting FCS is appended to the serial stream, followed by the Flag Sequence ๐Ÿ“ก.

The receiver has no way of determining that it has finished calculating the received FCS until it detects the Flag Sequence. So the FCS was designed so that a particular pattern results when the FCS operation passes over the complemented FCS. A good frame is indicated by this "good FCS" value ๐Ÿ’–.

C.1. FCS table generator ๐Ÿง

The following code creates the lookup table used to calculate the FCS-16.

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

   /*
    * The FCS-16 generator polynomial: x**0 + x**5 + x**12 + x**16.
    */
   #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("\t0x%04x", v & 0xFFFF);
           if (++b == 256)
               break;
           printf(",");
       }
       printf("\n};\n");
   }

C.2. 16-bit FCS Computation Method โœจ

okay so this is the table lookup trick for the 16-bit Frame Check Sequence ๐Ÿงš It works byte by byte as the data comes into the interface, so you don't have to wait for the whole frame. It's based on [7], [8], and [9], and honestly it's giving speed + elegance ๐Ÿ’…

/*
 * 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.
 */
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 PPPINITFCS16    0xffff  /* Initial FCS value */
#define PPPGOODFCS16    0xf0b8  /* Good final FCS value */

/*
 * Calculate a new fcs given the current fcs and the new data.
 */
u16 pppfcs16(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);
}

/*
 * How to use the fcs
 */
tryfcs16(cp, len)
    register unsigned char *cp;
    register int len;
{
    u16 trialfcs;

    /* add on output */
    trialfcs = pppfcs16( PPPINITFCS16, cp, len );
    trialfcs ^= 0xffff;                 /* complement */
    cp[len] = (trialfcs & 0x00ff);      /* least significant byte first */
    cp[len+1] = ((trialfcs >> 8) & 0x00ff);
    /* check on input */
    trialfcs = pppfcs16( PPPINITFCS16, cp, len + 2 );
    if ( trialfcs == PPPGOODFCS16 )
        printf("Good FCS\n");
}

C.3. 32-bit FCS Computation Method ๐ŸŒˆ

now the big sibling! ๐Ÿ‘‘ This one does the same table lookup thing, but for a 32-bit Frame Check Sequence, again as data arrives at the interface.

/*
 * The FCS-32 generator polynomial: x**0 + x**1 + x**2 + x**4 + x**5
 *                      + x**7 + x**8 + x**10 + x**11 + x**12 + x**16
 *                      + x**22 + x**23 + x**26 + x**32.
 */

/*
 * u32 represents an unsigned 32-bit number.  Adjust the typedef for
 * your hardware.
 */
typedef unsigned long u32;

static u32 fcstab_32[256] =
   {
   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
   0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
   0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
   0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
   0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
   0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
   0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
   0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
   0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
   0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
   0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
   0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
   0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
   0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
   0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
   0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
   0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
   0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
   0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
   0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
   0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
   0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
   0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
   0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
   0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
   0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
   0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
   0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
   0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
   0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
   0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
   0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
   0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
   0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
   0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
   0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
   0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
   0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
   0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
   0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
   0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
   0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
   0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
   };

#define PPPINITFCS32  0xffffffff   /* Initial FCS value */
#define PPPGOODFCS32  0xdebb20e3   /* Good final FCS value */
/*
 * Calculate a new FCS given the current FCS and the new data.
 */
u32 pppfcs32(fcs, cp, len)
    register u32 fcs;
    register unsigned char *cp;
    register int len;
    {
    ASSERT(sizeof (u32) == 4);
    ASSERT(((u32) -1) > 0);
    while (len--)
        fcs = (((fcs) >> 8) ^ fcstab_32[((fcs) ^ (*cp++)) & 0xff]);

    return (fcs);
    }

/*
 * How to use the fcs
 */
tryfcs32(cp, len)
    register unsigned char *cp;
    register int len;
{
    u32 trialfcs;

    /* add on output */
    trialfcs = pppfcs32( PPPINITFCS32, cp, len );
    trialfcs ^= 0xffffffff;             /* complement */
    cp[len] = (trialfcs & 0x00ff);      /* least significant byte first */
    cp[len+1] = ((trialfcs >>= 8) & 0x00ff);
    cp[len+2] = ((trialfcs >>= 8) & 0x00ff);
    cp[len+3] = ((trialfcs >> 8) & 0x00ff);

    /* check on input */
    trialfcs = pppfcs32( PPPINITFCS32, cp, len + 4 );
    if ( trialfcs == PPPGOODFCS32 )
        printf("Good FCS\n");
}

Security Considerations ๐Ÿ”ฅ

okay bestie, this part is serious ๐Ÿ˜ญ The Physical Layer Requirements section already mentioned that the link layer might not get told when the physical layer's connected state changes. That's a real problem, because it means you can end up leaning way too hard on the integrity and security of switching systems and administrations ๐Ÿ’€ An insertion attack might go totally unnoticed, and an attacker who can spoof the same calling identity might be able to dodge link authentication. Not okay. Stay alert, periodt ๐Ÿ™ˆ


References ๐Ÿ“š

[1]   Simpson, W., Editor, "The Point-to-Point Protocol (PPP)",
      STD 50, RFC 1661, Daydreamer, July 1994.

[2]   ISO/IEC 3309:1991(E), "Information Technology -
      Telecommunications and information exchange between systems -
      High-level data link control (HDLC) procedures - Frame
      structure", International Organization For
      Standardization, Fourth edition 1991-06-01.

[3]   ISO/IEC 3309:1991/Amd.2:1992(E), "Information Technology -
      Telecommunications and information exchange between systems -
      High-level data link control (HDLC) procedures - Frame
      structure - Amendment 2: Extended transparency options for
      start/stop transmission", International Organization For
      Standardization, 1992-01-15.

[4]   ISO/IEC 4335:1991(E), "Information Technology -
      Telecommunications and information exchange between systems -
      High-level data link control (HDLC) procedures - Elements of
      procedures", International Organization For Standardization,
      Fourth edition 1991-09-15.

[5]   Simpson, W., Editor, "PPP LCP Extensions", RFC 1570,
      Daydreamer, January 1994.

[6]   ANSI X3.4-1977, "American National Standard Code for
      Information Interchange", American National Standards
      Institute, 1977.

[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]  Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC
      1340, USC/Information Sciences Institute, July 1992.

Acknowledgements ๐Ÿซถ

this doc is the product of the Point-to-Point Protocol Working Group of the Internet Engineering Task Force (IETF) ๐ŸŒธ Comments should be sent to the ietf-ppp@merit.edu mailing list.

this spec is built on earlier RFCs, and lots of people contributed to those, so shoutouts to all of them ๐Ÿ’œ

the 32-bit FCS example code came from Karl Fox (Morning Star Technologies) โœจ

and a special thank you to Morning Star Technologies for the computing resources and network access support that made writing this spec possible ๐Ÿฆ‹


Chair's Address ๐ŸŽ€

the working group can be reached through the current chair:

Fred Baker
Advanced Computer Communications
315 Bollay Drive
Santa Barbara, California  93117

fbaker@acc.com

Editor's Address โœจ

okay so if you have questions about this memo, you can reach out to the editor directly ๐Ÿ’– bestie, here's where to find them:

William Allen Simpson
Daydreamer
Computer Systems Consulting Services
1384 Fontaine
Madison Heights, Michigan  48071

their emails are Bill.Simpson@um.cc.umich.edu and bsimpson@MorningStar.com ๐Ÿ“ฌ๐Ÿฆ‹

that's the whole editor's section, and honestly he's the one who wrote the book on this stuff ๐ŸŽ€

๐Ÿ“ฆ where this page comes from