A large part of network engineering still depends on manual validation. A topology is modified, a new routing or switching behavior is introduced, and someone eventually opens a terminal to test whether the network still behaves correctly. That approach works for small environments, but it becomes difficult to maintain when infrastructure logic evolves continuously through scripts, automation, or SDN-based control.

Over the past few years, I’ve been increasingly interested in treating network infrastructure more like software: version-controlled, reproducible, and automatically validated before changes are accepted.

One small but practical example of this was integrating Mininet into a CI/CD workflow using GitHub Actions.

The idea was straightforward. Every time a topology or network script changes, the pipeline automatically provisions a Linux environment, installs Mininet and Open vSwitch, launches the topology, performs connectivity checks, and validates the result before the change is merged.

The workflow itself is relatively lightweight, but it reflects a larger engineering mindset around reproducibility and automated infrastructure testing.

I initially explored this together with ideas inspired by the Internet Topology Zoo project, which provides real-world network topologies collected from operators worldwide. These datasets are commonly used for SDN experimentation, routing analysis, and large-scale topology studies. They also provide a useful foundation for reproducible network simulations and automated testing environments.

In this setup, the GitHub Actions runner installs the required networking components directly on Ubuntu:

- name: Install Mininet and OVS
  run: |
    sudo apt-get update

    sudo apt-get install -y \
      mininet \
      openvswitch-switch \
      openvswitch-common \
      python3 \
      python3-pip

Once the environment is ready, the pipeline starts Open vSwitch, cleans stale Mininet state, and launches the custom topology script:

- name: Run Mininet topology
  run: |
    sudo -E python3 topo.py | tee mininet_output.log

The topology script performs host-to-host validation internally and prints a deterministic success message once connectivity is verified. The pipeline then checks the generated logs to confirm the network behaved as expected.

- name: Verify ping success
  run: |
    grep "PING SUCCESS" mininet_output.log

One thing I particularly like about this approach is that the network behavior becomes reproducible and testable in the same way application logic is tested in modern software pipelines. Instead of relying on manual validation after deployment, failures are detected automatically during development.

Even for relatively small experiments, this changes the workflow considerably. It becomes easier to modify topologies, test OpenFlow logic, validate switching behavior, or experiment with overlay networking without worrying about silent regressions.

The same idea can scale further into:

  • SDN controller validation
  • tunnel establishment checks
  • failover testing
  • security policy verification
  • routing experiments
  • topology-aware simulations
  • network resilience testing

In practice, combining Mininet with CI/CD also creates a cleaner bridge between networking, infrastructure engineering, and DevOps-style workflows. Network experiments stop being isolated lab exercises and become reproducible engineering artifacts that can be versioned, validated, and continuously improved.

For me, this has been one of the more interesting shifts in network engineering: moving from manually tested infrastructure toward infrastructure that validates itself automatically every time the underlying logic changes.

from mininet.net import Mininet
from mininet.topo import Topo
from mininet.node import OVSSwitch
from mininet.log import setLogLevel

class MyTopo(Topo):

    def build(self):

        h1 = self.addHost('h1')
        h2 = self.addHost('h2')

        s1 = self.addSwitch(
            's1',
            failMode='standalone'
        )

        self.addLink(h1, s1)
        self.addLink(h2, s1)

def run():

    topo = MyTopo()

    net = Mininet(
        topo=topo,
        switch=OVSSwitch,
        controller=None,
        autoSetMacs=True
    )

    net.start()

    print("\n=== Ping test ===")

    result = net.ping(
        [net.get('h1'), net.get('h2')]
    )

    if result == 0:
        print("\nPING SUCCESS")
    else:
        print("\nPING FAILED")
        exit(1)

    net.stop()

if __name__ == '__main__':
    setLogLevel('info')
    run()
    
  

💡
GitHub Action logs should be as below for simple network connectivity: