RFC 1549

PPP in HDLC Framing

๐Ÿ“… published December 1993, from ietf

RFC 1549: PPP in HDLC Framing ๐ŸŽ€

Okay bestie, this one is PPP in HDLC Framing ๐Ÿ’– by W. Simpson, who is the Editor, with the second author line reading Daydreamer โœจ. It came out of the Network Working Group in December 1993, and it's on the Standards Track ๐Ÿฆ‹. The header has no Obsoletes or Updates line, so it doesn't replace or change any other RFC. Main character energy ๐Ÿ‘‘

Status of This Memo ๐Ÿ“œ

This is an Internet standards track protocol for the Internet community, and the authors are asking for discussion and suggestions for improvements ๐Ÿซถ. For the standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ’…. Distribution of this memo is unlimited ๐ŸŒˆ.

Abstract ๐Ÿฆ‹

PPP [1] gives us a standard way to send multi-protocol datagrams over point-to-point links โœจ.

This document explains how to use HDLC for framing PPP encapsulated packets ๐Ÿงš. It's the product of the Point-to-Point Protocol Working Group of the Internet Engineering Task Force (IETF) ๐Ÿ’œ. Comments go to ietf-ppp@ucdavis.edu ๐Ÿ“ฌ.

Table of Contents ๐ŸŒธ

1.   Introduction ..................................................2
1.1  Specification of Requirements .................................2
1.2  Terminology ...................................................3
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.   Asynchronous HDLC .............................................7
5.   Bit-synchronous HDLC ..........................................5
6.   Octet-synchronous HDLC ........................................12
APPENDIX A. Fast Frame Check Sequence (FCS) Implementation .........13
A.1  FCS Computation Method ........................................13
A.2  Fast FCS table generator ......................................15
SECURITY CONSIDERATIONS ............................................16
REFERENCES .........................................................17
ACKNOWLEDGEMENTS ...................................................17
CHAIR'S ADDRESS ....................................................18
EDITOR'S ADDRESS ...................................................18

1. Introduction ๐Ÿ’…

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 ๐Ÿ’–. PPP uses HDLC as the basis for its framing โœจ.

There's an escape mechanism so control data like XON/XOFF can travel transparently over the link ๐Ÿฆ‹. It also removes spurious control data that intervening hardware and software might inject into the link ๐Ÿ™ˆ.

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

1.1 Specification of Requirements ๐ŸŽ€

In this document, several words are used to signify the requirements of the specification ๐Ÿงš. They're often capitalized, so watch for them ๐Ÿ‘€.

  • MUST: This word, or the adjective "required", means the definition is an absolute requirement of the specification ๐Ÿ’….
  • MUST NOT: This phrase means the definition is an absolute prohibition of the specification ๐Ÿ’€.
  • SHOULD: This word, or the adjective "recommended", means there may be valid reasons in particular circumstances to ignore this item ๐ŸŒธ. But the full implications have to 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 still be prepared to interoperate with another implementation that does include it โœจ.

1.2 Terminology ๐Ÿฆ‹

