API de VLAN, IP y rutas
Estos endpoints administran las interfaces VLAN del router, las direcciones de sus interfaces, las rutas estáticas que conserva entre reinicios y sus pools de NAT dinámico (de origen). La URL base, la autenticación y el formato de los errores se describen en la descripción general de la API.
Todo lo que se crea aquí es persistido por el router y se restaura en el arranque. Los cambios se registran con la dirección de quien realiza la llamada. Una respuesta 5xx puede incluir broken_data_files, que indica los archivos de datos del router que no se pueden analizar.
El nombre de interfaz de una VLAN se deriva de su interfaz padre y de su protocolo: vlan100 para una VLAN 802.1Q sobre un puerto o bond, svlan500 para una S-VLAN 802.1ad, svlan500.20 para una C-VLAN dentro de una S-VLAN.
GET /vlans
Sección titulada «GET /vlans»Todas las VLAN que administra el router, con su estado actual.
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/vlans{ "count": 1, "vlans": [ { "name": "vlan110", "parent": "bond0", "vlan_id": 108, "protocol": "802.1Q", "ips": ["100.64.8.1/24"], "ips6": ["XXXX:XXXX:110::1/64"], "label": "OLT 1 PON 0/1/3", "added": "2026-09-01 10:00:00", "enabled": true, "live": true, "status": "UP", "live_ips": ["100.64.8.1/24"], "live_ips6": ["XXXX:XXXX:110::1/64"] } ]}status es el estado del enlace, DISABLED para una VLAN deshabilitada o NOT CREATED cuando la interfaz no existe.
POST /vlans
Sección titulada «POST /vlans»Crea la VLAN, la activa y agrega sus direcciones. Salvo que serve esté desactivado, cada dirección se sirve a continuación: IPv4 con DHCP (POST /net), IPv6 con DHCPv6 y un pool (POST /net6, POST /net6/pool) y delegación de prefijos (POST /pd). Cada paso de servicio se informa por separado; un paso fallido no deshace la VLAN.
| Nombre | En | Tipo | Notas |
|---|---|---|---|
parent |
body | string | Interfaz padre existente: un puerto, un bond o una S-VLAN. |
vlan_id |
body | integer | 1–4094. |
protocol |
body | string | 802.1Q (predeterminado) o 802.1ad. |
ip |
body | CIDR | Dirección de gateway IPv4 opcional, p. ej. 100.64.8.1/24. Una dirección de red se corrige al primer host (con una nota). |
ipv6 |
body | CIDR | Dirección IPv6 opcional, p. ej. XXXX:XXXX:110::1/64. |
label |
body | string | Descripción opcional. |
serve |
body | boolean | 0, false o no crea solo el enlace. Activado de forma predeterminada. |
force |
body | boolean | Permite una dirección que se solapa con otra ya presente en otra interfaz. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"parent":"bond0","vlan_id":108,"ip":"100.64.8.1/24","ipv6":"XXXX:XXXX:110::1/64","label":"OLT 1 PON 0/1/3"}' \ http://ROUTER-IP:8880/vlans{ "ok": true, "code": 201, "message": "VLAN vlan110 created on bond0 (100.64.8.1/24) (XXXX:XXXX:110::1/64)", "name": "vlan110", "parent": "bond0", "vlan_id": 108, "protocol": "802.1Q", "ip": "100.64.8.1/24", "ipv6": "XXXX:XXXX:110::1/64", "served": { "net": { "network": "100.64.8.0/24" }, "net6": { "network": "XXXX:XXXX:110::/64", "pool": "XXXX:XXXX:110::1000 - XXXX:XXXX:110::ffff" }, "pd": { "pool": "XXXX:XXXX:a:1000:: - XXXX:XXXX:a:10ff::", "capacity": 256 } }}Un paso de servicio fallido aparece como {"error": "…", "retry": "dtvsol net add vlan110"} bajo su clave, y warning indica que la VLAN no se sirve por completo. Con serve desactivado, served es null y note indica qué comandos la servirán más adelante.
Errores: 400 ID, dirección o protocolo no válidos; 404 no se encontró la interfaz padre; 409 la VLAN ya existe, la etiqueta ya se usa en esa interfaz padre o hay un conflicto de direcciones (la respuesta incluye conflict; envíe force para forzarlo).
DELETE /vlans
Sección titulada «DELETE /vlans»El nombre de la VLAN se toma del cuerpo.
| Nombre | En | Tipo | Notas |
|---|---|---|---|
name |
body | string | Nombre de la interfaz VLAN, p. ej. vlan110. |
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"vlan110"}' http://ROUTER-IP:8880/vlans{ "ok": true, "code": 200, "message": "VLAN vlan110 deleted", "name": "vlan110", "removed_subnets": ["subnet 100.64.8.0"], "removed_pd_pool": null, "removed_routes": [], "removed_nat": null, "removed_forwards": [], "kept": { "rrd": "data/rrd/iface_vlan110.rrd (traffic history; delete by hand if not wanted)" }}Errores: 404 no es una VLAN administrada; 409 cuando otra VLAN la usa como padre, todavía hay clientes registrados en ella o CGNAT traduce a través de ella (la respuesta incluye un fix).
POST /vlans/disable
Sección titulada «POST /vlans/disable»Desactiva una VLAN sin liberar nada; POST /vlans/enable la restaura exactamente. GET /vlans/disable toma los parámetros de la cadena de consulta.
| Nombre | En | Tipo | Notas |
|---|---|---|---|
name |
body | string | Nombre de la interfaz VLAN. |
reason |
body | string | Nota opcional que se guarda con la VLAN. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"vlan110","reason":"OLT maintenance"}' http://ROUTER-IP:8880/vlans/disable{ "ok": true, "code": 200, "message": "VLAN vlan110 disabled", "name": "vlan110", "enabled": false, "disabled_at": "2026-09-27 10:00:00", "reason": "OLT maintenance", "took_offline": ["dhcp4", "dhcp6", "radvd", "link down"], "kept": "delegation range, subnet blocks, NAT pool, port forwards, routes, client reservations and addresses — all restored by: dtvsol vlan enable vlan110", "forwards_still_active": []}Errores: 404 no encontrada; 409 ya está deshabilitada, una VLAN habilitada funciona sobre ella o CGNAT traduce a través de ella.
POST /vlans/enable
Sección titulada «POST /vlans/enable»| Nombre | En | Tipo | Notas |
|---|---|---|---|
name |
body | string | Nombre de la interfaz VLAN. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"vlan110"}' http://ROUTER-IP:8880/vlans/enable{ "ok": true, "code": 200, "message": "VLAN vlan110 enabled", "name": "vlan110", "enabled": true, "restored": ["link up", "addresses", "dhcp4", "dhcp6 + radvd"], "forwards_active": [], "was_disabled_at": "2026-09-27 10:00:00", "was_disabled_reason": "OLT maintenance"}Errores: 404 no encontrada; 409 ya está habilitada o su VLAN padre está deshabilitada.
Direcciones de interfaz
Sección titulada «Direcciones de interfaz»POST /ip
Sección titulada «POST /ip»Agrega una dirección IPv4 o IPv6 a una interfaz existente. En una VLAN administrada se guarda con la VLAN; en un puerto físico o un bond se guarda en la configuración de red del router. Agregar una dirección que ya está activa solo la persiste. La dirección no se sirve automáticamente: use POST /net o POST /net6.
| Nombre | En | Tipo | Notas |
|---|---|---|---|
iface |
body | string | Nombre de la interfaz. |
ip |
body | CIDR | Dirección IPv4 o IPv6 con longitud de prefijo. Una dirección de red se corrige al primer host. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"iface":"vlan110","ip":"100.64.9.1/24"}' http://ROUTER-IP:8880/ip{ "ok": true, "code": 201, "message": "IP 100.64.9.1/24 added to vlan110", "persisted": true }Cuando la dirección se corrigió, la respuesta incluye además requested, assigned y note. Errores: 400 dirección no válida; 404 no se encontró la interfaz; 409 cuando la subred ya está en otra interfaz (por REST no hay forma de forzarlo; la API de acciones acepta force=1).
DELETE /ip
Sección titulada «DELETE /ip»| Nombre | En | Tipo | Notas |
|---|---|---|---|
iface |
body | string | Nombre de la interfaz. |
ip |
body | CIDR | Dirección que se quitará, tal como se asignó. |
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"iface":"vlan110","ip":"100.64.9.1/24"}' http://ROUTER-IP:8880/ip{ "ok": true, "code": 200, "message": "IP 100.64.9.1/24 removed from vlan110", "warning": "no interface is served in that network any more, so subnet 100.64.9.0 in dhcpd.conf is now unused — kept because it may hold hand-tuned options; remove it deliberately if not wanted", "unused_subnet": { "kind": "subnet", "block": "100.64.9.0", "file": "/etc/dhcp/dhcpd.conf" }}Una subred DHCP o un rango de delegación que quedan sin uso se indican (unused_subnet, unused_pd_pool, pd_warning), nunca se eliminan. Errores: 400 dirección no válida; 404 no se encontró la interfaz; 409 cuando la dirección es el gateway de un cliente registrado. Los demás métodos sobre /ip responden 400 Use POST /ip or DELETE /ip (use POST /ip o DELETE /ip).
Rutas estáticas
Sección titulada «Rutas estáticas»GET /routes
Sección titulada «GET /routes»Las rutas que administra el router (restauradas en el arranque) y las tablas de enrutamiento IPv4 e IPv6 activas del kernel.
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/routes{ "count": 1, "managed": [ { "prefix": "default", "via": "XXX.XXX.XXX.1", "dev": "vlan90", "family": "ipv4", "comment": "upstream", "created": "2026-09-01 10:00:00" } ], "live_ipv4": ["default via XXX.XXX.XXX.1 dev vlan90"], "live_ipv6": []}POST /routes
Sección titulada «POST /routes»| Nombre | En | Tipo | Notas |
|---|---|---|---|
prefix |
body | string | CIDR (10.50.0.0/24, XXXX:XXXX::/48) o default. |
via |
body | IP | Gateway, de la misma familia que el prefijo. Se requiere via y/o dev. |
dev |
body | string | Interfaz de salida. |
comment |
body | string | Opcional. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"prefix":"default","via":"XXX.XXX.XXX.1","dev":"vlan90","comment":"upstream"}' \ http://ROUTER-IP:8880/routes{ "ok": true, "code": 201, "message": "Route added", "route": { "prefix": "default", "via": "XXX.XXX.XXX.1", "dev": "vlan90", "family": "ipv4", "comment": "upstream", "created": "2026-09-28 09:00:00" }}Errores: 400 prefijo, gateway o nombre de interfaz no válidos; 409 Route already managed (la ruta ya está administrada); 500 cuando el kernel rechaza la ruta.
DELETE /routes
Sección titulada «DELETE /routes»Se elimina la primera ruta administrada con este prefijo (y, si se indican, con este via/dev).
| Nombre | En | Tipo | Notas |
|---|---|---|---|
prefix |
body | string | Prefijo de la ruta, o default. |
via |
body | IP | Opcional, para elegir una entre varias rutas. |
dev |
body | string | Opcional, para elegir una entre varias rutas. |
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"prefix":"default"}' http://ROUTER-IP:8880/routes{ "ok": true, "code": 200, "message": "Route removed", "route": { "prefix": "default", "via": "XXX.XXX.XXX.1", "dev": "vlan90", "family": "ipv4" }, "kernel_removed": true}Errores: 404 Route … is not managed by DTVSOL (la ruta no es administrada por DTVSOL).
Pools de NAT dinámico
Sección titulada «Pools de NAT dinámico»NAT de origen para el tráfico que sale por una interfaz, traducido a una dirección pública o a un rango. Para NAT de nivel operador (CGNAT) con bloques de puertos deterministas, consulte la API de CGNAT.
GET /nat
Sección titulada «GET /nat»Los pools configurados y las reglas NAT POSTROUTING activas.
curl -H "X-API-Key: YOUR_API_KEY" http://ROUTER-IP:8880/nat{ "count": 1, "pools": [ { "iface": "vlan90", "pool_start": "XXX.XXX.XXX.10", "pool_end": "XXX.XXX.XXX.20", "exempt": ["10.0.0.0/8"], "comment": "", "created": "2026-09-01 10:00:00" } ], "live_postrouting": ["-P POSTROUTING ACCEPT", "-A POSTROUTING -o vlan90 -j SNAT --to-source XXX.XXX.XXX.10-XXX.XXX.XXX.20 …"]}POST /nat
Sección titulada «POST /nat»| Nombre | En | Tipo | Notas |
|---|---|---|---|
iface |
body | string | Interfaz de salida. |
pool_start |
body | IPv4 | Primera dirección pública. |
pool_end |
body | IPv4 | Última dirección pública, opcional; omítala para una sola dirección. |
exempt |
body | list or string | Redes IPv4 (CIDR) opcionales que no se traducen; una lista o una cadena separada por comas. |
comment |
body | string | Opcional. |
curl -X POST -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"iface":"vlan90","pool_start":"XXX.XXX.XXX.10","pool_end":"XXX.XXX.XXX.20","exempt":["10.0.0.0/8"]}' \ http://ROUTER-IP:8880/nat{ "ok": true, "code": 201, "message": "Dynamic NAT pool configured", "pool": { "iface": "vlan90", "pool_start": "XXX.XXX.XXX.10", "pool_end": "XXX.XXX.XXX.20", "exempt": ["10.0.0.0/8"], "comment": "", "created": "2026-09-28 09:00:00" }}Errores: 400 nombre de interfaz, dirección del pool, rango invertido o red exenta no válidos; 404 no se encontró la interfaz; 500 cuando no se puede instalar una regla.
DELETE /nat
Sección titulada «DELETE /nat»| Nombre | En | Tipo | Notas |
|---|---|---|---|
iface |
body | string | Interfaz cuyo pool se quita. |
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \ -d '{"iface":"vlan90"}' http://ROUTER-IP:8880/nat{ "ok": true, "code": 200, "message": "NAT pool removed", "iface": "vlan90", "rules_removed": 1, "pool": { "iface": "vlan90", "pool_start": "XXX.XXX.XXX.10", "pool_end": "XXX.XXX.XXX.20" }}Errores: 400 sin iface; 404 No DTVSOL NAT pool on … (no hay pool de NAT de DTVSOL en esa interfaz).
Equivalentes en la API de acciones
Sección titulada «Equivalentes en la API de acciones»| Acción | Parámetros de consulta | Equivale a |
|---|---|---|
action=vlan-list |
— | GET /vlans |
action=vlan-add |
parent, vlan_id, protocol, ip, ipv6, label, force=1, serve=0 |
POST /vlans |
action=vlan-del |
name |
DELETE /vlans |
action=vlan-disable |
name, reason |
POST /vlans/disable |
action=vlan-enable |
name |
POST /vlans/enable |
action=ip-add |
iface, ip, force=1 |
POST /ip (con forzado) |
action=ip-del |
iface, ip |
DELETE /ip |
action=route-list |
— | GET /routes |
action=route-add |
prefix, via, dev, comment |
POST /routes |
action=route-del |
prefix, via, dev |
DELETE /routes |
action=nat-list |
— | GET /nat |
action=nat-add |
iface, pool_start, pool_end, exempt, comment |
POST /nat |
action=nat-del |
iface |
DELETE /nat |
Este sitio fue escrito con ayuda de IA y revisado por nuestro equipo.