Skip to content

Network Management

The Network Management module is the core module - no dependencies - that gives you a unified interface for switch port management, VLAN operations, wireless networks, topology visualization, firmware lifecycle, and controller config backup across all connected network controllers.

The reference adapter is Omada (TP-Link) - production, gold-standard, tested against real hardware. UniFi is production, live-validated on a real UCG Fiber. Every configuration write is staged by default and requires an explicit apply step before touching a live device. This is not optional during initial setup - see Write safety and staging.

Adapter Tier Notes
Omada (TP-Link) Production / gold standard write-capable with staging gate; full VLAN/WiFi/port/AP/hotspot/802.1X surface; deepest adapter in the codebase
UniFi (Ubiquiti) Production Read paths + dual-gated writes; reads live-validated on a real UCG Fiber across both the classic v1 and modern v2 API lanes

For firewall/router adapters - OPNsense, pfSense, MikroTik, OpenWRT - see Firewall.

Every configuration write routes through the staged dual-gate:

  1. Read-only gate - ADAPTER_READ_ONLY (and OMADA_READ_ONLY) both default to true on new installs (safe by default). While either is true, the Omada client layer raises OmadaApiError on any mutating HTTP verb, and the standard network endpoint router (_push_vlan_to_controller, _push_wifi_to_controller) catches that error silently - the database change commits, but the controller is not written. No row is queued in adapter_pending_changes; the push is simply skipped with a warning log.
  2. Apply gate - the formal staged-change pipeline (adapter_pending_changes / AdapterStagingService) is used by the shared gateway-vpn apply dispatcher (POST /api/v1/gateway-vpn/changes/{change_id}/apply with {"force": true}) and by all firewall/gateway adapter endpoint families - OPNsense, pfSense, MikroTik, OpenWrt, Proxmox, UniFi, and Omada write endpoints all stage through AdapterStagingService and apply via this dispatcher. The standard VLAN/WiFi/port paths in the network module do not use this pipeline - they push directly and live to the controller.

When ADAPTER_READ_ONLY is disabled (false), standard VLAN/WiFi writes push directly and live to the controller. There is no pending-changes queue for these paths; the controller sync or next scheduled poll reconciles any drift.

The Omada raw passthrough (/api/v1/gateway-raw/{controller_id}/call) also enforces this gate and blocks sensitive paths regardless of force - /admin, /users, /roles, /cmd/backup, /maintenance/, /setting/system/sslcert, and others - so the escape hatch cannot bypass the staging audit trail.

ControllerCreate accepts inline credentials (username / password). There is no credential_id field and no separate credential-store step for controller registration.

Required fields: name, controller_type, host, port, site_id. Optional: username, password, use_ssl, verify_ssl, sync_enabled, sync_interval_seconds, config, site_mappings.

Omada:

Terminal window
curl -s -X POST https://<freesdn>/api/v1/controllers/ \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"name": "omada-1",
"controller_type": "omada",
"host": "https://omada.lan",
"port": 8043,
"site_id": "<site_uuid>",
"username": "admin",
"password": "<pass>"
}'

UniFi:

Terminal window
curl -s -X POST https://<freesdn>/api/v1/controllers/ \
-H "Cookie: freesdn_access=<token>" \
-H "X-CSRF-Token: <csrf>" \
-H "Content-Type: application/json" \
-d '{
"name": "unifi-1",
"controller_type": "unifi",
"host": "https://unifi.lan",
"port": 8443,
"site_id": "<site_uuid>",
"username": "admin",
"password": "<pass>"
}'
Terminal window
# Test connectivity against stored credentials
curl -s -X POST https://<freesdn>/api/v1/controllers/<controller_id>/test \
-H "Cookie: freesdn_access=<token>" -H "X-CSRF-Token: <csrf>"
# Pull inventory into FreeSDN
curl -s -X POST https://<freesdn>/api/v1/controllers/<controller_id>/sync \
-H "Cookie: freesdn_access=<token>" -H "X-CSRF-Token: <csrf>"

3. Probe remote sites (multi-site controllers)

Section titled “3. Probe remote sites (multi-site controllers)”

Omada and UniFi controllers can manage multiple sites. Map their remote sites to FreeSDN sites before you start syncing:

