Skip to main content

Pure-Python, zero-dependency TCP/IP stack — Ethernet through RFC 9293 TCP — running in user space on a TAP/TUN interface, with a Berkeley-sockets API.

Project description

PyTCP

Pure-Python, zero-dependency TCP/IP stack — Ethernet through RFC 9293 TCP — running in user space on a TAP/TUN interface, with a Berkeley-sockets API.

from pytcp import socket, stack

What it is

A full, RFC-grounded TCP/IP stack implemented entirely in Python: Ethernet II / 802.3 (LLC/SNAP), ARP, IPv4 / IPv6 (with Hop-by-Hop / Destination-Options / Routing / Fragment extension headers), ICMPv4 / ICMPv6 (incl. Neighbor Discovery, MLDv2 with MLDv1 fallback, and IGMP IPv4 multicast group membership), DHCPv4 and DHCPv6 clients, UDP, and a RFC 9293 TCP with a real FSM, congestion control (Reno / NewReno / CUBIC), SACK / timestamps / window-scaling, and a BSD-sockets facade. It runs on a TAP/TUN interface in user space — no kernel module, no privileged data path.

The project's north star is feature-equivalence with the Linux host network stack: where an RFC is unambiguous PyTCP follows it, and where it is silent or offers a menu PyTCP picks the Linux choice. Per-RFC adherence is audited under docs/rfc/.

The three distributions

PyTCP is strictly layered into three independently-published dists (one invariant: project folder == import name):

Distribution Import Role
PyTCP-net_addr net_addr Address value types (IPv4/IPv6/MAC, networks, masks, wildcards, interface-addresses).
PyTCP-net_proto net_proto Protocol packet parse / assemble / validate.
PyTCP pytcp The running stack: subsystems/threads, sockets, FIB, ARP/ND caches, RX/TX rings.

Installing PyTCP pulls the other two automatically (lockstep version pin).

Runtime architecture

TAP/TUN fd ─> RxRing ─> PacketHandler (per protocol, RX) ─> Socket queues / ARP+ND caches / fragment store
           <─ TxRing <─ PacketHandler (per protocol, TX) <─ Socket send / ND / DHCP / ACD
  • Subsystem base — every background service (RX/TX rings, neighbor caches, timer, DHCPv4 / DHCPv6 clients, link-local / ACD) extends Subsystem and runs its own thread with an event-driven loop.
  • Packet handlers — RX and TX paths are composed from per-protocol sub-handlers (packet_handler__<proto>__<rx|tx>.py). Every branch bumps a per-protocol stat counter for observability.
  • Event-driven timer — a heap-based deadline scheduler (no polling tick); subsystems register deadlines and are woken on the nearest one.
  • Per-interface model — a PacketHandler is an interface. A multi-homed host runs one handler per interface; global tables (routing FIB, socket table, neighbor caches) are shared and lock-guarded.

Free-threaded (no-GIL) safety

Per-interface state is partitioned (single-writer TX ring hand-off); the shared global tables (RouteTable, SocketTable, InterfaceTable) guard their compound (check-then-act) operations with a small threading.Lock and hand readers consistent snapshots. Single built-in dict/list ops are left lock-free (individually atomic).

Control-plane APIs (the Phase-3 kernel/userspace boundary)

Consumers talk to the stack only through sanctioned surfaces — never by reaching into runtime internals — mirroring how a Linux process talks to its kernel:

