19 KiB
Mininet Topology JSON Language: Rationale and Reference
1. Purpose and design rationale
This document explains why the topology language has its current shape, then serves as a reference for its JSON fields, defaults, and semantic constraints. The starting point is the assignment: describe hosts, switches, a router, two subnets, and DHCP configuration in a form that can also express other valid topologies.
1.1 Describe network intent
The JSON describes the desired network and its configuration. A reader should be able to identify participants, connections, addresses, and services without tracing a sequence of Python or shell commands. This makes a topology easier to inspect and change independently of the code that constructs it.
The design combines top-down modeling with bottom-up implementability. We start with the concepts needed to describe the network, while requiring each concept to have a clear translation into Mininet and Linux networking primitives. Nodes, interfaces, links, network-stack settings, and processes provide that translation without requiring a separate abstraction for every assignment step.
This is why the language distinguishes a router from a host even though both can use similar underlying construction mechanisms. Their network roles differ, so the description expresses that distinction. Conversely, DHCP is a service on a node rather than a new kind of network node.
1.2 Give each property a clear owner
The network structure leads to five core entities:
| Entity | Question it answers |
|---|---|
| Node | What participates in the network, and what role does it have? |
| Interface | Where does a node attach, and how is that attachment configured? |
| Link | Which two interfaces are connected? |
| Node settings | How should the node's network stack behave? |
| Service | Which service runs on a node, and where is it bound? |
An interface belongs to its node because addressing, MAC, and MTU describe that node's attachment to the network. A link references two interfaces and owns connection properties such as delay or bandwidth. Keeping endpoint configuration out of links gives each property one clear place in the description.
The same interface structure works for hosts, routers, and switches. An interface is an attachment point even when it has no IP address, which makes unaddressed switch ports natural to represent. Addressing is therefore optional, while MAC and MTU remain independent fields.
1.3 Separate behavior from services
Forwarding and reverse-path filtering describe network-stack behavior and
belong in node settings.
A DHCP server is a running service with its own configuration, so it belongs in
services.
This separation lets a node host a service without changing its node type.
A service's node and interface fields describe its placement.
Its settings describe its behavior, such as the DHCP address range and
advertised gateway.
Keeping placement outside service-specific settings preserves the same shape
for future service types.
1.4 Make identity explicit where it matters
Logical interface tags such as lan and wan express the meaning of a
connection without depending on generated operating-system interface names.
Explicit tags let a topology identify a particular attachment point.
The auto selector avoids unnecessary port naming when only connectivity
matters, as is often the case for a switch.
An omitted interface set allows automatic allocation as needed. An explicitly declared set defines the available ports, so automatic selection must stay within that set. This distinction preserves both convenience and the ability to express a fixed interface limit; an explicit empty set consequently means zero available ports.
1.5 Describe configuration without recording runtime state
Static addressing declares a known address and, optionally, a default gateway. DHCP addressing declares how configuration will be obtained; the acquired address and lease are runtime results. The language therefore does not require a DHCP client to contain an address that is not yet known.
The same boundary excludes learned ARP entries, packet counters, captures, and experimental commands from the topology description. Those observations change as the network runs, while the declared topology continues to describe its configuration intent.
1.6 Keep the language small and predictable
The current assignment needs a static default gateway, rather than a general routing-policy language. It needs a DHCP service with an address range and an optional advertised gateway, rather than arbitrary daemon command lines. The chosen fields cover those requirements while leaving settings and services as clear places for future extensions.
Unknown fields are rejected so a misspelled setting cannot silently change the meaning of a topology. The reference below defines the supported vocabulary and the constraints that make declarations consistent. It proceeds from the entity model through nodes, interfaces, links, and services, then collects the grammar and semantic rules before a complete example.
For setup and usage, see the README. Its Architecture section describes the Python processing pipeline, generated code, and execution behavior.
2. High-level entity model
The current grammar is:
Network
├── Nodes
│ ├── name
│ ├── type
│ ├── interfaces
│ └── settings
│
├── Links
│ ├── name?
│ ├── endpoints
│ │ ├── node
│ │ └── interface
│ └── settings
│
└── Services
├── type
├── node
├── interface
└── settings
The actual JSON keys are lowercase: nodes, links, and services.
Each top-level list may be omitted and defaults to an empty list.
Node interfaces and node/link settings are optional.
Service settings must contain the fields required by its type.
The main entities intentionally have different responsibilities.
Node
identifies a network participant
Link
connects two network attachment points
Service
represents a process or daemon running on a node
Common entities used in these entities are:
Interface
identifies a network attachment point owned by a node
Settings
configure the node/link/service or its networking stack
3. Nodes
A node represents a logical network participant.
The current structure is:
Node
├── name
├── type
├── interfaces
└── settings
3.1 Node name
name is the logical identifier used by the rest of the topology.
For example:
{
"name": "r0",
"type": "router"
}
Node names are expected to be unique.
Duplicate node names are invalid.
3.2 Node type
The currently supported node types are:
host
switch
router
A host is an end system.
A switch is an autonomous Layer-2 learning switch.
A router connects IP networks and supports forwarding and reverse-path-filter
settings.
Selecting router does not implicitly enable forwarding.
3.3 Node settings
settings contains configuration that changes the behavior of the node itself.
For a router, the currently supported settings are:
"settings": {
"ip_forward": true,
"rp_filter": false
}
These values configure the networking behavior of the node namespace. Omitted router settings leave the corresponding behavior unspecified. Hosts and switches currently accept only empty settings objects.
They are not modeled as services because they do not represent independent user-space processes.
The distinction is:
Node settings
-> properties of the node or its networking stack
Services
-> processes or daemons running on the node
Node settings are type-specific.
Unknown settings for the selected node type are invalid.
4. Interfaces
Interfaces belong to nodes.
This is a deliberate modeling decision.
Node owns Interfaces
Link connects Interfaces
An interface is broader than an object that merely owns an IP address.
It is a network attachment point with optional Layer-3 configuration and optional interface-level properties.
Conceptually:
Interface
=
network attachment point
+ optional L3 configuration
+ optional interface properties
A host or router interface will commonly have Layer-3 addressing.
A Layer-2 switch port normally will not.
Using one interface abstraction for all node types keeps link endpoints uniform.
4.1 Logical interface tags
Interfaces are declared as members of the interfaces object.
The JSON key is the logical interface tag.
For example:
"interfaces": {
"lan": {
"addressing": "static",
"address": "192.168.1.1/24"
},
"wan": {
"addressing": "static",
"address": "192.168.2.1/24"
}
}
lan and wan are topology-level identifiers.
They are not required to be the real Linux interface names.
Logical tags identify interfaces within the JSON independently of generated operating-system interface names.
The same mechanism may be used for meaningful switch-port names.
For example:
"interfaces": {
"client1": {},
"client2": {},
"server": {},
"uplink": {}
}
4.2 Interface properties
The current interface structure is flat.
There is no nested addressing object.
The currently modeled properties are:
addressing? static | dhcp | none
address? required with static addressing
gateway? optional with static addressing
mac? optional interface property
mtu? optional interface property
Possible future interface properties can be added at the same level.
4.3 Addressing semantics
The supported addressing values are:
static
dhcp
none
The addressing field is optional.
Omitting it is semantically equivalent to:
"addressing": "none"
Therefore these two declarations mean the same thing:
"p1": {}
"p1": {
"addressing": "none"
}
Both mean that no Layer-3 addressing configuration is requested.
Static addressing
A static interface is written as:
"net0": {
"addressing": "static",
"address": "192.168.2.10/24",
"gateway": "192.168.2.1"
}
address is required.
gateway is optional.
The gateway is kept with static interface configuration because this matches the simple configuration model used by traditional Linux network configuration.
For the scope of this assignment, this is simpler than introducing a general routing language.
DHCP addressing
A DHCP interface is written as:
"net0": {
"addressing": "dhcp"
}
A DHCP interface does not contain a predetermined address or gateway.
Those values are runtime configuration learned from the DHCP server.
The resulting distinction is:
static
address and optional gateway are configured locally
dhcp
address and gateway are learned dynamically
none / omitted
no L3 configuration is requested
4.4 Switch interfaces
Switch ports use the same interface abstraction.
For example, a switch with a fixed set of four logical ports may be written as:
{
"name": "s1",
"type": "switch",
"interfaces": {
"p1": {},
"p2": {},
"p3": {},
"uplink": {}
}
}
This is useful when link placement should refer to specific switch ports.
If exact port identity does not matter, the interfaces field may be omitted
and links may use automatic interface allocation.
4.5 Omitted interfaces versus an empty interface set
The distinction between these two forms is intentional.
{
"name": "s1",
"type": "switch"
}
means:
interface set omitted
-> dynamic interface set
while:
{
"name": "s1",
"type": "switch",
"interfaces": {}
}
means:
interface set explicitly declared
-> fixed interface set containing zero interfaces
This distinction is important for the semantics of auto.
4.6 Connected and unused interfaces
An interface requesting addressing, an address, a gateway, a MAC address, or an MTU must be attached to a link. Unused empty interface declarations may remain in a fixed interface pool. An interface used by a service must also be attached to a link.
5. Links
A link is a first-class entity connecting exactly two endpoints.
The current structure is:
Link
├── name?
├── endpoints
│ ├── endpoint A
│ │ ├── node
│ │ └── interface
│ └── endpoint B
│ ├── node
│ └── interface
└── settings
Keeping the endpoints wrapper is intentional.
A link may carry properties other than its endpoints, so flattening the link into a raw pair would make future link-level configuration awkward.
5.1 Explicit interface references
An endpoint may reference an explicitly declared interface.
For example:
{
"node": "r0",
"interface": "lan"
}
The referenced interface tag must exist on that node.
5.2 Automatic interface allocation
An endpoint may instead use:
{
"node": "s1",
"interface": "auto"
}
The meaning of auto depends on whether the node declared an interface set.
If interfaces is omitted:
dynamic interface set
-> auto may allocate/create interfaces as needed
If interfaces is explicitly declared:
fixed interface set
-> auto selects an unused declared interface
-> auto must not silently create an additional interface
For example:
"interfaces": {
"p1": {},
"p2": {},
"p3": {},
"uplink": {}
}
allows an explicit link to select:
"interface": "uplink"
or an automatic link to select one of the remaining unused ports.
Explicit references reserve their interfaces before auto selections are made.
Each auto selection consumes the first remaining declared interface in
interface declaration order, following link and endpoint order.
If the fixed interface pool is exhausted, the topology is invalid.
5.3 Why interfaces remain under nodes
Interfaces remain under nodes because they may carry or receive:
- addressing configuration,
- MAC configuration,
- MTU configuration,
- service bindings,
- future interface-specific properties.
The selected relationship therefore remains:
Node owns Interface
Link references Interface
5.4 Link settings
Links contain a settings object for provisioning properties.
The supported provisioning fields are:
bandwidth_mbps?
delay_ms?
loss_percent?
jitter_ms?
Example:
{
"endpoints": [
{
"node": "h1",
"interface": "net0"
},
{
"node": "s1",
"interface": "auto"
}
],
"settings": {
"bandwidth_mbps": 100,
"delay_ms": 1.5,
"loss_percent": 0.1
}
}
Bandwidth is expressed in megabits per second, delay and jitter in milliseconds, and loss as a percentage.
The allowed ranges are:
bandwidth_mbps > 0
delay_ms >= 0
jitter_ms >= 0
0 <= loss_percent <= 100
6. Services
A service represents a process or daemon running on a topology node.
The generic structure is:
Service
├── type
├── node
├── interface
└── settings
The currently supported service type is:
dhcp-server
Example:
{
"type": "dhcp-server",
"node": "r0",
"interface": "lan",
"settings": {
"range": {
"start": "192.168.1.100",
"end": "192.168.1.200"
},
"gateway": "192.168.1.1"
}
}
6.1 Service binding
node and interface describe where the service runs and where it is bound.
They therefore remain outside settings.
The service interface grammar reserves:
<tag>
auto
all
The validity and meaning of special selectors are service-type-specific.
A DHCP service accepts a specific declared interface tag.
The service also supports auto only when exactly one suitable statically
addressed interface can be selected unambiguously from the declared set.
The DHCP server does not support all.
6.2 DHCP settings
The current DHCP server settings are:
range.start
range.end
gateway?
The service gateway is the gateway advertised to DHCP clients.
This is distinct from a static interface gateway.
static interface gateway
-> locally configured default gateway
DHCP service gateway
-> gateway distributed to DHCP clients
7. Grammar summary
Node
name
required unique logical node identifier
type
host | switch | router
interfaces
optional map of logical interface tags to Interface objects
settings
optional node-type-specific configuration
Interface
<tag>
logical interface identifier
addressing
optional: static | dhcp | none
omission is equivalent to none
address
required when addressing = static
forbidden otherwise
gateway
optional when addressing = static
forbidden otherwise
mac
optional
mtu
optional
Link
name
optional logical link name
endpoints
exactly two endpoints
endpoint.node
node name
endpoint.interface
declared interface tag | auto
settings.bandwidth_mbps
optional
settings.delay_ms
optional
settings.loss_percent
optional
settings.jitter_ms
optional
Service
type
currently dhcp-server
node
node on which the service runs
interface
interface tag | auto | all
validity depends on service type
settings
service-type-specific configuration
8. Strict grammar
Unknown fields and unsupported tokens are invalid.
For example, ip_foward is not an alias for ip_forward, and bananas is not
an addressing mode.
Field names, value types, and closed token sets define the JSON grammar.
Cross-references and network constraints define semantic validity.
A recognized static addressing mode without an address is therefore a
semantic error, as is a link referring to an unknown node.
Only the fields described in this reference are currently supported. Additional node types, services, or settings require a language extension.
9. Semantic constraints
A topology must satisfy the following constraints in addition to the JSON grammar. Invalid configurations include:
- duplicate node names,
- duplicate explicit link names,
- empty logical names,
- reserved interface tags,
- static interfaces without an address,
- invalid IPv4/CIDR syntax,
- invalid gateway syntax,
- gateways outside the interface subnet,
- addresses or gateways used with DHCP or no addressing,
- invalid MAC syntax,
- invalid MTU values,
- explicit link references to unknown nodes,
- explicit link references to unknown interfaces,
- explicit interface reuse across links,
- fixed interface-pool exhaustion caused by
auto, - invalid link provisioning ranges,
- services referencing unknown nodes,
- services referencing unknown interfaces,
- DHCP services bound to interfaces without static addressing,
- invalid DHCP IPv4 ranges,
- reversed DHCP ranges,
- DHCP range values outside the bound interface subnet,
- DHCP network or broadcast addresses,
- DHCP pools that include the server address,
- DHCP pools that include the advertised gateway.
Switch interfaces may not request Layer-3 addressing. Only one static default gateway is supported per node. Configured interfaces and service bindings must be connected as described in Connected and unused interfaces.