Terminal window
# List remote sites visible on the controller
GET /api/v1/controllers/<controller_id>/remote-sites
# Map remote-site IDs to FreeSDN site UUIDs
PUT /api/v1/controllers/<controller_id>/site-mappings

The switch detail view (/switches/:deviceId/:tab) has twelve tabs driven by the URL.

Method Path Permission Purpose
GET /api/v1/switches/ network:read Paginated list with aggregated port/PoE stats
GET /api/v1/switches/{id} network:read Detailed single-switch info
POST /api/v1/switches/{id}/refresh network:write Pull live state from controller into DB
Method Path Permission Purpose
GET /api/v1/switches/{id}/ports network:read List all ports (SwitchPortOut)
GET /api/v1/switches/{id}/ports/{n} network:read Single port detail
PATCH /api/v1/switches/{id}/ports/{n} network:write Full port config (see fields below)
POST /api/v1/switches/{id}/ports/{n}/toggle network:write Enable / disable port
POST /api/v1/switches/{id}/ports/{n}/poe network:write Enable / disable PoE
POST /api/v1/switches/{id}/ports/{n}/poe/cycle network:write Power-cycle PoE (disable → wait → enable)
POST /api/v1/switches/{id}/ports/bulk network:write Bulk-update multiple ports

The PATCH port body accepts: name, enabled, speed, duplex, mtu, flow_control, vlan_config (native/tagged), poe_config, and stp_config (mode, guard, BPDU protection). It also accepts security_config for 802.1X mode (auto / force_auth / force_unauth / disable), MAC limit, and violation action.

The interactive U (untagged) / T (tagged) / empty matrix lets you assign VLAN membership to every port in one operation.

Method Path Permission Purpose
GET /api/v1/switches/{id}/vlans network:read VLANs on this switch’s controller
PUT /api/v1/switches/{id}/vlans/port-assignments network:write Bulk-assign VLAN memberships to ports

Large switches (48+ ports × 20+ VLANs) render the matrix with TanStack Virtual to avoid DOM overhead.

Method Path Permission Purpose
GET /api/v1/switches/{id}/lags network:read List LAG groups
POST /api/v1/switches/{id}/lags network:write Create LAG
PUT /api/v1/switches/{id}/lags/{lag_id} network:write Update LAG (member ports, LACP/static)
DELETE /api/v1/switches/{id}/lags/{lag_id} network:write Delete LAG
Method Path Permission Purpose
GET /api/v1/switches/{id}/mirror network:read Port mirror config
PUT /api/v1/switches/{id}/mirror network:write Set mirror session, source, and destination
Method Path Permission Purpose
GET / PUT /api/v1/switches/{id}/stp network:read / network:write STP/RSTP global config (mode, priority, hello, max-age)
GET / POST /api/v1/switches/{id}/acl network:read / network:write ACL rules
PUT / DELETE /api/v1/switches/{id}/acl/{rule_id} network:write Update / delete ACL rule
GET / PUT /api/v1/switches/{id}/igmp network:read / network:write IGMP snooping config
POST /api/v1/switches/{id}/ports/{n}/isolation network:write Port isolation toggle
Method Path Purpose
POST .../ports/{n}/flow-control 802.3x flow control
POST .../ports/{n}/speed Link speed / duplex
POST .../ports/{n}/loopback-detect Loopback detection
POST .../ports/{n}/bandwidth Bandwidth / rate limiting
POST .../ports/{n}/storm-control Storm-control thresholds
POST .../ports/{n}/lldp Enable / disable LLDP-MED

All require network:write.

Requires the network.advanced_poe feature flag (default OFF).

Method Path Purpose
GET /api/v1/switches/{id}/poe-schedules List PoE schedules
POST /api/v1/switches/{id}/poe-schedules Create schedule
PUT /api/v1/switches/{id}/poe-schedules/{schedule_id} Update schedule
DELETE /api/v1/switches/{id}/poe-schedules/{schedule_id} Delete schedule
Method Path Purpose
POST /api/v1/switches/{id}/diagnostics/cable-test Cable diagnostic on a port
POST /api/v1/switches/{id}/diagnostics/ping Ping from device to target
POST /api/v1/switches/{id}/diagnostics/traceroute Traceroute from device

There are two distinct kinds of profiles - be precise about which you mean:

