Skip to main content

ppp-fcs16-pure

Zero-dependency pure-Python PPP Frame Check Sequence (FCS-16) per IETF RFC 1662 §7.1 — serverless-compatible.

version python license deps tests

Quick Start

pip install git+https://github.com/prasad-a-abhishek/ppp-fcs16-pure.git
>>> from ppp_fcs16_pure import ppp_fcs16, ppp_fcs16_verify
>>> hex(ppp_fcs16(b"123456789"))    # RFC 1662 Appendix C.3 canonical check
'0x906e'
>>> hex(ppp_fcs16(b""))             # empty frame
'0x0'
>>> ppp_fcs16_verify(b"123456789", 0x906E)
True

⚡ Performance & Benchmarks

50-iteration head-to-head (5 runs × 10 workload profiles) of ppp_fcs16 against the RFC 1662 Appendix C.1 reference C implementation (gcc -O2):

Payload size Python mean (µs) Python P95 (µs) C mean (µs) Ratio (py/c) Peak mem (KB)
16 13.24 12.71 299.11 0.04x 0.11
64 41.05 41.25 245.98 0.17x 0.11
256 158.90 160.88 248.47 0.64x 0.11
1500 843.56 848.17 219.40 3.84x 0.11
4096 2103.19 2123.21 213.14 9.87x 0.11
8192 3843.30 3853.38 234.47 16.39x 0.11

Honest trade-off disclosure: The C reference times include subprocess fork/exec overhead per iteration (~200µs). For an in-process C comparison (ctypes/cffi), the C side would be ~10× faster still. The pure-Python implementation is table-driven (256-entry lookup), so it is ~30× faster than a naive bit-serial impl on realistic frames. For typical PPP frame sizes (≤1500B), ppp_fcs16 is ~0.1–4 ms per call — adequate for any realistic network-function workload.

The crcmod alternative (a C-extension CRC library) would be ~2-5× faster than our pure-Python, but requires a C build toolchain at install time and fails in AWS Lambda, GCP Cloud Functions, Cloudflare Workers WASM, and Pyodide. The whole purpose of ppp-fcs16-pure is to be 100% serverless-compatible.

Reproduce locally:

python3 benchmarks/run_benchmark.py

Why ppp-fcs16-pure?

PPP-FCS-16 is the FCS used by every RFC 1662 PPP/HDLC link — Cisco HDLC WAN encapsulation, sync serial PPP, dial-up modems, GSM/LTE control-plane signalling, and many embedded serial protocols. Real peer devices REJECT frames whose FCS does not match their own computation — there is no negotiation, no fallback. A developer writing a serverless network function that emits or validates HDLC frames needs the exact PPP-FCS-16 algorithm.

What is currently available (and why each is wrong)

Option Failure mode
crcmod Requires building a C-extension. Fails in AWS Lambda, GCP Cloud Functions, Cloudflare Workers WASM, Pyodide, AWS Greengrass. Cold-start cost + native build chain = serverless-incompatible.
python-can 30+ dep serial-bus toolchain (SocketCAN, Kvaser, PCAN, IXXAT). Cannot be imported in a Lambda; pulls in pyserial, wrapt, pywin32, etc.
crc16 (PyPI) Implements CRC-16 CCITT (non-reflected 0x1021). Wrong FCS — peer device will reject every frame.
pysctp / pycrc32c / crc32c SCTP-CRC32C / IEEE-CRC32C / 32-bit checksums. Wrong polynomial width.
Hand-rolled crcmod-derived table Quietly diverges on init, xorout, or byte order — produces "almost-right" FCS that fails only on real equipment.
binascii.crc_hqx (XMODEM/CCITT) Same non-reflected 0x1021 issue.
Calling out to pppd -f via subprocess 100ms+ fork overhead per frame, plus requires the pppd binary present in the deployment image.

What ppp-fcs16-pure delivers

  • One ~18-line pure-Python core (src/ppp_fcs16_pure/core.py).
  • Byte-exact RFC 1662 Appendix C reference — verified Python↔C gcc -O2 cross-check on 1005+ vectors (5 canonical + 1000 random + 256 single-byte).
  • Zero runtime dependencies — works in any Python 3.7+ runtime, including WASM (Pyodide), Lambda, Cloudflare Workers, GCP Cloud Functions.
  • Constant-time verify helper — safe for use in protocol parsers where timing oracles matter.
  • 2551 pytest cases — including the canonical "123456789" → 0x906E check, the 0x0F47 residue, streaming equivalence, and full RFC 1662 Appendix C conformance.

