diff --git a/MininetComparativeAnalysis.py b/MininetComparativeAnalysis.py new file mode 100644 index 0000000..f1ba0a0 --- /dev/null +++ b/MininetComparativeAnalysis.py @@ -0,0 +1,158 @@ +import sys +import multiprocessing +from colorama import Fore, Style +from mininet.net import Mininet +from mininet.link import TCLink +from mininet.topo import Topo +from mininet.node import Node +from mininet.cli import CLI +from mininet.log import setLogLevel + +class MyRouter (Node): + def config(self, **params): + super(MyRouter, self).config(**params) + self.cmd('sysctl net.ipv4.ip_forward=1') #Enable forwarding on the router + def terminate(self): + self.cmd('sysctl net.ipv4.ip_forward=0') #Disable forwarding on the router + super(MyRouter, self).terminate + +def build_topology(config_file): + topo = Topo() + elements = {} # Dictionary to store nodes + + with open(config_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith('#'): #Skip comment + continue + parts = line.split(" ") #Parse the topology file using spaces + if parts[0] == 'N_host': #Parse hosts + host_name = parts[1] + elements[host_name] = topo.addHost(host_name) + + elif parts[0] == 'N_router': #Parse routers + router_name = parts[1] + elements[router_name] = topo.addNode(router_name) + + elif parts[0] == 'N_switch': #Parse switches + switch_name = parts[1] + elements[switch_name] = topo.addSwitch(switch_name) + + elif parts[0] == 'NN_link': #Parse general links nodes to nodes + node1 = parts[1] + node2 = parts[2] + topo.addLink(elements.get(node1), elements.get(node2)) + + elif parts[0] == 'SN_link': #Parse general links switches to nodes + switch = parts[1] + node = parts[2] + bandwidth = int(parts[3]) + topo.addLink(elements.get(switch), elements.get(node), bw=bandwidth) + + if parts[0] == 'host': #Parse hosts + host_name = parts[1] + host_ip = parts[2] + host_nexthop = 'via ' + parts[3] + elements[host_name] = topo.addHost(host_name, ip=host_ip, defaultRoute=host_nexthop) + + elif parts[0] == 'router': #Parse routers + router_name = parts[1] + router_ip = parts[2] + elements[router_name] = topo.addNode(router_name, cls=MyRouter, ip=router_ip) + + elif parts[0] == 'linkRR': #Parse links routers to routers + router1 = parts[1] + router1_intfName = parts[2] + router1_intfIP = parts[3] + router2 = parts[4] + router2_intfName = parts[5] + router2_intfIP = parts[6] + topo.addLink(elements.get(router1), elements.get(router2), intfName1=router1_intfName, intfName2=router2_intfName, params1={'ip' : router1_intfIP}, params2={'ip' : router2_intfIP}) + + elif parts[0] == 'linkRH': #Parse links routers to hosts + host = parts[1] + host_intfName = parts[2] + router = parts[3] + router_intfName = parts[4] + router_intfIP = parts[5] + topo.addLink(elements.get(host), elements.get(router), intfName1=host_intfName, intfName2=router_intfName, params2={'ip' : router_intfIP}) + + elif parts[0] == 'linkRS': #Parse links routers to switches + switch = parts[1] + router = parts[2] + router_intfName = parts[3] + router_intfIP = parts[4] + topo.addLink(elements.get(switch), elements.get(router), intfName2=router_intfName, params2={'ip' : router_intfIP}) + + elif parts[0] == 'linkSS': #Parse links switches to switches + switch1 = parts[1] + switch2 = parts[2] + topo.addLink(elements.get(switch1), elements.get(switch2)) + + elif parts[0] == 'linkSH': #Parse links switches to hosts + switch = parts[1] + host = parts[2] + host_intfName = parts[3] + topo.addLink(elements.get(switch), elements.get(host), intfName2=host_intfName) + + return topo + +def run_topology(config_file): + setLogLevel('info') #Different logging levels are 'info' 'warning' 'error' 'debug' + topo = build_topology(config_file) + net = Mininet(topo=topo, link=TCLink) + net.start() #Starting the network + with open(config_file, 'r') as file: #Search in the configuration file for routing table + for line in file: + line = line.strip() + if line.startswith('#'): #Skip comment + continue + parts = line.split(" ") + if parts[0] == 'route': #Parse routing tables + name = parts[1] + pck_src = parts[2] + pck_nexthop = parts[3] + interf = parts[4] + cmd = 'ip route add ' + pck_src + ' via ' + pck_nexthop + ' dev ' + interf + (net.getNodeByName(name)).cmd(cmd) + if net.pingAll(): + print(Fore.RED + "Network has issues" + Style.RESET_ALL) + else: + print(Fore.GREEN + "Network working properly" + Style.RESET_ALL) + + def run_command(host,command): + output = host.cmd(command) + with open('N_to1.test', 'a') as file: #Based on the N hosts in hosts list, have to be modified for different execution + file.write(output) + + server = multiprocessing.Process(target=run_command, args=(net.getNodeByName("steffe0"), "iperf -s -P 20")) + server.start() + hosts = ["steffe1","steffe2","steffe3","steffe4"] #List of the working hosts, have to be modified for different execution + for i in range(0,10): + print(f"Currently on loop {i+1}") + processes = [] + for host in hosts: + command = 'echo -n "Runned on "; date; echo '+host+';iperf -c 10.0.0.1 -t 5' #10.0.0.1 is the IP of the steffe0 host + client = multiprocessing.Process(target=run_command, args=(net.getNodeByName(host),command)) + client.start() + processes.append(client) + for client in processes: + client.join() + server.terminate() + server.join() + net.stop() #Stopping the network + +#### +# If you get "Exception: Please shut down the controller which is running on port 6653:" +# use this to solve the issue: "sudo fuser -k 6653/tcp" +#### +if __name__ == '__main__': + if '-f' in sys.argv: + try: + file_index = sys.argv.index('-f') + 1 + config_file = sys.argv[file_index] + run_topology(config_file) + except IndexError: + print("Error: No configuration file provided after -f flag.") + else: + run_topology('SteffeCluster.conf') diff --git a/README.md b/README.md index 692a3c6..82c8fb1 100644 --- a/README.md +++ b/README.md @@ -90,14 +90,15 @@ In addition to its network emulation capabilities, Mininet also provides support In order to build a custom network topology I used Mininet and Python tools; in front of all to run the program we need to install those dependencies: ``` sudo -v -sudo apt install python3 python3-pip openvswitch-testcontroller mininet; +sudo apt install python3 python3-pip python3-venv openvswitch-testcontroller mininet; pip3 install --upgrade pip; -pip3 install mininet colorama configparser ryu pillow pox matplotlib; +pip3 install mininet colorama configparser pillow pox matplotlib ryu; ``` The *MininetNetPractice.py* program showcases the ability to parse and extract data from the configuration file to define the desired network topology. Using the Mininet API, the program reads and parses the *MininetTopo.conf* file, which contains information about the network topology. By leveraging the parsed data, the program creates a virtual network with the desired topology, replicating the specified network configuration. This allows for the creation of custom and complex network scenarios tailored to specific research or testing requirements. Referring to a random topology, like the one in the figure below, we can create a configuration file that brings back exactly these parameters within the Mininet topology in order to interact with them. The configuration file *MininetTopo.conf* represents it. Some notes for the creation are reported there as a structure model, together with some constraints to be respected. Another important aspect to allow the network to function is to manage the routers routing table(**TODO inside MininetTopo.conf**). I tested the mininet emulation software to reproduce a real situation of a cluster. Within this [file.pdf](https://github.com/edoardoColi/5G_Sandbox/blob/edoardoColi/docs/MininetConf/researchReport.pdf) it is possible to view all my comparison analysis and the conclusions I have reached. +Additionally, a scientific paper has been sent for publication approval, offering a more in-depth analysis, that can be reed [here](https://github.com/edoardoColi/5G_Sandbox/blob/edoardoColi/docs/MininetConf/researchPropose.pdf). To reproduce the paper environment is possible to use *MininetComparativeAnalysis.py* doing `sudo python3 MininetComparativeAnalysis.py` ## 5G Network simulation For emulating and testing a 5G Network we are going to use ComNetsEmu, a testbed and network emulator designed for the NFV/SDN teaching book "Computing in Communication Networks: From Theory to Practice".