This document frequently uses the following terms, and they're kind of the building blocks of everything else ๐Ÿงฑ:

  • datagram: The unit of transmission in the network layer (such as 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 ๐Ÿ’…. The exceptions are when data link layer fragmentation is being performed, or when multiple packets are incorporated into a single frame ๐Ÿ™ˆ.
  • peer: The other end of the point-to-point link ๐Ÿ‘‘.
  • silently discard: This means the implementation discards the packet without further processing ๐Ÿซ . The implementation SHOULD provide the capability of logging the error, including the contents of the silently discarded packet ๐Ÿ“. It SHOULD also record the event in a statistics counter ๐Ÿ“Š.

2. Physical Layer Requirements ๐ŸŒธ

PPP works across most DTE/DCE interfaces, like EIA RS-232-C, EIA RS-422, EIA RS-423, and CCITT V.35 ๐Ÿ”Œ. The only absolute requirement PPP imposes is a full-duplex circuit ๐Ÿ’œ. That circuit can be dedicated or circuit-switched, and it can run in asynchronous (start/stop), bit-synchronous, or octet-synchronous mode ๐ŸŒˆ. Whatever mode it's in, it has to 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 ๐Ÿ™….

PPP doesn't impose any restrictions on transmission rate, other than whatever the particular DTE/DCE interface already has ๐Ÿš€.

Control Signals ๐ŸŽ›๏ธ

PPP does not 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 ๐Ÿ”ฅ. In particular, such 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 ๐ŸŒฑ. It SHOULD NOT signal the Down event ๐Ÿ™ˆ.

Because signalling isn't required, the physical layer MAY be decoupled from the data link layer ๐Ÿฆ‹. That hides the transient details of the physical transport, which 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 ๐Ÿ—บ๏ธ. That's true 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 ๐Ÿฐ. However, 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 ๐Ÿ’ค. They reconnect when traffic resumes, without informing 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 considerable debate ๐Ÿ—ฃ๏ธ. It's based on the tariffs, call setup times, and security concerns of the installation ๐Ÿ’….

PPP uses the principles, terminology, and frame structure of the International Organization For Standardization's (ISO) 3309-1979 High-level Data Link Control (HDLC) frame structure [2] ๐Ÿงฉ. It's modified by "Addendum 1: Start/stop transmission" [3], which specifies modifications that allow HDLC to be used in asynchronous environments ๐ŸŒŠ.

The PPP control procedures use the definitions and Control field encodings standardized in ISO 4335-1979 [4] and ISO 4335-1979/Addendum 1-1979 [5] ๐Ÿ“š. PPP framing is also consistent with CCITT Recommendation X.25 LAPB [6] and CCITT Recommendation Q.922 [7] ๐Ÿ’ซ. That's because those are also based on HDLC ๐Ÿซถ.

The purpose of this specification is not to document what's already standardized in ISO 3309 ๐Ÿ™…โ€โ™€๏ธ. It assumes the reader is already familiar with HDLC, or has access to a copy of [2] or [6] ๐Ÿ“–. Instead, this document gives a concise summary and points out the specific options and features PPP uses โœจ.

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 ๐Ÿ”ข. This is contrary to standard ISO and CCITT practice, which orders bits as transmitted (network bit order) ๐Ÿ”„. Keep this in mind when comparing this document with the international standards documents ๐Ÿ‘€๐Ÿ’œ.

3.1. Frame Format โœจ

okay so here's the vibe of a PPP HDLC frame ๐Ÿ’… this diagram is the full outfit, minus the start/stop bits (for async links) and any bits or octets that get stuffed in for transparency. everything gets sent left to right, no skipping ๐Ÿซถ

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

The Protocol, Information and Padding fields get their full glow-up in the Point-to-Point Protocol Encapsulation [1] ๐ŸŽ€

Flag Sequence

The Flag Sequence marks where a frame starts or ends ๐Ÿšช it's always the binary sequence 01111110 (hexadecimal 0x7e) and it's basically the frame's bouncer.

Only one Flag Sequence is required between two frames. Two back-to-back Flag Sequences make an empty frame, which just gets ignored and doesn't count as a FCS error ๐Ÿ™ˆ

Address Field

The Address field is one octet, and it's always 11111111 (hexadecimal 0xff), the All-Stations address ๐ŸŒˆ PPP doesn't hand out individual station addresses, so everyone's just... everyone ๐Ÿ’œ

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 ๐Ÿฆ‹

Control Field

The Control field is also one octet, and it's 00000011 (hexadecimal 0x03), which is the Unnumbered Information (UI) command with the P/F bit set to zero โœจ other Control field values may be defined at a later time, or by prior agreement.

Frames with unrecognized Control field values SHOULD be silently discarded ๐Ÿ’€

Frame Check Sequence (FCS) Field

The FCS field is normally 16 bits (two octets), but other FCS lengths may be defined at a later time, or by prior agreement. It gets sent with the coefficient of the highest term first ๐Ÿงš

The FCS is calculated over all bits of the Address, Control, Protocol, Information and Padding fields. It doesn't count any start and stop bits (asynchronous), any bits (synchronous) or octets (asynchronous or synchronous) that got inserted for transparency, the Flag Sequences, or the FCS field itself ๐Ÿซถ

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

For more info on the FCS spec, check out ISO 3309 [2] or CCITT X.25 [6] ๐Ÿ“š

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 modifications to the basic HDLC frame structure ๐ŸŽ€ but don't worry, modified frames will always be clearly distinguishable from standard frames. no mix-ups, bestie ๐Ÿ’–

Address-and-Control-Field-Compression

With the default HDLC framing, the Address and Control fields hold 0xff and 0x03 respectively ๐ŸŒธ

When transmitting, compressed Address and Control fields are made by just leaving them out โœ‚๏ธ

On reception, the receiver looks at the first two octets to decompress things. If they're 0xff and 0x03, those are assumed to be the Address and Control fields. If not, it's assumed the fields were compressed and never got sent ๐Ÿ•ต๏ธโ€โ™€๏ธ

By definition, the first octet of a two octet Protocol field can never be 0xff, since it's not even ๐Ÿ™ˆ The Protocol field value 0x00ff is not allowed (reserved), so there's no ambiguity when Protocol-Field-Compression is enabled and the first Information field octet is 0x03 ๐Ÿ‘‘

When other Address or Control field values are in use, Address-and-Control-Field-Compression MUST NOT be negotiated. absolutely no compressing the outfit if the fit is different ๐Ÿšซ๐Ÿ’…


4. Asynchronous HDLC โœจ

This section is all about using HDLC over 8-bit asynchronous links ๐ŸŒˆ

Flag Sequence

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

Transparency

An octet stuffing procedure is used here ๐Ÿงธ The Control Escape octet is defined as binary 01111101 (hexadecimal 0x7d), and the bit positions are numbered 87654321 (not 76543210, BEWARE ๐Ÿ˜ญ).

Each end of the 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, two in each direction of the link ๐Ÿ’œ

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 known to get intercepted โœจ

After FCS computation, the transmitter goes through the whole frame between the two Flag Sequences. Each Flag Sequence, each Control Escape octet, and each octet below hexadecimal 0x20 that's flagged in the sending Async-Control-Character-Map gets swapped out for a two octet sequence: the Control Escape octet, then the original octet with bit 6 complemented (exclusive-or'd with hexadecimal 0x20) ๐Ÿ”ฅ

