StackHPC

  • Home
  • About
  • Workshops
  • Kayobe
  • Contact
  • Careers
  • Blog

  • Bare metal
  • Community
  • Data
  • Deployment
  • Networking
  • Package
  • Virtualisation
  • Workloads
  • Home
  • About
  • Workshops
  • Kayobe
  • Contact
  • Careers
  • Blog
  • Bare metal
  • Community
  • Data
  • Deployment
  • Networking
  • Package
  • Virtualisation
  • Workloads

Testing Physical Network Setups with GNS3

For optimal reading, please switch to desktop mode.

Published: Wed 04 November 2026
Updated: Wed 04 November 2026
By Leonie Chamberlin-Medd

In Deployment.

tags: gns3 ci testing network

Is network testing the hardest of all kinds of testing? Kayobe and OpenStack releases may not work correctly with networking hardware that should be supported. This affects those using the kayobe physical network configure command and those with Ironic and Networking Generic Switch deployed. For example, the dellemc.os* modules changed how they needed to be invoked, but we did not discover this until trying to configure a new customer system. Current CI has no way of verifying the network configuration features, but adding this in would bring more confidence that they work correctly.

This blog post discusses the implementation of GNS3 in the CI pipeline to test and validate the physical network configurations.

GNS3 is a graphical network simulator that allows users to design and test complex network topologies in a virtual environment. It has multi-vendor support for running real switch images, meaning we can make calls with the switch CLIs as if we were interacting with the actual hardware. It is possible to interact with the GNS3 server both through a dedicated GUI and via a REST API. We use gns3fy, a project by David Ban, which acts as a Python wrapper for the GNS3 REST API. By utilising this, we can automate the testing of physical network setups in the CI pipeline with an Ansible playbook.

GNS3 Setup

Diagram of the process of setting up a GNS3 project.

There are 5 main steps to setting up a GNS3 project for testing the physical network setup:

  1. GNS3 Installation and Setup: Install the GNS3 server, add the systemd service and start it.
  2. Project Creation: Create a new project.
  3. GNS3 Appliance Template Upload: Download and upload the required GNS3 appliance templates to the server.
  4. Create nodes and links: Add the required nodes to the project and create links between them. Nodes in this case refers to the switch and cloud nodes in GNS3, as opposed to hosts.
  5. Remote Connection: Connect to the switch with Telnet and use an Expect script to set an IP address.

GNS3 is installed and configured through an Ansible role, designed to be called during the CI pipeline. The role has configurable values that should be set. You can find an example configuration file shown below in the NGS example.

Kayobe Integration

The first goal was to integrate GNS3 into the Kayobe CI pipeline. The aim was to set up a GNS3 project and test the physical network setup by using the kayobe physical network configure command.

Before calling the GNS3 role, Kayobe needs to be installed with the networking set up, so that GNS3 can use the breth1 interface to connect to the physical network, allowing for the host to communicate with the switch. So the role can set the switch up properly, you should set gns3_integration_mode to kayobe_physical_network_configuration.

Network diagram showing the connection between the switch and OpenStack Controller.

We deploy the switch and a single cloud node in GNS3, which acts as connection to the OpenStack Controller via the breth1 interface. It is connected to the management port.

Once Kayobe and GNS3 are installed, you can then bootstrap the control host with kayobe control host bootstrap and run then configure the physical network with kayobe physical network configure. This will apply any changes detailed in your host_vars file.

Networking Generic Switch

The next goal was to configure Networking Generic Switch (NGS) to talk with GNS3. To do this, we needed to deploy a virtualised OpenStack with Ironic and Tenks enabled.

The networking configuration is quite complex, as we needed to establish connection between the switch and both the baremetal node and the OpenStack Controller. This involved creating a new bridge for GNS3 and setting this bridge to be the master of the Tenks OVS interface.

Network diagram showing the connection between the switch, baremetal node, and OpenStack Controller.

There are 8 main steps when setting up NGS to work with GNS3:

First, you should complete the Kayobe automated setup with Ironic and Tenks enabled.

Once this is completed, you can call the GNS3 Ansible role, with the following configuration options set to correctly configure the switch and network for NGS.

gns3_project_name: Trial_project
switch_type: dellos10
gns3_switch_model: "Dell OS10 S4000-10.5.6.13.327"
gns3_cloud_node_quantity: 3
gns3_cloud_interfaces:
  - cloud: Cloud1
    interface: breth1
    name: breth1
    port_number: 0
    type: ethernet
  - cloud: Cloud2
    interface: breth1
    name: breth1
    port_number: 0
    type: ethernet
  - cloud: Cloud3
    interface: brgns3
    name: brgns3
    port_number: 0
    type: ethernet
gns3_links:
  - source_node: "{{ gns3_switch_model }}"
    source_adapter: 0
    source_port: 0 #mgmt 1/1/1
    target_node: Cloud1
    target_adapter: 0
    target_port: 0
  - source_node: "{{ gns3_switch_model }}"
    source_adapter: 1
    source_port: 0 #eth 1/1/1
    target_node: Cloud2
    target_adapter: 0
    target_port: 0
  - source_node: "{{ gns3_switch_model }}"
    source_adapter: 2
    source_port: 0 #eth 1/1/2
    target_node: Cloud3
    target_adapter: 0
    target_port: 0
gns3_switch_boot_delay: 181
gns3_integration_mode: "ngs"
vlan_tag: 1234

os_controller_interface: "eth 1/1/1"
baremetal_interface: "eth 1/1/2"
management_ip: "192.168.33.10/24"
management_interface: "mgmt1/1/1"

You should then apply the configuration detailed in this repository. This can be completed with a simple cherry-pick.

