Skip to content

Command Reference

sat edited this page Aug 16, 2026 · 21 revisions

Command Reference

This page provides a complete reference for all dot2net commands and their options.

Global Usage

dot2net [COMMAND] [OPTIONS] <topology.dot>

Arguments:

  • <topology.dot> - The DOT file describing the network (required)

Common Options:

  • -c, --config <file> - Configuration YAML file (default: input.yaml)
  • -v, --verbose - Enable verbose output

Important: Always run dot2net from the directory containing your configuration files, as the tool references files relative to the current working directory.

Commands

build - Generate Configuration Files

Generates configuration files based on the input topology and configuration templates.

dot2net build [OPTIONS] <topology.dot>

Examples:

# Basic usage (uses input.yaml by default)
dot2net build input.dot

# Specify custom config file
dot2net build -c custom.yaml input.dot

# With verbose output
dot2net build -v input.dot

# With CPU profiling
dot2net build -p profile.out input.dot

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net build -c input.yaml input.dot

This generates:

  • Node directories: r1/, r2/, r3/ containing device-specific configuration files
  • TiNET deployment: spec.yaml for TiNET network emulation
  • Containerlab deployment: topo.yaml for Containerlab container-based labs

Generated files for each router include:

r1/etc/frr/frr.conf    # FRR routing daemon configuration
r1/etc/frr/daemons     # FRR daemon startup configuration
r1/etc/frr/vtysh.conf  # FRR CLI configuration

Sample r1/etc/frr/frr.conf content:

ip forwarding
!
router ospf
 ospf router-id 10.0.255.1
 network 10.0.0.0/24 area 0
!
interface eth0
 ip address 10.0.0.1/24