Kind Prefix Notes
DB-backed port profiles /api/v1/switches/profiles* Stored in FreeSDN DB; GET/POST/PUT/PATCH/DELETE
Controller-side port profiles /api/v1/switches/{id}/port-profiles* Pushed to the controller; GET/POST/PUT/DELETE

You can also apply a batch CLI configuration profile to multiple ports with POST /api/v1/switches/{id}/cli-profile/apply.

Visibility: MAC table, LLDP, events, clients

Section titled “Visibility: MAC table, LLDP, events, clients”
Method Path Purpose
GET /api/v1/switches/{id}/mac-table MAC address table
GET /api/v1/switches/{id}/lldp LLDP neighbors (from port metadata)
GET /api/v1/switches/{id}/events Recent controller events for this device
GET /api/v1/switches/{id}/alerts Active controller alerts
GET /api/v1/switches/{id}/clients Connected clients

These endpoints read site-level config from the controller; DHCP snooping and QoS have corresponding PUT write paths:

GET /api/v1/switches/{id}/routes - static routes (read-only)
GET /api/v1/switches/{id}/dhcp - site DHCP config
GET|PUT /api/v1/switches/{id}/dhcp/snooping - DHCP snooping
GET|PUT /api/v1/switches/{id}/qos - site QoS

POST /api/v1/switches/{id}/oui-vlan/apply matches connected-client MAC OUIs to VLAN mappings and configures each client port’s native VLAN automatically. Body:

{
"mappings": [
{ "oui_prefix": "AA:BB:CC", "vlan_id": 20, "description": "Printers" }
]
}

GET /api/v1/switches/{id}/running-config pulls the running config for backup or diff comparison. The Config History tab in the switch detail view shows a diff viewer across snapshots.


VLANs are controller-scoped in the network.vlans table (Network model). This is the Layer 0 truth - what a specific controller currently knows. Site-wide desired state (gateway.gw_canonical_vlans) is a Layer 2 concept managed by the Firewall module.

Method Path Permission Purpose
GET /api/v1/network/vlans authenticated List VLANs; site_id?, skip, limit
GET /api/v1/network/vlans/{id} authenticated Get one VLAN
POST /api/v1/network/vlans config:write Create VLAN (201)
PATCH /api/v1/network/vlans/{id} config:write Update + best-effort controller push
DELETE /api/v1/network/vlans/{id} config:write Soft-delete + push delete to controller

Create body fields: vlan_id (1-4094), name (1-128 chars), description?, site_id?, dhcp_enabled, dhcp_start, dhcp_end, gateway, subnet_mask.

When a site has multiple controllers, VLANs can drift out of sync. Use the alignment endpoints to detect and fix this:

Terminal window
# See alignment matrix - always safe, never mutates
GET /api/v1/network/vlans/alignment?site_id=<uuid>

Response includes a per-controller present/absent/differs flag and an alignment_score (0-100). The matrix only provides meaningful data with two or more controllers at the same site.

Terminal window
# Push a VLAN from a source controller to target controllers
POST /api/v1/network/vlans/distribute
{
"source_network_id": "<uuid>",
"target_controller_ids": ["<uuid>", "<uuid>"]
}

This is a direct write subject to the adapter read-only gate. If ADAPTER_READ_ONLY=true, the push to each target controller is blocked and no DB record is written for that target. Per-target success/fail results are returned; a partial failure does not roll back successful targets.

The VlansPage alignment tab shows the VLAN × controller matrix with per-cell “Copy” buttons that call distribute on a single target.


Method Path Permission Purpose
GET /api/v1/access-points/ network:read Paginated AP list with radio/client summary
GET /api/v1/access-points/{id} network:read AP detail including live controller data
GET /api/v1/access-points/{id}/clients network:read Clients connected to this AP
GET /api/v1/access-points/{id}/firmware network:read Firmware update status
PATCH /api/v1/access-points/{id}/name network:write Update display name (pushes to controller)
Method Path Purpose
GET /api/v1/access-points/{id}/radios Radio config for all bands
PATCH /api/v1/access-points/{id}/radios/{band} Update radio settings for band ∈ {2g, 5g, 5g2, 6g}

Radio settings include channel, TX power, channel width, DFS, and band steering.

