Part I: Porting the NCTUns Network Simulator to Linux
3. High Level Architecture
3.3 Simulation Engine Design
The simulation engine is a user-level program and has complex functions. We can say that it functions like a small operating system. Through a defined API, it provides useful and basic simulation services to protocol modules. These services contain virtual clock maintenance, timer management, event scheduling, variable registration, script interpreter, IPC interface, etc. At the same time, it manages all of the tools and daemons that are used in a simulation case and decides when to start these programs, when to finish them, and when to run them. Figure I-3.3.1 shows an architecture diagram readers of the NCTUns 1.0 network simulator.
In figure I-3.3.1, we can see the whole architecture of the NCTUns 1.0 network simulator. In the section, we first describe the organization of the simulation engine.
Figure I-3.3.1: The architecture of the NCTUns 1.0 network simulator
Figure I-3.3.2: The module based platform
In section 3.4, we will explain how the kernel supports the simulation engine. We can simply divide the simulation engine into several components:
I. Script Interpreter
The script interpreter reads a script file of a simulation case to construct the simulation network environment, the network conditions, protocol module settings, and the network traffic.
II. Module Manager
The module manager manages all protocol modules that users registered and used in a simulation. When the script interpreter parses the script file, the module manager dynamically constructs the corresponding C++ objects and organizes them to build a simulation network environment. In figure I-3.3.1, those modules in the box of the module-based platform form a simple simulation network.
III. Command Dispatcher
The command dispatcher is used to communicate with other external components such as the coordinator, command console (It is a modified tcsh.), and the GUI program.
IV. NCTUns APIs
We call these APIs provided by the simulation engine NCTUns APIs. All of the protocol modules can ask for the simulation engine’s services via the NCTUns APIs such as registering modules, processing events, setting timers, creating/freeing packets, etc.
V. Event Queue
The event queue has three kinds of data structure type inside it: event, timer, and event packet. The event is used to encapsulate messages that are exchanged between protocol modules. Every event has a timestamp inside it used to decide when to process it. The timer can be used to set what to do at a specified time stamp. If an event encapsulates a network packet (e.g. an IP packet), we call the event an event packet. In the event queue, all events or timers are sorted with their timestamp.
VI. Scheduler
The main job of the scheduler is to execute the event or timer in the event queue.
The scheduler always picks up the event or timer which has the smallest timestamp to execute. In the meantime, the scheduler will advance the simulation time to the timestamp of the event.
VII. System calls and tunnel interface t0e0
We use two approaches to enable the simulation engine to communicate with the FreeBSD/Linux kernel. The first approach is through system calls. The simulation engine can use system calls that are added or modified by us to register/get information into/from the kernel. This approach suits the situation that the simulation engine actively wants to get or set some kernel parameters. The second approach is through using a tunnel interface. If the kernel wants to actively inform the simulation engine with some information, we use the tunnel interface t0e0. The kernel can fill a packet with some information and inserts it into the tunnel interface t0e0. Then the simulation engine can issue a read() system call to get the packet and further get the information inside it. This mechanism is mostly used by the kernel timeout event and
the tunnel check event (we will describe this in section 3.5 of part I).
VIII. IPC (Inter-Process Communication)
The IPC in the simulation engine is used to communicate with the coordinator.
When a GUI user wants to send a command to the simulation engine such as pause a simulation, stop a simulation, send command to a protocol module etc., the GUI should send the command to the coordinator and then the coordinator relays the command to the simulation engine via IPC. After the simulation engine processes the command, it will send the result back to the coordinator and then the coordinator will relay the result to GUI.
Due to the module-based platform, we can dynamically construct or change the network protocol of a device. For example, figure I-3.3.2 shows a simple simulation case: the switch is a two-port layer-2 device and is connected with the host 1 and host 2 (host 1, 2 are both layer-3 devices). We can easily change the protocol module settings of host 1. We can just replace the FIFO module with a RED (Random Early Drop) module in the script file and then the module manager will dynamically construct corresponding protocol module settings according to the script file. We can also build a network device via the module-based platform. The switch device in figure I-3.3.2 is a layer-2 device and all components of the device are represented by modules. In addition to protocol modules, the layer-3 devices (such as host 1, host 2) will need kernel supports because we directly use the layer-3 protocols in the kernel.
Figure I-3.3.2 also shows the flow path that a packet will take when it is exchanged between the two traffic generators via the module-based platform. We already explain how a packet will pass through the kernel in section 3.1. When the
packet is read by the simulation engine from tunnel interface 1 (tun1), the packet will follow the trace of figure I-3.3.2 and then the simulation engine will insert it into tunnel interface 2. Finally, the kernel will send it to the traffic generator.