!

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file
--dir -d commands Directory name for per-device configuration files
--name (the topology's own) Name this lab, in place of the topology's name:. Generate one topology under two names to deploy it twice at once — see Running one topology twice. Every command that reads a topology takes it, so files and clean name the same files build wrote
--profile -p (empty) Profile CPU performance and output to specified file
--verbose -v false Enable verbose output

Running one topology twice

A lab's containers are named after the lab, so two labs from one topology collide unless they are told apart. --name is how: it replaces the topology's own name: for that build, and every platform's file takes the name up in the way that platform namespaces its containers.

mkdir lab0 lab1
cd lab0 && dot2net build -c ../input.yaml --name lab0 ../input.dot
cd ../lab1 && dot2net build -c ../input.yaml --name lab1 ../input.dot
Platform What carries the name
containerlab the lab, so a container is clab-lab0-r1
Kathara the device, so lab.conf holds lab0_r1 and the container is labelled with it
TiNET the node, so spec.yaml holds lab0_r1 — TiNET names a container after the node and nothing else

What does not change: the nodes are still r1, r2, r3. Their files are still written to r1/etc/frr/frr.conf, the configuration inside is untouched, and you still say exec r1 — each entry script knows how its own platform spells the name.

A name has to be usable as part of a container's name: it must start with a letter or digit and hold only letters, digits, and _, ., -. dot2net says so at build time rather than letting the platform fail at deploy.

Output:

  • Node-specific configuration directories (e.g., r1/, r2/, r3/)
  • Platform-specific deployment files (spec.yaml for TiNET, topo.yaml for Containerlab)

params - List Available Parameters

Lists all parameters available for use in configuration templates.

dot2net params [OPTIONS] <topology.dot>

Examples:

# Show basic parameters
dot2net params input.dot

# Show all parameters including relative ones
dot2net params -a input.dot

# Output to file
dot2net params input.dot > params.txt

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net params -c input.yaml input.dot

Sample output (excerpt):

network:ospf_simple {{ .name }} = ospf_simple
node:r1 {{ .image }} = quay.io/frrouting/frr:8.5.4
node:r1 {{ .ip_loopback }} = 10.0.255.1
node:r1 {{ .kind }} = linux
node:r1 {{ .name }} = r1
interface:r1.eth0 {{ .conn_name }} = conn0
interface:r1.eth0 {{ .ip_addr }} = 10.0.0.1
interface:r1.eth0 {{ .ip_net }} = 10.0.0.0/24
interface:r1.eth0 {{ .ip_plen }} = 24
interface:r1.eth0 {{ .name }} = eth0
interface:r1.eth0 {{ .node_name }} = r1
interface:r1.eth0 {{ .node_ip_loopback }} = 10.0.255.1

This shows how parameters are automatically assigned:

  • IP addresses: Loopback (10.0.255.x) and interface IPs (10.0.0.x/24)
  • Cross-object references: {{ .conn_name }}, {{ .node_name }}, etc.
  • Platform-specific parameters: Container bind mounts, image specifications

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file
--all -a false Show all parameters including relative ones
--verbose -v false Enable verbose output

Output Format:

network {{ .network_name }} = example_network
node:r1 {{ .name }} = r1
node:r1 {{ .ip_loopback }} = 192.168.1.1

visual - Visualize IP Address Assignment

Generates a DOT file showing IP address assignments for visualization.

dot2net visual [OPTIONS] <topology.dot>

Examples:

# Generate visualization and create PDF
dot2net visual input.dot | dot -Tpdf > addr.pdf

# Visualize specific layer only
dot2net visual -l ipv4 input.dot > ipv4_layout.dot

# SVG output
dot2net visual input.dot | dot -Tsvg > addr.svg

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net visual -c input.yaml input.dot

Sample output:

digraph G {
	r1->r2 [ dir=none, headlabel="eth0\n10.0.0.2", label="10.0.0.0/24", taillabel="eth0\n10.0.0.1" ];
	r2->r3 [ dir=none, headlabel="eth0\n10.0.1.2", label="10.0.1.0/24", taillabel="eth1\n10.0.1.1" ];
	r1 [ label="r1\nlo: 10.0.255.1" ];
	r2 [ label="r2\nlo: 10.0.255.2" ];
	r3 [ label="r3\nlo: 10.0.255.3" ];
}

This DOT output shows:

  • Node labels: Router names with loopback IP addresses
  • Edge labels: Interface names and IP addresses on both ends
  • Network labels: Subnet information for each link (10.0.0.0/24, 10.0.1.0/24)

Generate a visual network diagram:

dot2net visual -c input.yaml input.dot | dot -Tpdf > ospf_network.pdf

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file
--layer -l (all layers) Specify layer name to visualize
--verbose -v false Enable verbose output

Requirements: GraphViz must be installed to generate visual output files.


data - Export Parameter Data

Outputs all calculated parameters in JSON format for external processing.

dot2net data [OPTIONS] <topology.dot>

Examples:

# Export to JSON file
dot2net data input.dot > network_data.json

# Use with jq for processing
dot2net data input.dot | jq '.nodes[].name'

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net data -c input.yaml input.dot

Sample output (excerpt):

{
  "name": "ospf_simple",
  "nodes": [
    {
      "name": "r1",
      "params": {
        "image": "quay.io/frrouting/frr:8.5.4",
        "ip_loopback": "10.0.255.1",
        "kind": "linux",
        "name": "r1"
      },
      "interfaces": [
        {
          "name": "eth0",
          "params": {
            "conn_name": "conn0",
            "ip_addr": "10.0.0.1",
            "ip_net": "10.0.0.0/24",
            "ip_plen": "24",
            "node_name": "r1",
            "node_ip_loopback": "10.0.255.1"
          }
        }
      ]
    }
  ]
}

Extract specific information with jq:

# Get all node names
dot2net data -c input.yaml input.dot | jq -r '.nodes[].name'

# Get all IP addresses
dot2net data -c input.yaml input.dot | jq -r '.nodes[].interfaces[].params.ip_addr'

# Get network topology summary
dot2net data -c input.yaml input.dot | jq '{network: .name, node_count: (.nodes | length)}'

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file

files - List Generated Files

Shows what files would be generated by the build command without actually creating them.

dot2net files [OPTIONS] <topology.dot>

Examples:

# List all files that would be generated
dot2net files input.dot

# With verbose details
dot2net files -v input.dot

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net files -c input.yaml input.dot

Sample output:

r1/etc/frr/daemons
r1/etc/frr/frr.conf
r1/etc/frr/vtysh.conf
r2/etc/frr/daemons
r2/etc/frr/frr.conf
r2/etc/frr/vtysh.conf
spec.yaml
topo.yaml

This shows all files that would be created by dot2net build:

  • Node configuration files: laid out by the path they take inside the container, so path: /etc/frr/frr.conf is written to r1/etc/frr/frr.conf
  • Platform deployment files: spec.yaml (TiNET), topo.yaml (containerlab), kathara/lab.conf (Kathara)

With -v each file that reaches a container is listed with where it goes and how it gets there:

r1/etc/frr/frr.conf	/etc/frr/frr.conf	mount
r1/staging/etc/motd	/etc/motd	copy

The plain listing stays a list of paths, because dot2net clean reads it.

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file
--verbose -v false List the container path and how each file is provided

clean - Delete Generated Files

Removes configuration files that were generated by previous build commands.

dot2net clean [OPTIONS] <topology.dot>

Examples:

# Delete all generated files
dot2net clean input.dot

# Preview what would be deleted (dry run)
dot2net clean --dry-run input.dot

# With verbose output
dot2net clean -v input.dot

Example with ospf_simple topology:

cd topologies/ospf_simple/
dot2net clean --dry-run -c input.yaml input.dot

Sample output:

Would delete: r1/etc/frr/daemons
Would delete: r1/etc/frr/frr.conf
Would delete: r1/etc/frr/vtysh.conf
Would delete: r2/etc/frr/daemons
Would delete: r2/etc/frr/frr.conf
Would delete: r2/etc/frr/vtysh.conf
Would delete: r3/etc/frr/daemons
Would delete: r3/etc/frr/frr.conf
Would delete: r3/etc/frr/vtysh.conf
Would delete: spec.yaml
Would delete: topo.yaml

Actually delete the files:

dot2net clean -c input.yaml input.dot

The --dry-run option is especially useful for:

  • Verification: Checking what files would be affected before deletion
  • Safety: Avoiding accidental deletion of important files
  • Debugging: Understanding what files dot2net considers "generated"

Options

Flag Alias Default Description
--config -c input.yaml Specify the configuration YAML file
--verbose -v false Enable verbose output
--dry-run false Show what would be deleted without actually deleting

Entry Point Scripts

With module_config.<module>.generate_scripts: true, dot2net writes a script beside the lab — containerlab.sh, tinet.sh, kathara/kathara.sh — that carries the part which differs between platforms and is easy to get wrong.

sudo ./containerlab.sh deploy
sudo ./containerlab.sh exec r1 vtysh -c "show ip ospf neighbor"
sudo ./containerlab.sh collect            # copy out what the lab collects
sudo ./containerlab.sh destroy            # teardown, collect, destroy, clean up

exec reaches the container through docker on all three platforms, so the words you quoted stay quoted: vtysh -c "show ip ospf neighbor" arrives as two arguments, not five. The platforms' own exec commands take the whole command as one string, which loses that.

deploy makes the bridges the topology names before handing over to the platform: containerlab refuses to deploy while a bridge its topology names does not exist, and its check runs before any stage, so nothing inside the lab can create one. Anything you write after deploy is passed on to the platform's own command — sudo ./containerlab.sh deploy --network lab7 --ipv4-subnet 172.29.7.0/24 places that lab's management network, which is how several labs run side by side. TiNET brings a lab up in two commands, so its script has nowhere to put an extra argument and says so rather than dropping it.

destroy takes the lab down in four steps:

  1. the lab's teardown commands, run inside each node while it is still up
  2. the files the lab collects, copied to collected/<node>/<path>
  3. the platform's own destroy
  4. what the lab left on the machine — for containerlab, the bridges setup-bridges.sh made

A step that fails is named and the rest still run: a lab left standing because something could not be copied is worse than the missing file. The script ends non-zero so that whatever called it knows which steps failed.

Variable Meaning
DOT2NET_COLLECT_DIR Where collected files go (default collected)

A lab is named by the topology, and the script deploys and destroys it under that name. To run one topology more than once at a time, generate it more than once, giving each build a name of its own:

dot2net build -c input.yaml --name lab0 input.dot    # in one directory
dot2net build -c input.yaml --name lab1 input.dot    # in another

Each build's files name their own lab, so the two can be deployed side by side and each script reaches only its own containers. You still say exec r1: the script knows how its platform spells the name.

Renaming a lab at deploy time is not offered. containerlab's deploy --name renames the lab but its destroy takes the name from the topology file whatever --name says, so a renamed lab cannot be taken down again — and the destroy reports success while leaving everything running. Naming the lab when it is generated has no such gap, and works the same way on all three platforms.

The scripts are written executable, and each finds its own files, so they can be run from anywhere. What a lab tears down and collects is declared in the topology — see File Output — and each module's page says what its own script does: containerlab, TiNET, Kathara.

Common Workflows

Development Workflow

# 1. Design and test
dot2net files input.dot                         # Preview generated files
dot2net params input.dot                        # Check parameter assignments
dot2net build -v input.dot                      # Generate with verbose output

# 2. Deploy and test
sudo containerlab deploy --topo topo.yaml       # Deploy with Containerlab
# or
tinet up -c spec.yaml | sudo sh -x              # Deploy with TiNET

# 3. Cleanup
dot2net clean input.dot                         # Remove generated files

Debugging Workflow

# Check parameter assignments
dot2net params -a input.dot > debug_params.txt

# Generate with detailed output
dot2net build -v input.dot 2> debug_build.log

# Visualize IP assignments
dot2net visual input.dot | dot -Tpdf > debug_layout.pdf

Exit Codes

  • 0: Success
  • 1: General error (invalid arguments, file not found, configuration conflicts, etc.)

Notes

  • The DOT file is always required as a positional argument
  • Configuration files are referenced relative to the current working directory
  • Use --verbose flag for detailed output when troubleshooting
  • The --dry-run option for clean command is useful for safely previewing deletions
  • Default configuration file name is input.yaml to match project conventions

See Also

Clone this wiki locally