Before FCS computation, the receiver goes through the whole frame between the two Flag Sequences. Each octet below 0x20 gets checked. If it's flagged in the receiving Async-Control-Character-Map, it just gets removed, since it might have been slipped in by some intervening data communications equipment ๐Ÿ•ต๏ธโ€โ™€๏ธ For each Control Escape octet, that octet is removed too, and bit 6 of the following octet gets complemented, unless that following octet is the Flag Sequence ๐Ÿฆ‹

Note: The inclusion of all octets less than hexadecimal 0x20 allows all ASCII control characters [8] excluding DEL (Delete) to be transparently communicated through all known data communications equipment.

The transmitter may also send octets in the range 0x40 through 0xff (except 0x5e) in Control Escape format ๐ŸŽ€ but since those values aren't negotiable, this doesn't fix the problem for receivers that can't handle every non-control character. And since this technique doesn't touch the 8th bit, it doesn't help links that can only send 7-bit characters ๐Ÿ’€

A few examples make it way 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 gets sent 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 immediately followed by a closing Flag Sequence ๐Ÿ›‘

Time Fill

For asynchronous links, inter-octet and inter-frame time fill MUST be done by sending continuous "1" bits, which is the mark-hold state ๐ŸŒธ

Inter-frame time fill is basically 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 close and a frame begin. After receiving any frame, an idle receiver is always in a frame begin state ๐Ÿ‘‘

Robust transmitters should avoid overusing this trick, because the price of lower delay is lower reliability ๐Ÿ˜ฌ Noisy links can make the receiver 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 and becomes 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 opening Flag Sequence whenever "appreciable time" has passed since the prior closing Flag Sequence. The maximum "appreciable time" is likely no more than the typing rate of a slow typist, say 1 second โŒจ๏ธ๐Ÿข

Encoding

Every octet gets sent with one start bit, eight bits of data, and one stop bit ๐ŸŽ€ there's no provision for seven bit asynchronous links, so no 7-bit squad here ๐Ÿšซ

5. Bit-synchronous HDLC โœจ

okay so this section is all about how HDLC works on bit-synchronous links ๐Ÿฆ‹ let's get into it

Flag Sequence

the Flag Sequence marks where a frame starts or ends, and it's how the receiver keeps everything in sync ๐ŸŽ€ the bit stream gets checked one bit at a time for the pattern 01111110 (hexadecimal 0x7e) ๐Ÿ’–

the "shared zero mode" Flag Sequence 011111101111110 SHOULD NOT be used ๐Ÿ™ˆ if you can't avoid it, the implementation MUST make sure the first Flag Sequence it detects (the end of the frame) gets passed up to the link layer quickly โšก shared zero mode also makes things harder with synchronous-to-asynchronous converters, so it's giving interop drama ๐Ÿ’€

Transparency

