docker pull patriotframework/patriot-router:latest
Network Simulator is the most complex feature of Patriot framework. It implements logic necessary to deploy virtual network environment where the parts of System Under Test, or whole SUT, can be deployed. In the current state of the framework, the network simulation is done with the Docker container platform.
The Docker container platform is containerization platform aiming to bring several enhancements to the application deployment and its lifecycle. The core concept of containerization is to build a system for deployment of applications, that allows software delivery independent of the platform, advanced sandboxing of the applications. In case of Docker this is achieved by Paravirtualization, where the application is using only the kernel of the operating system and its core features, but all other services (e.g. networking, storage) are allocated for the containerized process and process is as separated from other processes as possible.
Following terms are necessary to understand the implementation of the network simulator.
Docker image - is bundled application with all necessary dependencies for application execution.
Docker container - running instance of application, unit that has its own separated virtual drive initialized with data from image, using Copy-on-write strategy.
Docker network - a virtual network that provides network interfaces to the docker containers and interconnects or separates them from one another.
The Patriot framework embraces those properties and builds on top of them scalable solution, that allows preparing, deploy and test components of the System Under Test.
One of the necessary parts for the Network Simulation is a component called a router. The router is in general device, which connects together two or more networks on L3 ISO/OSI level, (network level). That means that routers are responsible for providing service on the level of IP protocol instead of L2 ethernet. The main functionality of a router is to pass the data from one network to another based on their target network. To achieve this the routers must be equipped with routing tables.
A routing table is set of rules that define to which network should be data holder, in case of IP called packet, passed by its target.
The router component of Patriot framework is implemented in the
patriot-router module. This
the module implements a software router with RESTfull API, which allows Patriot framework to set it
up and control its behavior.
docker pull patriotframework/patriot-router:latest
This step will pull an image stored in the DockerHub, which is ready to use for the Patriot framework router. If you want to do any modification of
routers behavior you can do it via Dockerfile, but CMD and ENTRYPOINT must stay ! After you build your routers image, you have to set tag to the
io.patriot_framework.router property. After the router is built or pulled, the Network Simulator has all the dependencies ready for the execution.
Application has to be build on base image from patriotframework docker hub. You can modify your application container, but stay must same. Java and go are fully installed in base image. Specify CMD with command which will run your java application. After all modifications are done, you have to build image from your Dockerfile. Tag used for building image will be later used for deploying application to topology.
docker pull patriotframework/simulator-base:latest
FROM patriotframework/simulator-base:latest CMD["java", "-jar", "generator.jar", "-c", "config.yaml"]
docker build -t MY_TAG DOCKERFILE_DIRECTORY
The basic scenario shows how the network topology is set up within Network Simulator and how the components are integrated to achieve the desired outcome. The scenario can be broke down into the following steps.
Define network topology which is the high-level connection of the networks, it allows networks to be built into the tree structure.
Define routers that will interconnect the virtual networks
Define networks that will be interconnected in the topology
Define routes between networks
Call manager to deploy topology
Those steps should be used in the series as is defined before because it will not cause possible errors due to missed dependencies.
The first step is to define needed routers in the Patriot framework context, which will later
connect networks together into the desired topology. These objects are only blueprints for the Network Simulator runtime, hence the only attribute for the router in this step is only its
name of type
String. For later use, these Router objects can be build with RouterBuilder.
import io.patriot_framework.network.simulator.api.model.devices.router.RouterImpl; RouterImpl r = new RouterIml("TRt")
A TopologyNetwork is another object that is used for Topology creation, it defines one address pool, which interconnects all containers associated with it. When initializing networks, the following 3 main attributes are expected
Network mask is an integer in range 0 - 32
Network name is the identifier of the network for later use
Network IP address is a string in IPv4 address format
0-255.0-255.0-255.0-255 and identifies
the network address, which is in combination with network mask also a pool of addresses for the network devices.
If the network serves as a corner gateway to the internet, the
Internet attribute must
be set to
Every router has a default gateway that targets the shortest path to internet network!
import io.patriot_framework.network.simulator.api.model.network.TopologyNetwork; TopologyNetwork tNet = new TopologyNetwork("Teacher", "192.168.0.0", 28);
For now, the entire topology is stored in TopologyNetwork objects. There is one more attribute named CalcRoutes that points to a list of CalcRoute objects. The list contains the description of topology (routes). Each CalcRoute object has 2 attributes:
Next hop router (object)
Next hop network position in the networks ArrayList (int)
If the networks are not directly connected, and have to be calculated, the cost must be equal to the networks ArrayList size + 1
If the target network is same as the source, the value of this attribute must be set to
null in Java environments.
To show the Network Simulator in action, let’s assume the following scenario: we want to create the network topology that consists of three networks
First one is for teachers
Second one is for students
Third one is the backbone
And also we want to have a connection to the Internet
All parts of topology are for now created by docker, so we need to specify Docker as creator for whole topology
The following snippet shows basic objects that are needed for the simulation.
Topology topology = new TopologyBuilder(4) .withCreator("Docker") .withRouters() .withName("TRt") .createRouter() .withName("SRt") .createRouter() .withName("MainRt") .withCorner(true) .createRouter() .addRouters() .withNetwork("tNet") .withIP("192.168.0.0") .withMask(28) .create() .withNetwork("sNet") .withIP("192.168.16.0") .withMask(28) .create() .withNetwork("bNet") .withIP("172.16.0.0") .withMask(16) .create() .withNetwork("iNet") .withInternet(true) .create()
After the base objects are defined, now it’s time to define the interconnection of the networks by putting the Routers in place. We have to specify route just one time, api will set same route in opposite direction (We specify tNet → bNet and api will set bNet → tNet too).
int routNeedCalc = topology.getNetworks().size() + 1; .withRoutes() .withSourceNetwork("tNet") .withDestNetwork("sNet") .viaRouter((RouterImpl)null) .withCost(routNeedCalc) .addRoute() .withSourceNetwork("tNet") .withDestNetwork("bNet") .withCost(1) .viaRouter("TRt") .addRoute() .withSourceNetwork("tNet") .withDestNetwork("iNet") .withCost(routNeedCalc) .viaRouter((RouterImpl)null) .addRoute
.withSourceNetwork("sNet") .withDestNetwork("bNet") .withCost(1) .viaRouter("SRt") .addRoute() .withSourceNetwork("sNet") .withDestNetwork("iNet") .withCost(routNeedCalc) .viaRouter((RouterImpl)null) .addRoute()
.withSourceNetwork("bNet") .withDestNetwork("iNet") .withCost(1) .viaRouter("MainR") .buildRoute() .buildRoutes() .build();
For iNet network we doesn’t have more routes to specify. After all of those commands are executed, our topology is ready to be deployed.
For deployment we need initialize Manager with 4 parameters:
List<Controller> controllers that will be used for environment creation
Patriot router image tag
Manager networkManager = PatriotHub.getInstance().getManager(); networkManager.setControllers(Arrays.asList(new DockerController())); networkManager.deploy(topology);
Central log server can be set with Manager attributes:
monitoringAddr - Logstash or Graylog ip address
monitoringPort - Logstash or Graylog port
If these parameters are set, all logs on stdout and stderr are logged into central server. Deployment of log server described in patriot-monitoring
The last part of the Network Simulator is support for the deployment of a tested application into the simulated environment. In the current state the basic prerequisite is, that the application is containerized.
Manager networkManager = PatriotHub.getInstance().getManager(); Topology topology = new TopologyBuilder(2) .withRouters() .withName("R1") .addRouters() .withNetwork("N1") .withIP("192.168.0.0") .withMask(28) .create() .withNetwork("N2") .withIP("192.168.16.0") .withMask(28) .create() .withRoutes() .withSourceNetwork("N1") .withDestNetwork("N2") .withCost(1) .viaRouter("R1") .addRoute() .buildRoutes() .build(); networkManager.setControllers(Arrays.asList(new DockerController()); networkManager.deploy(topology); Application app = new Application("Generator", "Docker"); networkManager.deployDeviceToNetwork(app, topology.getNetworks().get(1), topology, "app-1.0-SNAPSHOT");