Method Path Permission Purpose
GET /api/v1/network/wifi authenticated List SSIDs; site_id?, enabled?, paging
POST /api/v1/network/wifi config:write Create SSID; requires site_id
PATCH /api/v1/network/wifi/{id} config:write Update + controller push
DELETE /api/v1/network/wifi/{id} config:write Soft-delete + controller push
POST /api/v1/network/wifi/{id}/toggle config:write Enable / disable SSID; body {"enabled": true}
GET /api/v1/access-points/{id}/ssid-overrides network:read Per-AP SSID enable/disable overrides
PUT /api/v1/access-points/{id}/ssid-overrides network:write Set per-AP SSID overrides

SSID create body: ssid (1-32 chars), security (default wpa2_personal; valid values: open, wep, wpa_personal, wpa2_personal, wpa3_personal, wpa_wpa2_personal, wpa2_wpa3_personal, wpa2_enterprise, wpa3_enterprise - all underscore-separated; sending an unrecognised value returns 422), password? (max 63 chars; WPA2 requires ≥ 8 chars as a protocol constraint, but the API schema does not enforce a minimum - short passwords are forwarded to the adapter unchanged), vlan_id? (1-4094), hidden, enabled, band (default both), client_isolation, band_steering, fast_roaming, rate_limit_enabled/up/down.

Method Path Purpose
GET / PATCH /api/v1/access-points/{id}/lan-port LAN port VLAN tagging and PoE passthrough
PATCH /api/v1/access-points/{id}/mesh Enable / disable mesh; body {"enabled": true}
PATCH /api/v1/access-points/{id}/led LED mode: 0=off, 1=on, 2=site_settings
Method Path Purpose
POST /api/v1/access-points/{id}/adopt Adopt a pending AP; sets status ADOPTING
POST /api/v1/access-points/{id}/forget Forget / remove AP; sets status UNKNOWN
POST /api/v1/access-points/{id}/upgrade Trigger firmware upgrade
POST /api/v1/access-points/{id}/reboot Reboot AP
POST /api/v1/access-points/{id}/locate Flash LEDs to locate AP
GET /api/v1/access-points/{id}/rf-scan RF scan results

All AP write endpoints require network:write.


Controllers are the upstream systems FreeSDN reads from and pushes to. The controller detail page and these endpoints cover advanced wireless functions, hotspot, 802.1X, batch ops, firmware lifecycle, and config backup.

Method Path Permission Purpose
GET /api/v1/controllers/ controller:read Paginated list
GET /api/v1/controllers/{id} controller:read Single controller with stats
POST /api/v1/controllers/ controller:create Add controller (201)
PATCH /api/v1/controllers/{id} controller:update Update controller
DELETE /api/v1/controllers/{id} controller:delete Delete controller (204)
POST /api/v1/controllers/{id}/test controller:update Test stored-credential connection
POST /api/v1/controllers/test-connection controller:create Test connection pre-creation (raw creds)
POST /api/v1/controllers/{id}/sync controller:update Sync inventory from controller
Method Path Purpose
GET / PUT /api/v1/controllers/{id}/hotspot Hotspot config
GET / PUT /api/v1/controllers/{id}/captive-portal Captive portal config
GET /api/v1/controllers/{id}/hotspot/vouchers List vouchers
POST /api/v1/controllers/{id}/hotspot/vouchers Create vouchers (201)
DELETE /api/v1/controllers/{id}/hotspot/vouchers/{voucher_id} Delete voucher

All require controller:update.

Method Path Purpose
GET / PUT /api/v1/controllers/{id}/dot1x 802.1X site-wide config
GET /api/v1/controllers/{id}/dot1x/events Recent authentication events
GET / PUT /api/v1/controllers/{id}/dot1x/radius RADIUS auth + accounting servers (primary/secondary, ports, shared secrets)
GET /api/v1/controllers/{id}/dot1x/stats Success / failure counts
Method Path Purpose
GET / PUT /api/v1/controllers/{id}/wifi/radio-settings Site-wide channel plan, TX power, DFS, band steering
GET /api/v1/controllers/{id}/wifi/channel-utilization Per-AP/band utilization (RF Health tab)
GET /api/v1/controllers/{id}/wifi/rogue-aps Rogue-AP detection results
Method Path Permission Purpose
POST /api/v1/controllers/{id}/batch/reboot controller:update + site_admin role Reboot multiple devices; logged to freesdn.security.batch_op
POST /api/v1/controllers/{id}/batch/firmware-upgrade controller:update + site_admin role Bulk firmware upgrade
POST /api/v1/controllers/{id}/batch/firmware-check controller:update Check available updates fleet-wide
Method Path Purpose
GET /api/v1/controllers/{id}/firmware Available firmware versions
GET /api/v1/controllers/{id}/firmware/overview Counts per version + update availability
GET /api/v1/controllers/{id}/firmware/history Upgrade history log
Method Path Purpose
GET /api/v1/controllers/{id}/health Controller health
GET /api/v1/controllers/{id}/logs Controller system logs
POST /api/v1/controllers/{id}/backup Trigger controller config backup
GET /api/v1/controllers/{id}/topology Topology data from the controller