the transmitter checks the whole frame sitting between the two Flag Sequences ๐Ÿ‘€ after every run of five contiguous 1 bits, it inserts a 0 bit so a Flag Sequence never gets faked out by accident ๐Ÿงš this includes the last 5 bits of the FCS โœจ

when receiving, any 0 bit that comes right after five contiguous 1 bits gets thrown away ๐Ÿซถ that's the un-stuffing part, and it's literally the mirror of what the sender did ๐Ÿ’…

since the Control Escape octet-stuffing method isn't used here, the default receiving and sending Async-Control-Character-Maps are 0 ๐ŸŒธ

there might be some synchronous-to-asynchronous converters floating around (some are built right into modems ๐Ÿ“ ) on point-to-point links. so you could end up with a synchronous PPP implementation on one end and an asynchronous one on the other ๐Ÿ˜ญ in that case, the converter is the one responsible for doing all the mapping conversions while things are running ๐Ÿ‘‘

to make that work, bit-synchronous PPP implementations MUST always respond to the Async-Control-Character-Map Configuration Option with an LCP Configure-Ack ๐Ÿ’œ BUT (and this part is important bestie ๐Ÿšจ) accepting that option does NOT mean the bit-synchronous side is actually doing any octet mapping ๐Ÿ™…โ€โ™€๏ธ all of that octet mapping is handled by the asynchronous-to-synchronous converter, full stop ๐ŸŒˆ

Aborting a Transmission

a sequence of more than six 1 bits means the frame is invalid ๐Ÿ’€ it gets ignored, and it does NOT count as an FCS error (no cap, that's a sneaky one ๐Ÿ‘€)

Inter-frame Time Fill

on bit-synchronous links, the Flag Sequence SHOULD be sent during inter-frame time fill ๐ŸŒธ there's no provision for inter-octet time fill at all, so don't go looking for it ๐Ÿ™ƒ

mark idle (continuous ones) SHOULD NOT be used for inter-frame fill ๐Ÿ™ˆ BUT, lowkey, some circuit-switched links need mark idle anyway, especially the ones that calculate accounting based on periods of bit activity ๐Ÿ’ธ if you do use mark idle on a bit-synchronous link, the implementation MUST make sure there are at least 15 consecutive 1 bits between Flags during the idle period ๐Ÿ”ฅ and the Flag Sequence has to always be generated at the start of a frame after an idle period ๐Ÿซถ

Encoding

the definition of various encodings and scrambling belongs to the DTE/DCE equipment in use, so it's totally outside the scope of this spec ๐Ÿงš

PPP will work no matter how the bit stream is represented underneath ๐Ÿ’… but, ngl, if nobody agrees on transmission standards, interop gets messy just like it does without data link standards ๐Ÿ˜ญ at speeds of 56 Kbps through 2.0 Mbps, NRZ is the most widely available right now, so on that basis it is recommended as a default ๐ŸŽ€

when you're allowed to configure the encoding, NRZI is recommended as an alternative โœจ it's pretty immune to signal inversion configuration errors, and it MAY let you connect without an expensive DSU/CSU ๐Ÿค‘ the tea though: NRZI kills the (1 + x) factor of the 16-bit FCS, so one error in 215 goes undetected (instead of one in 216), and triple errors aren't detected at all ๐Ÿ˜ฑ so when NRZI is in use, it is recommended that the 32-bit FCS be negotiated, because that one doesn't include the (1 + x) factor ๐Ÿ’–

at higher speeds of up to 45 Mbps, some implementors have gone with the ANSI High Speed Synchronous Interface [HSSI] ๐Ÿš€ the experience is still pretty limited, but implementors are encouraged to work together on picking transmission encoding ๐Ÿซถ๐ŸŒˆ


6. Octet-synchronous HDLC ๐Ÿฆ‹

this section covers HDLC on octet-synchronous links, like SONET and optionally ISDN B or H channels ๐Ÿ’…

even though the bit rate is synchronous, there's NO bit-stuffing here ๐Ÿ™…โ€โ™€๏ธ instead it uses the octet-stuffing feature from 8-bit asynchronous HDLC โœจ

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 (hexadecimal 0x7e) ๐Ÿ’–

Transparency

octet stuffing is the move here ๐Ÿงš the Control Escape octet is defined as binary 01111101 (hexadecimal 0x7d) ๐ŸŒธ

the octet stuffing procedure is described in "Asynchronous HDLC" above (go check Section 4 if you forgot ๐Ÿ“š)

the sending and receiving implementations only need to escape the Flag Sequence and Control Escape octets ๐Ÿ‘€ no extra escaping, we're keeping it lean ๐Ÿ’…

considerations about using converters are described in "Bit-synchronous HDLC" above ๐Ÿซถ

Aborting a Transmission

frames can be aborted by sending a Control Escape octet immediately followed by a closing Flag Sequence ๐Ÿ’€ the frame before that gets ignored and does NOT count as an FCS error ๐Ÿ™ˆ

Inter-frame Time Fill

the Flag Sequence MUST be sent during inter-frame time fill ๐Ÿ”ฅ there's no provision for inter-octet time fill, same as before ๐Ÿ˜ญ

Encoding

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


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

okay the FCS was originally designed with hardware in mind ๐Ÿ”ง a serial bit stream goes out on the wire, the FCS is calculated over the serial data as it leaves, and then the complement of that FCS gets tacked onto the end of the stream, followed by the Flag Sequence ๐ŸŽ€

the receiver has no way to know it's done calculating the received FCS until it spots the Flag Sequence ๐Ÿ‘€ so the FCS was designed so that a particular pattern shows up when the FCS operation runs over the complemented FCS โœจ that's the "good FCS" value, and it's how you know a frame is good ๐Ÿ’–

A.1 FCS Computation Method

this code gives you a table lookup computation for calculating the Frame Check Sequence as data arrives at the interface ๐Ÿง  it's based on [9], [10], and [11] ๐Ÿ“š 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 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 FCS0);
}

