Skip to content

Usage: Python (Advanced)

Bryan Wyatt edited this page Dec 14, 2024 · 1 revision

Note: This section is intended to be used as a quick "how to use the simulator in Python", and will be light on explaining networking concepts.

Start by either running Python interactively or (preferred) installing and running iPython to get an interactive shell to run the simulation.

The Simulation object is what controls all simulation activity.

from networksim.simulation import Simulation

sim = Simulation()

We can progress the simulation's time with the step() function, which takes an optional integer parameter for number of steps (default is 1).

sim.setp(20)

But this doesn't do much at present, as we don't have any devices in the simulaton or any packets. We can add a couple Ethernet Devices (devices that can only speak the low-level Ethernet protocol) and a Switch (a networking device that moves packets within a network based on low-level Ethernet addresses) to the simulation

from networksim.hardware.device import Device
from networksim.hardware.device.infrastructure.switch import Switch

A = Device(name="A")
B = Device(name="B")
SW = Switch(name="SW")

sim.add_device(A)
sim.add_device(B)
sim.add_device(SW)

By default, Devices have a single interface, and Switches have 4. You can see the current state of the simulation, and see that the devices have been added with the show() function, which will output all devices and their interfaces (including their hardware ("MAC") addresses), as well as their in/out queue sizes.

sim.show()

They aren't connected yet, however, we need to connect them, which we can do two ways:

Manually creating a cable, connecting it to the device interface, and adding it to the simulation:

from networksim.hardware.cable import Cable

cable_A_SW = Cable(A[0], SW[0])
sim.add_cable(cable_A_SW)

Having the simulation create the cable and connect to the first available (unused) interface on a device for you (which will, additionally, add the devices to the simulation if they aren't already):

sim.connect_devices(B, SW)

After that, both devices should be connected to the switch. Both methods, by default, will create cables of length 3 with a bandwidth of 1. You can check the new state with sim.show() and see the cables connecting the devices to the switch, as well as see any packets traveling along the cables (which should be none).

Now that we have both devices connected to the switch, they should be able to send Ethernet packets to each other. We can send a packet from A to B with the following:

A[0].send(EthernetPacket(dst=B[0].hwid, payload="Hello B!"))

And a sim.show() will show that Iface[0] on device A has a packet on the outbound queue. If we advance the simulation by 1 (sim.step()), we can see the packet on the cable between A and the switch by running show() again.

If we advance the simulation 3 more times (sim.step(3)), we can see a packet on the outbound queue of Iface[1] of SW. As well as an entry for A's hardware address in the switch's CAM table (more on that later).

Advancing the simulation 4 more steps will show a packet on the inbound queue for B. Unlike Switches (and, later, IPDevices), basic Ethernet Devices don't automatically process packets from their queue by default. But we can manually read the packet from the interface ourselves.

B[0].receive().payload

The list of all devices in the simulation can be accessed with:

sim.devices

Loading examples

Examples from the examples directory are JSON (.nsj) or gzip-compressed JSON (.nsj.gz) data files and can be read using the gzip and json libraries, then de-serialized by passing the resulting dictionary to Simulation.deserialize(data).

For example:

import gzip
import json

from networksim.simulation import Simulation


file_path = "./examples/SimpleRoutedNetwork.nsj"

with open(file_path, "rb") as file:
    data = file.read()

if file_path.endswith(".gz"):
    data = gzip.decompress(data)
data = json.loads(data.decode())

sim = Simulation.deserialize(data)
Clone this wiki locally