The topology graph is a React Flow canvas at /topology. It has three distinct API surfaces - know which one the frontend is calling:

Router Path prefix Notes
Module router GET /api/v1/network/topology Nodes + links, site_id?
Endpoint router GET /api/v1/network/topology Also nodes + links (UI fallback)
Topology router /api/v1/topology/* Frontend TopologyPage uses this one; includes saved layouts
Method Path Permission Purpose
GET /api/v1/topology/graph device:read Full topology graph (TopologyGraphResponse)
GET /api/v1/topology/layout/{site_id} device:read Saved node positions for a site (nullable)
PUT /api/v1/topology/layout/{site_id} device:write Save / update node positions
POST /api/v1/topology/auto-layout/{site_id} device:write Auto-arrange layout
DELETE /api/v1/topology/layout/{site_id} device:write Delete saved layout (204)
Method Path Permission Purpose
POST /api/v1/network/discovery/start device:update Start device discovery Celery task; site_id?, subnet? (202)
GET /api/v1/network/discovery/status device:read Poll Celery progress; task_id required
POST /api/v1/network/topology/refresh device:update Dispatch discover_all_devices Celery task (202)

Method Path Permission Purpose
GET /api/v1/network/clients authenticated List clients; site_id?, paging
GET /api/v1/network/clients/{id} authenticated Single client
GET /api/v1/network/clients/stats/summary device:read Summary counts; site_id?
POST /api/v1/network/clients/{id}/block device:update Block client; sets blocked=True + calls adapter.block_client(mac) best-effort
POST /api/v1/network/clients/{id}/unblock device:update Unblock client; clears flag + calls adapter.unblock_client(mac)

The actions router provides a small set of imperative device operations:

Method Path Permission Purpose
POST /api/v1/actions/poe/cycle device:action Cycle PoE on a switch port; body {device_id, port (1-48), duration (1-30s)}
POST /api/v1/actions/wifi/ssid/toggle controller:action Enable / disable SSID; body {controller_id, ssid_name, enabled}
POST /api/v1/actions/reboot device:admin Reboot a device; body {device_id}

POST /api/v1/actions/poe/cycle also publishes an action.poe_cycle event to the event bus.


Different routers use different permission strings. This is a real implementation seam, not a documentation error.

Router Read permission Write permission Admin/delete
Module api.py (/network/*) device:read device:update device:admin
Endpoint network.py - VLAN/WiFi/port-VLAN authenticated config:write config:write
Endpoint network.py - port PoE/patch, client block authenticated device:update -
switches.py network:read network:write -
access_points.py network:read network:write -
controllers.py controller:read controller:update controller:delete; batch ops also require site_admin role
actions.py - PoE cycle / SSID toggle - device:action / controller:action device:admin (reboot)
topology.py device:read device:write -

The module manifest declares network.view, network.manage, network.vlan.manage, network.wifi.manage, network.poe.control, and network.firmware.upgrade as its public permission names, which map onto the role hierarchy.


These routers mount directly at /api/v1/ and provide typed or raw access to Omada-specific API surfaces. They are Omada-only and not vendor-neutral FreeSDN features.

Path prefix Source file Coverage
/api/v1/gateway-wifi/* adapter_omada_wifi.py WLAN groups, SSIDs, surveillance-VLAN, walled-garden, voucher templates, WIDS/WIPS events
/api/v1/gateway-switch-advanced/* adapter_omada_switch_advanced.py Switch configs, mirror sessions, per-port jumbo frame
/api/v1/gateway-hotspot/* adapter_omada_hotspot.py Operators, SMS gateway, portal form fields, free-auth policies
/api/v1/gateway-firmware/* adapter_omada_firmware.py Firmware lists, checks
/api/v1/gateway-bulk/* adapter_omada_bulk.py Bulk read + bulk action
/api/v1/gateway-diagnostics/* adapter_omada_diagnostics.py Gateway speed-test, sessions
/api/v1/gateway-raw/{controller_id}/call adapter_omada_raw.py Power-user raw passthrough (see below)

The raw passthrough requires controller:write. Write methods are blocked when ADAPTER_READ_ONLY is true unless force=true is passed in the body. A hardcoded blocklist prevents bypassing the staging audit trail regardless of force:

/admin /users /roles /cmd/backup /maintenance/ /setting/system/sslcert …

Route Page Notes
/network NetworkDashboardPage Overview widgets
/topology TopologyPage (enterprise) React Flow canvas; uses /topology/* API
/switches SwitchesPage Paginated list; select → detail
/switches/:deviceId/:tab SwitchesPage detail Tabs: overview, ports, vlans, lags, profiles, network, config, config-history, logs, clients, diagnostics, advanced
/access-points AccessPointsPage Paginated list; select → detail
/access-points/:deviceId/:tab AccessPointsPage detail Tabs: overview, radios, ssids, clients, config, rf-health, rogue-aps, radio-settings
/vlans or /network/vlans VlansPage Tabs: vlans (CRUD), alignment (VLAN × controller matrix)
/wifi or /network/wifi WifiNetworksPage SSID list + create/edit
/network/clients NetworkClientsPage Client table with block/unblock
/poe PoEPage PoE budget + scheduling

The Network module participates in the Fabric universal app-interconnect:

  • Operation network.client.list - read connected clients (org-scoped, optional site_id and is_online filter, up to 200 results); permission network.view. Use as a mid-chain step in Fabric Connections.
  • Events emitted - network.vlan.created, network.vlan.updated, network.vlan.deleted, network.wifi.created, network.wifi.updated, network.wifi.deleted (NATIVE tier). Wire these as triggers in the Fabric Connections builder.

Setting Default Notes
discovery_interval 300 s Configures the interval used when discovery is manually triggered; background auto-polling is not currently active (tasks are commented out)
topology_refresh 600 s Configures the refresh interval used when topology refresh is manually triggered; automatic periodic rebuild is not currently active (tasks are commented out)
traffic_retention_days 30 Days of port traffic data kept in TimescaleDB
auto_backup_enabled true Currently not wired to any background task. Use POST /api/v1/controllers/{id}/backup to trigger backups manually.
backup_retention_count 5 Number of config snapshots to retain per device
poe_budget_warning_threshold 80 % PoE budget warning level
Feature flag Default Notes
network.advanced_poe OFF Enables PoE scheduling and budget endpoint
network.topology_auto ON Auto topology discovery
network.traffic_analytics ON Per-port traffic metrics to TimescaleDB
network.bulk_firmware OFF Multi-device firmware upgrade

  • Two port-write paths with different behavior. /api/v1/switches/{id}/ports/{n} pushes to the controller via the adapter. /api/v1/network/devices/{id}/ports/{n} is DB-only. If a port change does not appear on hardware, confirm which path your client is calling.

  • Rogue-AP 501. If the controller adapter does not implement rogue-AP detection, the endpoint returns 501. This is the expected behavior, not a server error.

  • VLAN distribute is not transactional across controllers. If distributing to three controllers and the second fails, the first succeeded and the third may or may not have run. Check per-target results in the response.

  • UniFi is production. Reads are live-validated on a real UCG Fiber; writes are staged and dual-gated, with VLAN/network create + delete proven live. Omada remains the deepest adapter for write capability.

  • Batch ops are not staged. batch/reboot and batch/firmware-upgrade hit live devices directly (subject to the read-only env flag). They require site_admin and are audit-logged, but they do not go through Pending Changes.

  • Module background tasks do not auto-run. Discovery and topology refresh run only when triggered via the API or a Celery task. The health_check reports their state but they are never spawned automatically by the module lifecycle.


  • Firewall - gateway orchestration, VPN, NAT, IDS/IPS, and the gw_canonical_vlans Layer 2 desired-state model
  • Configuration Reference - ADAPTER_READ_ONLY, discovery intervals, and all environment variables
  • Fabric - wire network events into cross-module automations
  • Supported Vendors - honest adapter maturity matrix

All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.