A.2. Fast FCS table generator ๐Ÿง

this code makes 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;0);
    printf("static u16 fcstab[256] = {");
    for (b = 0; ; ) {
        if (b % 8 == 0)
            printf("0);

        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("0;0);
}

Security Considerations ๐Ÿšจ

okay bestie, this part is SERIOUS ๐Ÿ˜ค as noted in the Physical Layer Requirements section, the link layer might not be informed when the connected state of the physical layer changes ๐Ÿ˜ฑ this can lead to possible security lapses because of over-reliance on the integrity and security of switching systems and administrations ๐Ÿ’€ an insertion attack might go undetected ๐Ÿ™€ and an attacker who can spoof the same calling identity might be able to avoid link authentication ๐Ÿ‘ป we are not okay, let's be careful out there ๐Ÿ’œ

References โœจ

okay bestie, here's the reading list ๐Ÿ“š these are the docs the spec leans on, so i'm keeping every detail exactly as written ๐Ÿ’…

  • [1] Simpson, W., Editor, "The Point-to-Point Protocol (PPP)", RFC 1548, December 1993
  • [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, Proposed Draft International Standard ISO 3309-1991/PDAD1, "Information processing systems - Data communication - High-level data link control procedures - Frame structure - Addendum 1: Start/stop transmission", 1991.
  • [4] International Organization For Standardization, ISO Standard 4335-1979, "Data communication - High-level data link control procedures - Elements of procedures", 1979.
  • [5] International Organization For Standardization, ISO Standard 4335-1979/Addendum 1, "Data communication - High-level data link control procedures - Elements of procedures - Addendum 1", 1979.
  • [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] International Telegraph and Telephone Consultative Committee, CCITT Recommendation Q.922, "ISDN Data Link Layer Specification for Frame Mode Bearer Services", April 1991.
  • [8] American National Standards Institute, ANSI X3.4-1977, "American National Standard Code for Information Interchange", 1977.
  • [9] Perez, "Byte-wise CRC Calculations", IEEE Micro, June, 1983.
  • [10] Morse, G., "Calculating CRC's by Bits and Bytes", Byte, September 1986.
  • [11] LeVan, J., "A Fast CRC", Byte, November 1987.

Acknowledgments ๐Ÿซถ

Okay so the vibe here is "we didn't do this alone!" ๐Ÿ’œ This specification is based on previous RFCs, where many contributions have been acknowleged.

Extra implementation detail for this version came from Fred Baker (ACC), Craig Fox (NSC), and Phil Karn (Qualcomm) ๐Ÿ™Œ

And a huge shoutout to Morning Star Technologies for providing computing resources and network access support for writing this specification โœจ


Chair's Address ๐ŸŽ€

If you need to reach the working group, the person to ping is the current chair ๐Ÿ’–

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

   EMail: fbaker@acc.com

Editor's Address ๐Ÿฆ‹

Questions about this memo can also go straight to the editor ๐Ÿงš

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

   EMail: Bill.Simpson@um.cc.umich.edu

And that's the whole spec, bestie!! ๐ŸŒˆ๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from