Trade-offs

  • We pre-compute the 256-entry table at module import (~50µs). On tiny inputs (≤16 bytes) this is slower than a naive bit-serial implementation, but on realistic frames (≥64 bytes) it is ~30× faster.
  • We do not implement CRC-32/CRC-32C/CRC-CCITT (those are different polynomials). See crc32-pure (shipped) and other variants.

Key Features

  • Zero dependencies: pure Python 3.7+ standard library only.
  • Byte-exact RFC 1662 Appendix C.1: Python↔C gcc -O2 cross-checked on the canonical "123456789" → 0x906E check and 1005+ vectors.
  • Streaming API: ppp_fcs16(data, seed=...) exposes the intermediate register so chunked frame processing matches one-shot computation.
  • Constant-time verify: ppp_fcs16_verify(data, expected) returns True/False without leaking timing information about the mismatch position.
  • Total over arbitrary input: passing None, ints, or non-bytes raises a structured TypeError (Invariant 21). Never ValueError, never AttributeError, never silent garbage.
  • 2551 pytest cases: canonical vectors, length sweep, byte-variation, streaming equivalence, determinism, exception safety, residue check, C-reference cross-check, stdlib purity, LOC budget.

API Reference

ppp_fcs16(data: bytes, seed: int = 0xFFFF) -> int

Compute PPP-FCS-16 over data per RFC 1662 §7.1. Returns the 16-bit unsigned FCS value (matches pppd / Cisco HDLC reference output).

Parameters:

  • data: bytes, bytearray, or memoryview. Anything else raises TypeError.
  • seed: optional 16-bit initial register value (default 0xFFFF). Used by the streaming helper to continue a prior computation.
>>> from ppp_fcs16_pure import ppp_fcs16
>>> ppp_fcs16(b"123456789")
36974  # = 0x906E
>>> ppp_fcs16(b"")
0
>>> # Streaming: continue from a prior chunk
>>> state = ppp_fcs16(b"1234")  # full FCS of first chunk
>>> ppp_fcs16(b"56789", seed=state ^ 0xFFFF)  # continue, round-trip xorout
36974

ppp_fcs16_verify(data: bytes, expected: int) -> bool

Verify that expected is the FCS-16 of data in constant time. Returns False on mismatch (does NOT raise on bad frames — protocol parsers expect this). Raises TypeError on non-bytes data or non-int expected. Raises ValueError if expected is outside [0, 0xFFFF].

>>> from ppp_fcs16_pure import ppp_fcs16_verify
>>> ppp_fcs16_verify(b"123456789", 0x906E)
True
>>> ppp_fcs16_verify(b"123456789", 0x0000)
False

CLI

ppp-fcs16-pure ships as a library, not a CLI. For a one-shot FCS computation, use Python:

python3 -c "from ppp_fcs16_pure import ppp_fcs16; print(hex(ppp_fcs16(b'123456789')))"
# -> 0x906e

Test & Verify

git clone https://github.com/prasad-a-abhishek/ppp-fcs16-pure.git
cd ppp-fcs16-pure
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest -v

Expected: 2551 items collected, 2551 passing, 0 failing in ~1s.

The test suite cross-checks Python output against the RFC 1662 Appendix C.1 reference C implementation (compiled at test time with gcc -O2). If gcc is unavailable, those tests skip cleanly without breaking the run.

License

Released under CC0 1.0 Universal (Public Domain Dedication). Author: Prasad A Abhishek (prasad.a.abhishek@gmail.com).

The PPP-FCS-16 algorithm itself is standardized in IETF RFC 1662 (William Simpson, 1994) and is freely implementable; this Python port is dedicated to the public domain.

Metadata

Release files for ppp-fcs16-pure 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ppp-fcs16-pure 0.1.0
File Size Uploaded
ppp_fcs16_pure-0.1.0.tar.gz 36.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ppp-fcs16-pure 0.1.0
File Interpreter ABI Platform
ppp_fcs16_pure-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.2 kB

Release files / ppp_fcs16_pure-0.1.0.tar.gz

Download URL ppp_fcs16_pure-0.1.0.tar.gz
Size 36.3 kB
Tags Source
SHA-256 checksum
How to use checksums
2c110721cac7b4dbde5715deac44ac5ec6246bf20a6b6ce11ee354fa5695a5c0
BLAKE2b-256 checksum
How to use checksums
2eba55e415a7e48ac25cc70fa7b444cf1877c1ce58b13a3c5233a11c5be1608c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / ppp_fcs16_pure-0.1.0-py3-none-any.whl

Download URL ppp_fcs16_pure-0.1.0-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3eec2380decaf7336331a9baddffe121a138077677f0bda26aeb0b003c26e63f
BLAKE2b-256 checksum
How to use checksums
8cc7cb04f6365cfb7ee456cb7697154cee44971bcf1d4b2a682ce82fdea5dc5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page