Boots cable modems from MySQL tables, in six Rust processes.

docsis_server is an integrated provisioning server for DOCSIS cable plants. Working alongside a CMTS, it boots cable modems and the customer equipment behind them: it answers DHCPv4 and DHCPv6, hands each modem its configuration file over TFTP, serves time-of-day, and collects syslog from the plant. All of it is driven from MySQL tables that an existing provisioning or billing system can write to directly.

View on GitHub Get started
docsis_server — project data MMQR-02 Rev A Sheet 02 of 06
01 Language Rust Edition 2024 · unsafe forbidden throughout · clean under clippy::pedantic
02 Licence GPL v2+ GNU General Public License, version 2 or later
03 Database MySQL 8.x, or MariaDB 10.11 or newer · InnoDB · utf8mb4
04 Heritage 20 years A port of a C server that ran a production cable plant for two decades
05 Processes Six One per service, each with its own PID file and log
06 Console docsis_admin A separate download; needs nothing from this server but a MySQL account

Repository: github.com/mmqr-developer/docsis_server · The four DOCSIS projects also have a site of their own at docsis-admin.com.

02 · Services

Six processes, one per port

A crash in one does not take the others down, and a supervisor restarts it.

01 DHCPv4 67 Provisions modems and customer equipment
02 DHCPv6 547 Customer equipment only, with prefix delegation
03 TFTP 69 Serves static and generated configuration files
04 Time 37 RFC 868 time-of-day, which DOCSIS modems require
05 Syslog 514 Collects device syslog into daily tables
06 Background Drains deferred writes, keeps the connection warm, takes remote commands
03 · What it does

From power-on to online

01 Provisions from power-on The modem broadcasts a DHCPDISCOVER, the CMTS relays it, and the server decides from the relay's address and VLAN which pool the modem belongs to, allocates a management address, and tells it where to fetch its configuration. The modem downloads that file over TFTP and comes online.
02 Tells devices apart An embedded telephony adapter, a set-top box and a customer's laptop each belong on a different network with different options. The server classifies them from the DHCP vendor options the device sends and from per-modem flags, and draws each from its own pool.
03 Assembles configuration files A modem can be given a static file from disk, or a list of numbered fragments — one for the address count, one for the downstream flow, one for the upstream flow, one for encryption — which the server concatenates, signs with both DOCSIS message integrity checks and serves from memory. Changing a service tier is then an edit to one row.
04 Keeps addressing stable A cable plant is treated as static by default: a RELEASE or a DECLINE is logged and the client keeps its address, because support calls, port forwards and customer bookmarks all depend on it not moving. An IPv4 lease can be pinned outright. On IPv6 a subscriber gets an address for their router and a delegated prefix for the network behind it, stable across renewals.
05 Allocates safely Address allocation runs inside a transaction with SELECT ... FOR UPDATE over the candidate range, so two servers sharing a database cannot hand out the same address. Deadlocks are retried; a lost race looks elsewhere rather than declaring the pool full.
06 Survives a database outage Connections are rebuilt rather than a failure latched. Requests are refused while the database is unreachable instead of answered from stale state, and deferred writes are queued to replay afterwards. An optional read-only backup server takes over reads.
07 Degrades under load Above a configurable request rate the DHCP and TFTP services switch to in-memory caches, optionally prebuilt by a separate generator and handed over through /dev/shm, so a plant-wide reboot storm is answered without waiting on the database.
08 Logs what it did Every DHCP reply, every configuration file served and every device syslog message goes to a table, one per day, in log databases kept apart from the plant — so a backup carries the plant rather than the month's traffic, and a day's logs are disposed of by dropping a table.
09 Can be steered while running tell-docserv queues a command for a running service: flush the caches, change the log level, or shut down. When a pool runs out of addresses an external program is invoked, rate-limited per kind.
04 · Administrative tools

Nine standalone binaries

01count-ipsAddress pool usage for one CMTS VLAN
02db-config-encoderCompiles configuration fragment text into its binary form
03delete-old-leasesAges out stale leases on one VLAN, with a dry-run mode
04gen-cache-filesRegenerates the /dev/shm hand-off caches
05list-messagesPrints recent rows from any log table
06summarize-logsRotates old log rows into the archive database
07tell-docservQueues a remote command for a running server
08stress-config-generatorBenchmarks configuration-file generation
09test-cv-macMAC address conversion round-trip check
05 · Get started

Build, load the schema, start

You need a Rust toolchain supporting edition 2024 (1.85 or newer), MySQL 8.x or MariaDB 10.11 or newer, and a CMTS configured to relay DHCP to this server. The docsis encoder is needed only if you use generated configuration files.

# build
git clone https://github.com/mmqr-developer/docsis_server.git
cd docsis_server
cargo build --release

# the provisioning database, and the two the logs go in
mysql -u root -p -e "CREATE DATABASE docsis_server
  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  CREATE DATABASE docsis_server_logs
  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  CREATE DATABASE syslog_server
  DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# the tables, into the provisioning database only
mysql -u root -p docsis_server < scripts_and_docs/schema-dhcp.sql
mysql -u root -p docsis_server < scripts_and_docs/schema-dhcpv6.sql   # if you serve IPv6

# copy and edit the configuration, then start the activated services
cp scripts_and_docs/docsis-server.json /etc/docsis-server.json
docsis_server

The configuration file is JSON read with a relaxed parser — comments, trailing commas and unquoted keys are all allowed — and it ships heavily annotated. Every key is typed: a misspelling or an out-of-range value is reported at start-up with the line and column rather than silently ignored. The schema files name no database, so a second plant can live on the same MySQL server under a different name.

Deploying

INSTALL.md covers a full deployment including the systemd units; INSTALL.cisco.md covers the CMTS side and INSTALL.mysql-users.md the database accounts and the grants each needs.

The tables

SQL_INFO.md names every table and column, what writes it and what reads it. Both schema files and the configuration file are annotated and worth reading alongside it.