To avoid an observed issue found with dnsmasq and libvirt, you should insert a dummy dnsmasq binary under /usr/sbin/dnsmasq, as detailed in this website.

Once this is complete, you should deploy the overcloud services with kayobe overcloud service deploy and then configure the host with kayobe overcloud host configure. It is important to note that when running this in a development environment you may need to pass the --use-test-images flag in the service deploy to allow the use of test images.

When finished, the provision-net network needs to be recreated as a VLAN type network. In order to do this, first the demo-router will need deleting. To delete this, we will need to remove the attached port. Then we can safely delete it with openstack router delete demo-router. Then, delete the network with openstack network delete provision-net. To recreate the network, run openstack post configure.

To prepare the port for NGS, we need to update the local link connection of the baremetal node's port. You will need to set the node to be in maintenance to apply the changes. It is also worth setting any additional unused baremetal nodes to maintenace so the test-baremetal script runs faster.

Below are the commands to run:

openstack baremetal node maintenance set tk0
switch_mac=$(grep switch_facts_mac ~/kayobe/config/src/kayobe-config/etc/kayobe/inventory/host_vars/switch1 | awk '{print $2}')
baremetal_port_uuid=$(openstack baremetal port list --node tk0 -f value -c uuid)
openstack baremetal port set  --local-link-connection port_id="Eth 1/1/2" $baremetal_port_uuid
openstack baremetal port set  --local-link-connection switch_id="$switch_mac" $baremetal_port_uuid
openstack baremetal port set --local-link-connection switch_info="brgns3" $baremetal_port_uuid
openstack baremetal node set --network-interface neutron tk0
openstack baremetal node maintenance unset tk0

Below is an example of the desired result of openstack baremetal port show:

(kayobe-venv) ubuntu@ngsdemo:~$ openstack baremetal port show $baremetal_port_uuid
+---------------------------------+-------------------------------------------------------------------------------------+
| Field                           | Value                                                                               |
+---------------------------------+-------------------------------------------------------------------------------------+
| address                         | 96:c1:13:46:e6:4f                                                                   |
| available_for_dynamic_portgroup | True                                                                                |
| category                        | None                                                                                |
| created_at                      | 2026-09-11T09:03:05+00:00                                                           |
| description                     | None                                                                                |
| extra                           | {}                                                                                  |
| internal_info                   | {}                                                                                  |
| is_smartnic                     | False                                                                               |
| local_link_connection           | {'switch_id': '0c:bd:4a:cf:00:00', 'switch_info': 'brgns3', 'port_id': 'Eth 1/1/2'} |
| name                            | None                                                                                |
| node_uuid                       | 946f5372-2f56-45ba-82dc-fbb307e55824                                                |
| physical_network                | physnet1                                                                            |
| portgroup_uuid                  | None                                                                                |
| pxe_enabled                     | True                                                                                |
| updated_at                      | 2026-09-16T14:51:28+00:00                                                           |
| uuid                            | 20247e2e-fb16-4923-b12a-2477a8c78e6f                                                |
| vendor                          | None                                                                                |
+---------------------------------+-------------------------------------------------------------------------------------+

The final step before we can start to provision the nodes is to implement a router so that the OpenStack Controller can communicate with the baremetal node. This is due to the fact that the baremetal node is under the .34 subnet, while the OpenStack Controller is under .33.

The port that connects the OpenStack Controller to the switch is set to trunk mode, allowing for multiple VLANs to be used. It uses VLAN 1234 for the provision_wl network. NGS sets the baremetal node port to the correct VLAN, allowing for the OpenStack Controller to communicate with the baremetal node through the switch.

Here's an example of the GNS3 GUI showing the NGS setup.

GNS3 GUI showing the NGS setup with the switch, baremetal node, and OpenStack Controller.

Now everything is set up, we can run the overcloud-test-baremetal.sh script to provision and deploy the baremetal node. In this, we can also observe NGS applying configuration. You can observe DHCP and HTTP traffic by running a tcpdump on the brgns3 interface on port 67, 68 and 80, or if you have access to the GNS3 GUI you can open Wireshark. DHCP will show the discover, offer, request, and acknowledgement packets for the PXE boot files. HTTP packets will show the PXE boot files being downloaded to the baremetal node.

Here is an example of the traffic we are looking for:

Wireshark capture showing the DHCP and HTTP traffic on the GNS3 bridge

The below video demonstrates NGS applying the changes.

The main steps are:

  1. NGS sends the relevant switch CLI commands via the management port to the switch to set the baremetal node port to the provision-net VLAN.
  2. Baremetal node provisioning and deployment occurs.
  3. NGS then sets the VLAN of the baremetal node port to the VLAN for demo-net.

CI Integration

Starting with our downstream CI, we first created a new job to test the physical network configuration with Kayobe. In its own instance, it starts by installing Kayobe and cloning the relevant configuration repository. The required interfaces are then created and packages installed. The Ansible role is then called to install and configure GNS3 to be used in CI. Finally, we bootstrap the control host and run a physical network configure. If the script runs to completion then we can verify that the configuration is setup correctly, if not changes may need to be made to the configuration.

Next Steps

Once we fully integrate GNS3 into our downstream CI, it would be beneficial to add this to upstream CI too. It will take some work to get this into upstream CI, as the GNS3 images can be very large. On top of this, adding support for more switch types would be great, as currently only Dell OS10 switches are supported. This would allow for broader testing of network configurations.

Get in touch

If you would like to get in touch we would love to hear from you. Reach out to us via BlueSky, LinkedIn or directly via our contact page.

Cyber Essentials certified
Scientific OpenStack Kayobe Scientific SIG

StackHPC Ltd, registered company number 09938332. Privacy Policy

Cyber Essentials certified