API Linux equivalent
pytcp.socket — BSD socket() factory + methods (TCP / UDP / raw / AF_PACKET) socket(2)
pytcp.stack.sysctl — runtime-tunable policy registry /proc/sys/net/
pytcp.stack.link — per-interface MAC / MTU / state / counters ip link / RTM_*LINK
pytcp.stack.address — assign / remove IPv4 / IPv6 host addresses ip addr / RTM_*ADDR
pytcp.stack.route — add / remove / list routes (FIB); Route / RouteProtocol / RouteScope ip route / RTM_*ROUTE
pytcp.stack.neighbor — static ARP / ND entries, cache flush ip neighbor / RTM_*NEIGH
read-only snapshots (route table, neighbor cache, socket list, counters) /proc/net/*, ss

Lifecycle

stack.init(...) builds the singletons, stack.add_interface(...) / stack.remove_interface(...) attach / detach interfaces at runtime (RTNETLINK RTM_NEWLINK / RTM_DELLINK semantics, including the address / route / neighbor / session teardown cascade), stack.start() spawns the subsystem threads, and stack.stop() winds them down. A stack can init() with zero interfaces and gain them later — the daemon / multi-homed shape.

Sockets

pytcp.socket mirrors the stdlib socket module: a socket(...) factory returns TcpSocket / UdpSocket / RawSocket / PacketSocket, with bind / listen / accept / connect / send / recv / close, fileno() + eventfd for selectors integration, blocking & non-blocking modes, errno-mapped OSError, getaddrinfo, common setsockopt options, IPv4/IPv6 multicast group membership and source-filter options (IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP, IPV6_JOIN_GROUP, …), and an IP_RECVERR / MSG_ERRQUEUE error queue. Stdlib-parity constants (AF_INET, SOCK_STREAM, IP_*, SO_*, MSG_*) are exposed as bare module names backed by IntEnums.

Install

pip install PyTCP

Brings in PyTCP-net_proto and PyTCP-net_addr — no other runtime dependencies (the whole stack is stdlib-only). Fully typed (ships py.typed, PEP 561); strict-mypy clean.

Running the stack

Running needs a TAP/TUN interface (root for interface / bridge setup):

make tap7        # create the tap7 interface (sudo)
make bridge      # set up the bridge (sudo)
make run         # run the stack on tap7
make run_multi   # multi-interface demo

PyTCP is consumed as a library through the stack lifecycle API and the pytcp.socket BSD-sockets API. See examples/examples/stack.py is the complete runnable reference (TAP/TUN open, stack.init(...), multi-interface bind, runtime interface removal on SIGUSR1).

Requirements

Python 3.14+, Linux (TAP/TUN), POSIX.

Current state (3.0.6)

  • ~175 source modules; the pytcp suite runs ~4,000 unit + integration tests (the full repo suite, across all three packages + examples, is ~12,400). Lint clean (codespell + isort + black + flake8 + mypy strict + pylint).
  • Host-stack feature-complete (North Star Phase 1). Phase-2 router/forwarding sits behind the forward_or_deliver seam as a stub. Authoring contracts in .claude/rules/pytcp.md; per-RFC adherence in docs/rfc/.

License

GPL-3.0-or-later. PyTCP by Sebastian Majewski.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytcp-3.0.6.tar.gz (505.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytcp-3.0.6-py3-none-any.whl (669.3 kB view details)

Uploaded Python 3

File details

Details for the file pytcp-3.0.6.tar.gz.

File metadata

  • Download URL: pytcp-3.0.6.tar.gz
  • Upload date:
  • Size: 505.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pytcp-3.0.6.tar.gz
Algorithm Hash digest
SHA256 ea0297f2e87e8d9ee50499d81f11440388385c144f5e97ba6b0e67c76b6b3d51
MD5 799c269d3d27f71bcb62d5ab2205c8bf
BLAKE2b-256 e5d3f5cf45974dc0e298d206345f2357955ed65fcaae40d0298f49885629974a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytcp-3.0.6.tar.gz:

Publisher: publish.yml on ccie18643/PyTCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytcp-3.0.6-py3-none-any.whl.

File metadata

  • Download URL: pytcp-3.0.6-py3-none-any.whl
  • Upload date:
  • Size: 669.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pytcp-3.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 1bb9a5e47e5aeb8506b2e535a5a1badcaf7980837002c77e688eb1e2fc87bf44
MD5 7c301dc7ab2f23cf039fe62a242b3972
BLAKE2b-256 872dd9e7ea6e99c27071bb1c9771d7ade692df8532920e1144af8fbde4d94a48

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytcp-3.0.6-py3-none-any.whl:

Publisher: publish.yml on ccie18643/PyTCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page