SLIP — Serial Line IP

The simplest framing protocol that actually works. One byte means “end of packet,” and one more byte rescues that meaning when it shows up inside your data. That’s the whole protocol — eight lines of C, RFC 1055 in 1988.

The trick in one paragraph

SLIP picks one byte — 0xC0, named END — and declares that whenever the receiver sees it, the current frame is over. To send a payload that itself contains 0xC0, you have to disguise it. SLIP uses one more byte, 0xDB (ESC), meaning “the next byte tells you what was really here.” ESC 0xDC means “a literal 0xC0,” and ESC 0xDD means “a literal 0xDB.” The cost: every C0 or DB in the data turns into two bytes on the wire. The win: a receiver that joins mid-stream just waits for the next C0 and resyncs — no header parsing, no length fields, no state.

Payload bytes

Hex bytes, any reasonable separator: 01 02 C0, 0x01,0x02,0xC0, 0102C0

SLIP encoding

END0xC0 frame delimiter ESC sequence — literal C0 or DB in the payload regular payload byte (passes through unchanged)

Cost

Why every byte except C0 and DB is free

Two bytes are reserved as “control” bytes. Everything else — the other 254 values — passes through as-is. So the worst case is a payload made entirely of C0 or DB bytes, where SLIP doubles your size. For typical IP packets, where these two specific values are rare, overhead is well under 1%.

On the wire: three frames back-to-back

Frames are simply concatenated, with a single END between each. (RFC 1055 also lets you send a END at the start of each frame — if line noise scrambled the previous one, the lone END turns into a harmless empty frame, and the real one stays intact.) A receiver synchronizes by discarding everything until it sees the first END, then decodes between successive END bytes.

Things to try

  1. Click Plain ASCII. None of the payload bytes match C0 or DB, so encoding adds exactly two bytes total — the leading and trailing END markers. Overhead: 2 bytes regardless of payload length.
  2. Click One C0 in the middle. Watch the single C0 turn into a gold ESC sequence on the wire. The receiver sees DB DC and reconstructs the original C0; the actual frame-ending C0 at the end is unambiguous.
  3. Click Worst case (all C0). Every payload byte costs two bytes on the wire. SLIP is at its 2× expansion factor — the same reason length-prefixed framings exist when the alphabet has many reserved values.
  4. Click Empty packet. With no payload at all, the wire shows just C0 C0. Many SLIP implementations skip empty frames silently, which is exactly why an extra leading END after noise is harmless.
  5. Type DB DC as the payload. The encoder must escape both bytes: the DB becomes DB DD, then the literal DC passes through, then nothing else — so the encoded frame contains C0 DB DD DC C0. The decoder, walking left-to-right, sees DB, swallows the next byte and emits DB, then sees DC and emits DC. No ambiguity.
What SLIP doesn’t do (and what came after)

SLIP has no addressing, no length, no checksum, no negotiation, and no compression. It simply frames a stream of bytes — both endpoints must already agree on what those bytes mean (e.g. that they’re an IP packet). RFC 1055 explicitly says “there is no ‘standard’ specification of SLIP,” just a description of the de facto convention.

PPP (RFC 1661, 1994) replaces SLIP in essentially every modern setting: it adds a real header with protocol type, an HDLC-style FCS for error detection, and link-layer negotiation. COBS (1997) tackles the same framing problem from a different angle — bounded constant overhead, instead of variable per-byte stuffing.