- Rust 91%
- TypeScript 8.8%
|
All checks were successful
CI / check (push) Successful in 59s
CI / test (push) Successful in 42s
Container Images / build-and-push (map[dockerfile:docker/host/Dockerfile name:netforge-host]) (push) Successful in 43s
Container Images / build-and-push (map[dockerfile:docker/router/Dockerfile name:netforge-router]) (push) Successful in 2m26s
Container Images / build-and-push (map[dockerfile:docker/switch/Dockerfile name:netforge-switch]) (push) Successful in 5s
Four user-reported bug batches, addressed end-to-end:
1. `default interface <name>` prints the IOS success confirmation
line, and the dispatcher's resync trigger widens to accept the
new `Output(_)` outcome alongside `Ok`.
2. `ping`/`traceroute` `source <X>` properly extracts the value
after the `source` keyword from the parser's greedy argv (was
always rejecting because it validated the literal keyword), and
the resolver now produces the three IOS-exact error texts:
"Invalid source address — IP address not on any of our up
interfaces", "Invalid source interface — IP not enabled or
interface is down", and "Invalid input detected at '^' marker.".
Up-state is now checked on both paths (down interfaces are
excluded). The marker error renders with the full IOS marker
(input echo + caret) via a new internal
`CommandOutcome::InvalidArg { token }` variant that `dispatch()`
rewrites using `personality.format_error` and
`effective_input.rfind(&token)` for column positioning. `rfind`
handles the pathological case `ping … source source` correctly.
3. `clear ip arp` is now wired through layered platforms: added
`flush_arp` to `delegate_platform_defaults!` so every wrapper
(ACL / NAT / EtherChannel-OVS) forwards to the real
`LinuxPlatform` implementation instead of the trait's
`NotSupported` default.
4. Command history is per-CLI-mode (User/Privileged EXEC bucket vs.
config bucket). New `cli::history` module owns the bookkeeping;
`read_line` takes the bucket by immutable reference so the
device mutex is not held across blocking user typing, and
accepted lines are filed via `record_history(line, &mode)` so
the *typing* mode (not the dispatcher's `effective_mode`)
chooses the bucket. `show history` and `do show history` both
read the bucket matching the user's actual mode.
Vlan SVI feature gap:
- Every Cisco-variant device (router, l2/l3 switch, firewall) now
ships with `Vlan1` pre-created as the default management SVI in
admin-down state, mirroring real Catalyst / IOS-XE behaviour.
Lazy kernel-device creation in `LinuxPlatform` ensures a
configured Vlan SVI is actually pingable (creates a `dummy`
device on first `ip add` / `link up`).
- `show interfaces` renders `Hardware is EtherSVI` for Vlan SVIs
(was always `GigabitEthernet`).
- All six `show interfaces*` commands list Vlan SVIs at the top
of the output, then physical interfaces. Required two layers
of fix: `cisco_interface_order` sorts by a coarse family
priority (Vlan first), AND each show command iterates a single
unified, pre-sorted list of names from all three sources
(hardware manifest / running-config / interface map) instead of
the previous source-grouped three-pass layout that always
pushed Vlan to the bottom.
Gates: cargo fmt, cargo clippy --workspace --all-targets -- -W
clippy::pedantic -D warnings, cargo nextest run --workspace
(2167/2167) all clean. /review PASS, /security-audit SECURE for
every batch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .claude | ||
| .forgejo/workflows | ||
| .vscode | ||
| crates | ||
| docker | ||
| docs | ||
| frontend | ||
| migrations | ||
| scripts | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| .markdownlint.yaml | ||
| .markdownlintignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| docker-compose.dev.yml | ||
| justfile | ||
| LICENSE | ||
| netforge.toml.example | ||
| README.md | ||
NetForge
A web-based network simulation platform with a built-in Cisco IOS CLI simulator.
Build network topologies visually, configure devices through a realistic command-line interface, and watch real routing protocols converge — all in your browser, no proprietary images required.
What Is This?
NetForge lets you drag routers, switches, and hosts onto a canvas, cable them together, and open terminal sessions to each device. Every device is a real Docker container running real Linux networking: OSPF neighbors form actual adjacencies via FRRouting, VLANs are tagged by Open vSwitch, ACLs are enforced by nftables. The custom IOS CLI simulator (netforge-agent) translates familiar Cisco commands into these real subsystems.
Target users:
- Network engineers studying for CCNA/CCNP/CCIE certifications
- University networking courses seeking a Packet Tracer alternative
- Lab environments for testing configurations before production
- Anyone who wants to prototype network designs visually
Key Features
- Visual topology builder — drag-and-drop device placement, point-and-click cabling, real-time status indicators
- Cisco IOS CLI simulator — abbreviated commands, tab completion, context-sensitive
?help,show running-config,write memory, pipe filters (| include,| section) - Real protocol behavior — OSPF, BGP, EIGRP, RIP, STP, HSRP/VRRP via FRRouting and Open vSwitch, not software models
- Full L2/L3 stack — VLANs, trunking, ACLs, NAT/PAT, static routing, EtherChannel, MPLS/LDP, L3VPN
- In-browser terminals — xterm.js with per-device tabs, split-view, and send-to-all
- Multi-user collaboration — real-time topology sync, role-based access (Owner/Admin/Editor/Operator/Viewer), shared and independent terminal sessions
- Lab assessments — author exercises with automated verification, "Check My Work" grading, import/export as
.nfassessfiles - Packet capture — per-link tcpdump with live streaming, pcap download, and BPF filter support
- Lightweight — Alpine-based containers target 32 MB (host) to 128 MB (router) RAM; run 100+ devices on a single host
Architecture at a Glance
Browser (React + xterm.js)
|
| REST / WebSocket
v
NetForge Backend (Rust / Axum)
|
+-- Docker Engine ----> Per-device containers
+-- Open vSwitch -----> Virtual network fabric
+-- PostgreSQL -------> State persistence
|
v
Container (e.g. router)
+-- netforge-agent ---> IOS CLI simulator
+-- FRRouting --------> OSPF, BGP, EIGRP, ...
+-- nftables ---------> ACLs, NAT
Quick Start
See docs/DEVELOPMENT.md for the full setup guide. The short version:
git clone git@git.fiedler.live:tux/netforge.git && cd netforge
docker compose -f docker-compose.dev.yml up -d
export DATABASE_URL="postgres://netforge:netforge_dev@localhost:5432/netforge"
sqlx migrate run --source migrations
sudo systemctl start openvswitch-switch
cp netforge.toml.example netforge.toml
docker build -t netforge-router:dev -f docker/router/Dockerfile .
docker build -t netforge-switch:dev -f docker/switch/Dockerfile .
docker build -t netforge-host:dev -f docker/host/Dockerfile .
cargo watch -x run &
cd frontend && pnpm install && pnpm dev &
# Open http://localhost:5173
Requirements: Linux (Ubuntu 22.04+), Rust, Node.js 20+, Docker Engine, Open vSwitch.
Documentation
| Document | Description |
|---|---|
| docs/DEVELOPMENT.md | Development environment setup, building, testing, CI |
| docs/DESIGN.md | Full project design document — vision, phasing, feature specs |
| docs/ARCHITECTURE.md | Technical architecture — design decisions, tradeoffs, internals |
| docs/VERIFICATION.md | Manual verification matrix — step-by-step CLI checks per agent phase |
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React, TypeScript, Vite, React Flow, xterm.js |
| Backend | Rust, Axum, Tokio, Bollard, SQLx |
| Networking | FRRouting, Open vSwitch, nftables, iproute2 |
| Database | PostgreSQL |
| Containers | Docker, Alpine Linux |
Project Status
NetForge is under active development. See docs/DESIGN.md for the full roadmap and phasing.