add UML, fix structure

This commit is contained in:
2025-11-23 17:37:45 +03:00
parent 75c30afb31
commit 3782217438
10 changed files with 846 additions and 8 deletions
-8
View File
@@ -1,8 +0,0 @@
@startuml
class Device {
+id: string
+name: string
+model: string
+getInterfaces()
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+79
View File
@@ -0,0 +1,79 @@
@startuml
' ===========================
' Abstract base class
' ===========================
abstract class Device {
- name : String
- mgmtIP : String
- interfaces : Interface[*]
}
Device "1" o-- "0..*" Interface : has >
' ===========================
' Device Types
' ===========================
class Host {
- operatingSystem : String
}
class Router {
- routingTable : Map
- routingProtocols : List
}
class Switch {
- macTable : Map
- vlanDatabase : Map
}
Device <|-- Host
Device <|-- Router
Device <|-- Switch
' ===========================
' Interfaces
' ===========================
class Interface {
- name : String
- ipAddress : String
- macAddress : String
- speed : String
- duplex : String
}
class VirtualInterface {
- vlanId : Integer
- parentPhysical : Interface
}
Interface <|-- VirtualInterface
' ===========================
' Physical Links
' ===========================
class Wire {
- type : String
- endpoints : Interface[2]
- bandwidth : String
}
Wire "1" -- "2" Interface : connects >
' ===========================
' Optional: Networks / Subnets
' ===========================
class Network {
- cidr : String
- gateway : String
}
Network "1" o-- "0..*" Interface : membership >
@enduml
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

View File
+160
View File
@@ -0,0 +1,160 @@
# yaml-language-server: $schema=./topology-schema.json
schema: asvk.topology/1.0
meta:
id: "string"
title: "string"
description: "string"
provider:
name: virtualbox # virtualbox | kvm | container
defaults:
cpu: 1
ram_mb: 512
disk_gb: 8
os_image: "debian-12-cloud.qcow2"
nic_model: virtio
defaults:
routing:
stack: bird # bird | frr | linux
protocols_enabled: []
switch:
impl: linux-bridge # linux-bridge | ovs
firewall:
impl: nftables # nftables | none
mgmt:
ssh_user: "lab"
ssh_key: "~/.ssh/id_rsa.pub"
variables: # for templates
asn: 65000
domain: "lab.local"
networks: # L2 / L3 / VLAN trunks
- id: lan1
type: l2 # l2 | l3
mtu: 1500
- id: lan13
type: l2
- id: trunk1
type: l2
vlan:
mode: trunk
allowed: [4, 8]
- id: mgmt
type: l3
cidr: 192.168.100.0/24
dhcp: false
nodes: # nodes (VM/containers)
- name: R1
role: router # router | switch | host
resources:
cpu: 1
ram_mb: 512
mgmt:
ip: 192.168.100.11/24
gw: 192.168.100.1
net: mgmt
interfaces: # order matters: eth1 ↔ adapter2 and so on
- name: eth1
network: lan13
addresses: ["10.0.13.1/24"]
- name: eth0 # MGMT
network: mgmt
routing:
stack: bird # inherited from defaults, can be omitted
protocols:
static:
routes:
- to: 0.0.0.0/0
via: 10.0.13.3
ospf: # if needed
enabled: false
rip:
enabled: false
services: # servers/daemons of the host
- name: sshd
enabled: true
switching: # L2 config for switch nodes
- node: S1
impl: linux-bridge # linux-bridge | ovs
bridges:
- name: br0
ports:
- if: eth1 # to trunk1
vlan:
mode: trunk
allowed: [4, 8]
- if: eth2 # access → VLAN 4
vlan:
mode: access
vid: 4
- if: eth3 # access → VLAN 8
vlan:
mode: access
vid: 8
svis: # VLAN management interfaces (SVI)
- vid: 4
ifname: br0.4
addresses: ["10.0.4.254/24"]
firewall: # High-level ACL-> to nftables
- node: R2
rules:
- id: allow-ospf
match:
in_if: eth1
ip_proto: ospf
action: accept
- id: telnet-from-R1-to-S1
match:
src: 10.0.13.1/32
dst: 10.0.4.254/32
l4: { proto: tcp, dport: 23 }
action: accept
- id: ftp-from-R3-to-S2
match:
src: 10.0.13.3/32
dst: 10.0.6.254/32
l4: { proto: tcp, dports: [20, 21] }
action: accept
- id: drop-rest
action: drop
profiles: # overlays - patches on top of the base description
- name: "all-frr"
description: "Switch all control-plane to FRR"
patches:
- op: replace
path: /defaults/routing/stack
value: frr
- name: "mix-bird-frr-ospf"
description: "BIRD by default, but OSPF on R2 via FRR"
patches:
- op: add
path: /nodes
where:
name: R2
patch:
routing:
protocols:
ospf:
enabled: true
impl: frr
- name: "switch-ovs"
patches:
- op: replace
path: /defaults/switch/impl
value: ovs
tests: # tests (expected result)
- name: ping-R1-to-R3
from: R1
to: 10.0.13.3
expect: success
- name: ping-VLAN-4-R1-to-R3
from: R1
to: 10.0.4.1
expect: success
+607
View File
@@ -0,0 +1,607 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://github.com/asvk-topology/schema/1.0",
"title": "ASVK Topology Configuration Schema",
"description": "JSON Schema for ASVK topology configuration files",
"type": "object",
"required": ["schema", "meta", "provider", "nodes"],
"properties": {
"schema": {
"type": "string",
"description": "Schema identifier",
"pattern": "^asvk\\.topology/[0-9]+\\.[0-9]+$",
"examples": ["asvk.topology/1.0"]
},
"meta": {
"type": "object",
"description": "Metadata for the topology configuration",
"required": ["id", "title"],
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the topology",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"title": {
"type": "string",
"description": "Human-readable name for the topology"
},
"description": {
"type": "string",
"description": "Detailed description of the topology"
}
}
},
"provider": {
"type": "object",
"description": "Provider configuration for VMs/containers",
"required": ["name"],
"properties": {
"name": {
"type": "string",
"description": "Provider name",
"enum": ["virtualbox", "kvm", "container"]
},
"defaults": {
"type": "object",
"description": "Default resource allocation",
"properties": {
"cpu": {
"type": "integer",
"description": "Default CPU cores",
"minimum": 1,
"default": 1
},
"ram_mb": {
"type": "integer",
"description": "Default RAM in MB",
"minimum": 128,
"default": 512
},
"disk_gb": {
"type": "integer",
"description": "Default disk size in GB",
"minimum": 1,
"default": 8
},
"os_image": {
"type": "string",
"description": "Default OS image"
},
"nic_model": {
"type": "string",
"description": "Default NIC model",
"enum": ["virtio", "e1000", "rtl8139"]
},
"promiscuous": {
"type": "string",
"description": "Promiscuous mode setting",
"enum": ["deny", "allow-vms", "allow-all"]
}
}
},
"images": {
"type": "object",
"description": "Custom images for different node types",
"properties": {
"router": { "type": "string" },
"switch": { "type": "string" },
"host": { "type": "string" }
}
}
}
},
"defaults": {
"type": "object",
"description": "Default behavior and software configuration",
"properties": {
"routing": {
"type": "object",
"properties": {
"stack": {
"type": "string",
"enum": ["bird", "frr", "linux"],
"default": "bird"
},
"protocols_enabled": {
"type": "array",
"items": {
"type": "string",
"enum": ["ospf", "rip", "bgp", "static"]
},
"default": []
}
}
},
"switch": {
"type": "object",
"properties": {
"impl": {
"type": "string",
"enum": ["linux-bridge", "ovs"],
"default": "linux-bridge"
}
}
},
"firewall": {
"type": "object",
"properties": {
"impl": {
"type": "string",
"enum": ["nftables", "none"],
"default": "nftables"
}
}
},
"mgmt": {
"type": "object",
"properties": {
"ssh_user": {
"type": "string",
"default": "lab"
},
"ssh_key": {
"type": "string",
"description": "Path to SSH public key"
}
}
}
}
},
"variables": {
"type": "object",
"description": "Global variables that can be referenced in templates",
"additionalProperties": true
},
"networks": {
"type": "array",
"description": "Network definitions (L2 domains, L3 networks, VLAN trunks)",
"items": {
"type": "object",
"required": ["id", "type"],
"properties": {
"id": {
"type": "string",
"description": "Unique network identifier",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"type": {
"type": "string",
"enum": ["l2", "l3"],
"description": "Network type"
},
"mtu": {
"type": "integer",
"description": "MTU for the network",
"minimum": 68,
"maximum": 9000,
"default": 1500
},
"cidr": {
"type": "string",
"description": "CIDR notation for L3 networks",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$"
},
"dhcp": {
"type": "boolean",
"description": "Enable DHCP on this network",
"default": false
},
"vlan": {
"type": "object",
"description": "VLAN configuration for trunk ports",
"properties": {
"mode": {
"type": "string",
"enum": ["access", "trunk"]
},
"allowed": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 4094
},
"description": "Allowed VLAN IDs on trunk"
},
"vid": {
"type": "integer",
"description": "Native VLAN ID for access ports",
"minimum": 1,
"maximum": 4094
}
}
}
}
}
},
"nodes": {
"type": "array",
"description": "Node definitions (VMs/containers)",
"items": {
"type": "object",
"required": ["name", "role"],
"properties": {
"name": {
"type": "string",
"description": "Node name",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"role": {
"type": "string",
"enum": ["router", "switch", "host"],
"description": "Node role/type"
},
"image": {
"type": "string",
"description": "OS image for the node (can reference provider.images)"
},
"resources": {
"type": "object",
"properties": {
"cpu": {
"type": "integer",
"minimum": 1
},
"ram_mb": {
"type": "integer",
"minimum": 128
},
"disk_gb": {
"type": "integer",
"minimum": 1
}
}
},
"mgmt": {
"type": "object",
"description": "Management network configuration",
"properties": {
"ip": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$"
},
"gw": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}$"
},
"net": {
"type": "string"
}
}
},
"interfaces": {
"type": "array",
"description": "Network interfaces (order matters)",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string",
"pattern": "^(eth[0-9]+|lo)$"
},
"network": {
"type": "string"
},
"loopback": {
"type": "boolean",
"description": "Indicates if this is a loopback interface"
},
"addresses": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$"
}
}
},
"anyOf": [
{
"required": ["network"]
},
{
"required": ["loopback"],
"properties": {
"loopback": { "const": true }
}
}
]
}
},
"routing": {
"type": "object",
"properties": {
"stack": {
"type": "string",
"enum": ["bird", "frr", "linux"]
},
"protocols": {
"type": "object",
"properties": {
"static": {
"type": "object",
"properties": {
"routes": {
"type": "array",
"items": {
"type": "object",
"required": ["to", "via"],
"properties": {
"to": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])|0\\.0\\.0\\.0/0$"
},
"via": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}$"
}
}
}
}
}
},
"ospf": {
"type": "object",
"properties": {
"enabled": { "type": "boolean", "default": false },
"impl": {
"type": "string",
"enum": ["bird", "frr"]
}
}
},
"rip": {
"type": "object",
"properties": {
"enabled": { "type": "boolean", "default": false }
}
},
"bgp": {
"type": "object",
"properties": {
"enabled": { "type": "boolean", "default": false },
"asn": { "type": "integer" }
}
}
}
}
}
},
"services": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"enabled": { "type": "boolean", "default": true }
}
}
}
}
}
},
"switching": {
"type": "array",
"description": "L2 switching configuration",
"items": {
"type": "object",
"required": ["node", "impl"],
"properties": {
"node": {
"type": "string",
"description": "Switch node name"
},
"impl": {
"type": "string",
"enum": ["linux-bridge", "ovs"]
},
"bridges": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"ports": {
"type": "array",
"items": {
"type": "object",
"required": ["if"],
"properties": {
"if": {
"type": "string",
"pattern": "^eth[0-9]+$"
},
"vlan": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"enum": ["access", "trunk"]
},
"allowed": {
"type": "array",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 4094
}
},
"vid": {
"type": "integer",
"minimum": 1,
"maximum": 4094
}
}
}
}
}
},
"svis": {
"type": "array",
"description": "Switched Virtual Interfaces (SVI)",
"items": {
"type": "object",
"required": ["vid", "ifname"],
"properties": {
"vid": {
"type": "integer",
"minimum": 1,
"maximum": 4094
},
"ifname": {
"type": "string",
"pattern": "^[a-zA-Z0-9._-]+$"
},
"addresses": {
"type": "array",
"items": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$"
}
}
}
}
}
}
}
}
}
}
},
"firewall": {
"type": "array",
"description": "Firewall configuration",
"items": {
"type": "object",
"required": ["node", "rules"],
"properties": {
"node": { "type": "string" },
"rules": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "action"],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-zA-Z0-9_-]+$"
},
"match": {
"type": "object",
"properties": {
"in_if": { "type": "string" },
"out_if": { "type": "string" },
"src": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$"
},
"dst": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$"
},
"ip_proto": {
"type": "string",
"enum": ["tcp", "udp", "icmp", "ospf", "all"]
},
"l4": {
"type": "object",
"properties": {
"proto": {
"type": "string",
"enum": ["tcp", "udp"]
},
"sport": {
"type": ["integer", "array"],
"items": { "type": "integer" },
"minimum": 1,
"maximum": 65535
},
"dport": {
"type": ["integer", "array"],
"items": { "type": "integer" },
"minimum": 1,
"maximum": 65535
},
"dports": {
"type": ["integer", "array"],
"items": { "type": "integer" },
"minimum": 1,
"maximum": 65535
}
}
}
}
},
"action": {
"type": "string",
"enum": ["accept", "drop", "reject"]
}
}
}
}
}
}
},
"profiles": {
"type": "array",
"description": "Configuration profiles/overlays",
"items": {
"type": "object",
"required": ["name", "patches"],
"properties": {
"name": { "type": "string" },
"description": { "type": "string" },
"patches": {
"type": "array",
"items": {
"type": "object",
"required": ["op", "path"],
"properties": {
"op": {
"type": "string",
"enum": ["add", "replace", "remove"]
},
"path": { "type": "string" },
"value": true,
"where": {
"type": "object",
"description": "Conditional matching for patches"
},
"patch": true
}
}
}
}
}
},
"tests": {
"type": "array",
"description": "Validation tests",
"items": {
"type": "object",
"required": ["name", "from", "to", "expect"],
"properties": {
"name": { "type": "string" },
"from": { "type": "string" },
"to": {
"type": ["string", "object"],
"properties": {
"ip": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}$"
},
"node": { "type": "string" }
}
},
"expect": {
"type": "string",
"pattern": "^(success|failure|timeout|via .*)$"
}
}
}
}
}
}
View File
View File