| name | netgraph-dsl |
| description | NetGraph scenario DSL for defining network topologies, traffic demands, failure policies, and analysis workflows in YAML. Use when: creating or editing .yaml/.yml network scenarios, defining nodes/links/groups, writing adjacency rules, configuring selectors or blueprints, setting up traffic matrices or failure policies, debugging DSL syntax or validation errors, or asking about NetGraph scenario structure. |
| license | MIT |
| metadata | [object Object] |
NetGraph DSL
Define network simulation scenarios in YAML format.
Quick Start: See Minimal Example below. Complete Reference: See references/REFERENCE.md for full documentation.
Instructions
When working with NetGraph scenarios:
- Creating new scenarios: Start with the Minimal Example, then add sections as needed
- Editing existing scenarios: Identify the relevant section (network, traffic_matrix_set, failure_policy_set, etc.)
- Understanding selection: Review Selection Models to understand path-based vs condition-based selection
- Debugging issues: Check Common Pitfalls and Validation Checklist
- Complex topologies: Use Blueprints for reusable patterns
- Failure simulation: Define Risk Groups before creating failure policies
Refer to specific sections below for detailed syntax and examples.
Quick Reference
| Section | Purpose |
|---|---|
network |
Topology: nodes, links, groups, adjacency (required) |
blueprints |
Reusable topology templates |
components |
Hardware library for cost/power modeling |
risk_groups |
Failure correlation groups |
vars |
YAML anchors for value reuse |
traffic_matrix_set |
Traffic demand definitions |
failure_policy_set |
Failure simulation rules |
workflow |
Analysis execution steps |
seed |
Master seed for reproducibility |
Minimal Example
network:
nodes:
A: {}
B: {}
links:
- source: A
target: B
link_params:
capacity: 100
cost: 1
Core Patterns
Selection Models
The DSL implements two distinct selection patterns:
1. Path-based Node Selection (adjacency rules, traffic demands, workflow steps)
- Uses regex patterns on hierarchical node names
- Supports capture group-based grouping
- Supports attribute-based grouping (
group_by) - Supports attribute filtering (
matchconditions) - Supports
active_onlyfiltering
2. Condition-based Entity Selection (failure rules, membership rules, risk group generation)
- Works on nodes, links, or risk_groups (
entity_scope) - Uses only attribute-based filtering (
conditions) - No path/regex patterns (operates on all entities of specified type)
These patterns share common primitives (condition evaluation, match specification) but serve different purposes and should not be confused.
For comprehensive details on entity creation flows, processing steps, and comparison tables, see the Entity Creation Architecture section in the full reference.
Nodes and Links
network:
nodes:
Seattle:
attrs: # Custom attributes go here
role: core
risk_groups: ["RG1"]
disabled: false
Portland:
attrs:
role: edge
links:
- source: Seattle
target: Portland
link_params: # Required wrapper for link parameters
capacity: 100
cost: 10
attrs:
distance_km: 280
link_count: 2 # Parallel links
Node Groups
network:
groups:
leaf:
node_count: 4
name_template: "leaf-{node_num}"
attrs:
role: leaf
Creates: leaf/leaf-1, leaf/leaf-2, leaf/leaf-3, leaf/leaf-4
Template Syntaxes
| Syntax | Example | Context |
|---|---|---|
[1-3] |
dc[1-3]/rack |
Group names, risk groups |
$var/${var} |
pod${p}/leaf |
Adjacency & demand selectors |
{node_num} |
srv-{node_num} |
name_template field |
These are NOT interchangeable. See REFERENCE.md for details.
Bracket Expansion
network:
groups:
dc[1-3]/rack[a,b]: # Cartesian product
node_count: 4
name_template: "srv-{node_num}"
Creates: dc1/racka, dc1/rackb, dc2/racka, dc2/rackb, dc3/racka, dc3/rackb
Scope: Bracket expansion works in group names, risk group definitions (including children), and risk group membership arrays. Component names and other fields treat brackets as literal characters.
Adjacency Patterns
network:
adjacency:
- source: /leaf
target: /spine
pattern: mesh # Every source to every target
link_params:
capacity: 100
- source: /group_a # 4 nodes
target: /group_b # 2 nodes
pattern: one_to_one # Pairwise with modulo wrap (sizes must have multiple factor)
Selectors with Conditions
adjacency:
- source:
path: "/datacenter"
match:
logic: and # "and" or "or"; defaults vary by context (see below)
conditions:
- attr: role
operator: "=="
value: leaf
target: /spine
pattern: mesh
Operators: ==, !=, <, <=, >, >=, contains, not_contains, in, not_in, any_value, no_value
Logic defaults by context:
| Context | Default logic |
Rationale |
|---|---|---|
Adjacency match |
"or" |
Inclusive: match any condition |
Demand match |
"or" |
Inclusive: match any condition |
| Membership rules | "and" |
Precise: must match all conditions |
| Failure rules | "or" |
Inclusive: match any condition |
Capturing Groups for Grouping
# Single capture group creates groups by captured value
source: "^(dc[1-3])/.*" # Groups: dc1, dc2, dc3
# Multiple capture groups join with |
source: "^(dc\\d+)/(spine|leaf)/.*" # Groups: dc1|spine, dc1|leaf, etc.
Variable Expansion
adjacency:
- source: "plane${p}/rack"
target: "spine${s}"
expand_vars:
p: [1, 2]
s: [1, 2, 3]
expansion_mode: cartesian # or "zip" (equal-length lists required)
pattern: mesh
Blueprints
blueprints:
clos_pod:
groups:
leaf:
node_count: 4
name_template: "leaf-{node_num}"
spine:
node_count: 2
name_template: "spine-{node_num}"
adjacency:
- source: /leaf
target: /spine
pattern: mesh
link_params:
capacity: 100
network:
groups:
pod[1-2]:
use_blueprint: clos_pod
parameters:
leaf.node_count: 6 # Override defaults
Traffic Demands
traffic_matrix_set:
production:
- source: "^dc1/.*"
sink: "^dc2/.*"
demand: 1000
mode: pairwise # or "combine"
flow_policy_config: SHORTEST_PATHS_ECMP
Flow policies: SHORTEST_PATHS_ECMP, SHORTEST_PATHS_WCMP, TE_WCMP_UNLIM, TE_ECMP_16_LSP, TE_ECMP_UP_TO_256_LSP
Failure Policies
failure_policy_set:
single_link:
fail_risk_groups: false # Expand to shared-risk entities
modes: # Weighted modes (one selected per iteration)
- weight: 1.0
rules:
- entity_scope: link # node, link, or risk_group
rule_type: choice # all, choice, or random
count: 1
# Optional: weight_by: capacity # Weighted sampling by attribute
Rule types: all (select all matches), choice (sample count), random (each with probability)
Risk Groups
Risk groups model failure correlation (shared infrastructure, geographic regions, vendor dependencies, or any custom domain). Three methods:
Direct definition:
risk_groups:
- name: "RG1" # Full form
- "RG2" # String shorthand (equivalent to {name: "RG2"})
Membership rules (assign entities by attribute matching):
risk_groups:
- name: HighCapacityLinks
membership:
entity_scope: link # node, link, or risk_group
match:
logic: and # "and" or "or" (default: "and" for membership)
conditions:
- attr: capacity
operator: ">="
value: 1000
Generate blocks (create groups from unique attribute values):
risk_groups:
- generate:
entity_scope: node # node or link only
group_by: region # Any attribute to group by
name_template: "Region_${value}"
Validation: Risk group references are validated at load time (undefined references and circular hierarchies detected).
See REFERENCE.md for complete details.
Workflow
workflow:
- step_type: NetworkStats
name: stats
- step_type: MaximumSupportedDemand
name: msd
matrix_name: production
alpha_start: 1.0
resolution: 0.05
- step_type: TrafficMatrixPlacement
name: placement
matrix_name: production
failure_policy: single_link
iterations: 1000
alpha_from_step: msd # Reference MSD result
alpha_from_field: data.alpha_star
- step_type: MaxFlow
source: "^(dc[1-3])$"
sink: "^(dc[1-3])$"
mode: pairwise
failure_policy: single_link
iterations: 1000
seed: 42 # Optional: for reproducibility
Step types: BuildGraph, NetworkStats, MaxFlow, TrafficMatrixPlacement, MaximumSupportedDemand, CostPower
Common Pitfalls
1. Custom fields must go in attrs
# WRONG
nodes:
A:
my_field: value # Error!
# CORRECT
nodes:
A:
attrs:
my_field: value
2. Link parameters require link_params wrapper
# WRONG
links:
- source: A
target: B
capacity: 100 # Error!
# CORRECT
links:
- source: A
target: B
link_params:
capacity: 100
3. one_to_one requires compatible sizes
Sizes must have a multiple factor (4-to-2 OK, 3-to-2 ERROR).
4. Path patterns are anchored at start
path: "leaf" # Only matches names STARTING with "leaf"
path: ".*leaf.*" # Matches "leaf" anywhere
Note: Leading / is stripped and has no effect. /leaf and leaf are equivalent. All paths are relative to the current scope (blueprint instantiation path or network root).
5. Variable syntax uses $ prefix
# WRONG (conflicts with regex {m,n})
source: "{dc}/leaf"
# CORRECT
source: "${dc}/leaf"
6. zip requires equal-length lists
# WRONG
expand_vars:
a: [1, 2]
b: [x, y, z] # Length mismatch!
expansion_mode: zip
7. Processing order matters
- Groups and direct nodes created
- Node overrides applied
- Adjacency and blueprint adjacencies expanded
- Direct links created
- Link overrides applied
Overrides only affect entities that exist at their processing stage.
Validation Checklist
- Custom fields inside
attrs - Link parameters inside
link_params - Referenced blueprints exist
- Node names in direct links exist
-
one_to_onesizes have multiple factor -
ziplists have equal length - Selectors have at least one of:
path,group_by,match
More Information
- Full DSL Reference - Complete field documentation, all operators, workflow steps
- Working Examples - 17 complete scenarios from simple to advanced