From 7d24a53db94c4483eff3ef1626c9ffc27370354e Mon Sep 17 00:00:00 2001 From: edoardocoli Date: Mon, 10 Jul 2023 17:25:09 +0200 Subject: [PATCH] Tests in Mininet Env --- MininetController.py | 63 ++++++++++++++ MininetNetPractice.py | 41 +++++++--- MininetRL.py | 18 ++-- MininetSDWAN.py | 185 ++++++++++++++++++------------------------ MininetTopo.conf | 42 ++++++---- SteffeCluster.conf | 46 +++++++++++ setup.txt | 1 + 7 files changed, 253 insertions(+), 143 deletions(-) create mode 100644 MininetController.py create mode 100644 SteffeCluster.conf diff --git a/MininetController.py b/MininetController.py new file mode 100644 index 0000000..d0d22c2 --- /dev/null +++ b/MininetController.py @@ -0,0 +1,63 @@ +from mininet.net import Mininet +from mininet.node import Controller, OVSSwitch +from mininet.cli import CLI +from mininet.log import setLogLevel + +class CustomController( Controller ): + "Open vSwitch controller" + def __init__( self, name, **kwargs ): + kwargs.setdefault( 'command', self.isAvailable() or + 'ovs-controller' ) + Controller.__init__( self, name, **kwargs ) + + +# class CustomController(Controller): +# def _handle_ConnectionUp(self, event): +# # Handle new connection +# dpid_str = dpid_to_str(event.dpid) +# log.info("Switch %s connected", dpid_str) +# self.connection = event.connection +# event.connection.addListeners(self) + +# def _handle_PacketIn(self, event): +# # Handle incoming packet +# packet = event.parsed +# if packet.type == ethernet.IP_TYPE: +# ip_packet = packet.payload +# src_ip = ip_packet.srcip +# dst_ip = ip_packet.dstip +# log.info("Source IP: %s, Destination IP: %s", src_ip, dst_ip) + +# # Call the parent handler to continue processing other events +# super(CustomController, self)._handle_PacketIn(event) + +def create_topology(): + net = Mininet(controller=Controller, switch=OVSSwitch) + + # Create network nodes + h1 = net.addHost('h1') + h2 = net.addHost('h2') + s1 = net.addSwitch('s1', cls=OVSSwitch) + + # Create links + net.addLink(h1, s1) + net.addLink(h2, s1) + + # Start the network + net.start() + + # Create a custom controller instance + controller = net.addController('c1', controller=CustomController) + + # Connect the switch to the controller + s1.start([controller]) + + # Enter command line mode + CLI(net) + + # Stop the network + net.stop() + +if __name__ == '__main__': + setLogLevel('info') + create_topology() diff --git a/MininetNetPractice.py b/MininetNetPractice.py index f502942..cc750b9 100644 --- a/MininetNetPractice.py +++ b/MininetNetPractice.py @@ -1,10 +1,10 @@ -import configparser +import sys 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.link import TCLink from mininet.log import setLogLevel class MyRouter (Node): @@ -42,6 +42,12 @@ def build_topology(config_file): 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] @@ -71,19 +77,22 @@ def build_topology(config_file): 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 - node1 = parts[1] - node2 = parts[2] - # topo.addLink TODO + 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 - node1 = parts[1] - node2 = parts[2] - # topo.addLink TODO + switch1 = parts[1] + switch2 = parts[2] + topo.addLink(elements.get(switch1), elements.get(switch2)) elif parts[0] == 'linkSH': #Parse links switches to hosts - node1 = parts[1] - node2 = parts[2] - # topo.addLink TODO + switch = parts[1] + host = parts[2] + host_intfName = parts[3] + topo.addLink(elements.get(switch), elements.get(host), intfName2=host_intfName) return topo @@ -119,4 +128,12 @@ def run_topology(config_file): net.stop() #Stopping the network if __name__ == '__main__': - run_topology('MininetTopo.conf') \ No newline at end of file + 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('MininetTopo.conf') diff --git a/MininetRL.py b/MininetRL.py index fdd723b..17491f3 100644 --- a/MininetRL.py +++ b/MininetRL.py @@ -50,7 +50,7 @@ class MyTCPAgent: # Implement TCP data transfer simulation # Placeholder logic: Simulating data transfer - time.sleep(0.1) # Simulating data transfer delay + # time.sleep(0.1) # Simulating data transfer delay # Simulate congestion control by waiting for a fixed amount of time time.sleep(0.1) @@ -136,19 +136,14 @@ class WindowPredictionAgent: max_q_value = max(self.q_table[curr_state].values()) # Get the maximum Q-value for the current state self.q_table[prev_state][prev_action] += self.alpha * (reward + self.gamma * max_q_value - self.q_table[prev_state][prev_action]) -# Create the Mininet network with custom topology -def create_network(): - topo = MyTopology() - net = Mininet(topo=topo) - net.start() - return net - # Main function if __name__ == '__main__': setLogLevel('info') # Create the Mininet network - net = create_network() + topo = MyTopology() + net = Mininet(topo=topo) + net.start # Instantiate TCP and RL agents tcp_agent = MyTCPAgent() @@ -161,7 +156,6 @@ if __name__ == '__main__': # Perform data transfer with RL-based tunnel selection and window prediction start_time = time.time() - while True: if time.time() - start_time > 10: # End packet exchange after seconds break @@ -172,14 +166,14 @@ if __name__ == '__main__': tcp_agent.handle_data_transfer(tunnel, window_size) # Update RL agents based on rewards - reward = 0.5 # Actual reward value + reward = -0.5 # Actual reward value tunnel_agent.update_policy(reward) # window_agent.update_policy(reward) # Stop the Mininet network net.stop() - # Plot Transmission Round versus Congestion Window Size + # Plot Transmission Round and Congestion Window Size plt.plot(tcp_agent.transmission_rounds, tcp_agent.congestion_window_sizes) plt.xlabel('Transmission Round') plt.ylabel('Congestion Window Size') diff --git a/MininetSDWAN.py b/MininetSDWAN.py index 5c4e139..d2f061f 100644 --- a/MininetSDWAN.py +++ b/MininetSDWAN.py @@ -1,109 +1,84 @@ -import heapq -import random from mininet.net import Mininet -from mininet.node import OVSSwitch, Controller -from mininet.link import TCLink -from mininet.net import Mininet -from mininet.topo import Topo -from mininet.node import Node -from mininet.cli import CLI -from mininet.link import TCLink -from mininet.log import setLogLevel +from mininet.node import Controller +from mininet.log import setLogLevel +from mininet.cli import CLI +from pox.lib import of +import time +import matplotlib.pyplot as plt + +# Create empty lists to store the timestamp and latency values +timestamps = [] +latencies = [] + +class PacketCopyController(Controller): + def __init__(self, name, target_host, **kwargs): + Controller.__init__(self, name, **kwargs) + self.target_host = target_host + + def _handle_PacketIn(self, event): + packet = event.parsed + self.packet_out(event.port, packet) + self.packet_out_to_host(packet) + # Measure latency and store timestamp and latency values + latency = time.time() - event.created + timestamps.append(time.time()) + latencies.append(latency) + + def packet_out(self, out_port, packet): + msg = of.ofp_packet_out() + msg.data = packet.pack() + action = of.ofp_action_output(port=out_port) + msg.actions.append(action) + self.connection.send(msg) + + def packet_out_to_host(self, packet): + host = self.net.get(self.target_host) + if host: + host.sendMsg(packet) -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 create_topology(): - net = Topo() - - # Create the SD-WAN sites - site1 = net.addHost('site1') - site2 = net.addHost('site2') - site3 = net.addHost('site3') - - # Create the virtual SD-WAN devices - sdwan1 = net.addHost('sdwan1') - sdwan2 = net.addHost('sdwan2') - - # Create switches - switch1 = net.addSwitch('s1') - - # Connect the hosts and switches - net.addLink(site1, switch1, bw=10, delay='10ms') - net.addLink(site2, switch1, bw=5, delay='20ms') - net.addLink(site3, switch1, bw=8, delay='15ms') - net.addLink(sdwan1, switch1, bw=100, delay='1ms') - net.addLink(sdwan2, switch1, bw=100, delay='1ms') - - return net - -def dynamic_path_selection(net, link_qos): # Function to select the best path based on real-time conditions using Dijkstra algorithm with QoS metrics - - # Add a random factor to the QoS metric - random_range = 4 - for link in link_qos: - link_qos[link] += random.randint(-random_range, random_range) - - # Perform Dijkstra algorithm to find the best path based on QoS metrics - def dijkstra(source): - distance = {node: float('inf') for node in net} - distance[source] = 0 - queue = [(0, source)] - while queue: - dist, node = heapq.heappop(queue) - if dist > distance[node]: - continue - for neighbor, _, link_info in net[node].connectionsTo(net): - qos = link_qos.get(link_info[0].intf1.name) - new_dist = dist + qos - if new_dist < distance[neighbor]: - distance[neighbor] = new_dist - heapq.heappush(queue, (new_dist, neighbor)) - return distance - - # Run Dijkstra algorithm from each site to determine the best path - site1_distance = dijkstra('site1') - site2_distance = dijkstra('site2') - site3_distance = dijkstra('site3') - sdwan1_distance = dijkstra('sdwan1') - sdwan2_distance = dijkstra('sdwan2') - - # Select the best path based on minimum total QoS distance - best_path = min(site1_distance, site2_distance, site3_distance, sdwan1_distance, sdwan2_distance, - key=lambda x: sum(x.values())) - print("Best path based on QoS metrics:") - for node, distance in best_path.items(): - print(f"Node: {node}, Total QoS Distance: {distance}") - -def run_topology(): - setLogLevel('info') #Different logging levels are 'info' 'warning' 'error' 'debug' - topo = create_topology() - net = Mininet(topo=topo, link=TCLink) - # net.addController('c0', controller=Controller) #non serve metterlo esplicitamente - - net.start() #Starting the network - # Define QoS metrics for each link (example values) - link_qos = { - 'site1-eth0': 8, # QoS value for link site1 -> switch1 - 'site2-eth0': 6, # QoS value for link site2 -> switch1 - 'site3-eth0': 9, # QoS value for link site3 -> switch1 - 'sdwan1-eth0': 10, # QoS value for link sdwan1 -> switch1 - 'sdwan2-eth0': 7 # QoS value for link sdwan2 -> switch1 - } - - # Add a random factor to the QoS metric - random_range = 4 - for link in link_qos: - link_qos[link] += random.randint(-random_range, random_range) +if __name__ == '__main__': + setLogLevel('info') + + # Creazione della rete Mininet + net = Mininet(controller=PacketCopyController) + + # Creazione degli host e degli switch + h1 = net.addHost('h1') + h2 = net.addHost('h2') + h3 = net.addHost('h3') + s1 = net.addSwitch('s1') + + # Creazione dei collegamenti + net.addLink(h1, s1) + net.addLink(h2, s1) + net.addLink(h3, s1) + + # Create the plot + plt.figure() + plt.xlabel('Time') + plt.ylabel('Latency (seconds)') + plt.title('Network Latency') + + # Avvio della rete e assegnazione del controller + # Add the POX controller + controller = net.addController(name='controller', target_host='h3', controller=PacketCopyController, ip='127.0.0.1', port=6633) + net.start() + controller.start() + # controller = net.controllers[0] + # controller.net = net + + # Start the plot animation + plt.ion() + plt.show() + + try: + while True: + # Update the plot with new latency data + plt.plot(timestamps, latencies, 'b-') + plt.draw() + plt.pause(0.1) + except KeyboardInterrupt: + pass - dynamic_path_selection(net, link_qos) CLI(net) - net.stop() #Stopping the network - -if __name__ == '__main__': - run_topology() \ No newline at end of file + net.stop() diff --git a/MininetTopo.conf b/MininetTopo.conf index b49471f..c2ab9f3 100644 --- a/MininetTopo.conf +++ b/MininetTopo.conf @@ -1,47 +1,61 @@ ######### Set Network Nodes ######### ## N_host name ## +## N_switch name ## ## host name intfIP/mask defRoute ## -## N_router name ## ## router name intfIP/mask ## -## N_switch name ## ##################################### # host H4 161.46.247.131/26 161.46.247.129 # host H3 161.46.247.196/27 161.46.247.195 +# host H2 161.46.247.3/25 161.46.247.1 # router R1 161.46.247.254/30 # router R2 161.46.247.253/30 N_host h1 N_host h2 +N_host h3 N_router r1 N_router r2 -N_switch s1 -N_switch s2 +N_router r3 + +# N_host h1 +# N_host h2 +# N_router r1 +# N_router r2 +# N_switch s1 +# N_switch s2 ############################################ ## The interface details defined inside ## ## the node during its creation must be ## -## reused in the links before new ## +## used in the links before new ## ## interfaces can be defined for the node.## ############################################# Set Network Links ############################################ ## NN_link node1, node2 ## +## SN_link switch, node, bandwidth(Mbps) ## ## linkRR router1, router1_intfName, router1_intfIP/mask, router2, router2_intfName, router2_intfIP/mask ## ## linkRH host, host_intfName, router, router_intfName, router_intfIP/mask ## -## linkRS TODO ## -## linkSS TODO ## -## linkSH TODO ## +## linkRS switch, router, router_intfName, router_intfIP/mask ## +## linkSS switch1, switch2 ## +## linkSH switch, host, host_intfName ## ############################################################################################################ # linkRR R1 R13 161.46.247.254/30 R2 R21 161.46.247.253/30 # linkRH H3 H31 R2 R22 161.46.247.195/27 # linkRH H4 H41 R2 R23 161.46.247.129/26 +# linkRH H2 H21 R1 R11 161.46.247.1/25 + +NN_link h1 r1 +NN_link h2 r2 +NN_link h3 r3 +NN_link r1 r2 +NN_link r2 r3 -NN_link s1 s2 -NN_link r1 s1 -NN_link r2 s2 -NN_link h1 s1 -NN_link h2 s2 +# NN_link r1 s1 +# NN_link r2 s2 +# NN_link r1 r2 +# NN_link h1 s1 +# NN_link h2 s2 ################## Route Table ################ -## N_route TODO ## ## route name final_destIP/mask nextHop intf ## ############################################### # route R1 161.46.247.192/27 161.46.247.254 R13 diff --git a/SteffeCluster.conf b/SteffeCluster.conf new file mode 100644 index 0000000..324364c --- /dev/null +++ b/SteffeCluster.conf @@ -0,0 +1,46 @@ +######### Set Network Nodes ######### +N_host steffe0 +N_host steffe1 +N_host steffe2 +N_host steffe3 +N_host steffe4 +N_host steffe5 +N_host steffe6 +N_host steffe7 +N_host steffe8 +N_host steffe9 +N_host steffe10 +N_host steffe11 +N_host steffe12 +N_host steffe13 +N_host steffe14 +N_host steffe15 +N_host steffe16 +N_host steffe17 +N_host steffe18 +N_host steffe19 +N_host steffe20 +N_switch s0 + +############################################ Set Network Links ############################################ +SN_link s0 steffe0 1000 +SN_link s0 steffe1 1000 +SN_link s0 steffe2 1000 +SN_link s0 steffe3 1000 +SN_link s0 steffe4 1000 +SN_link s0 steffe5 1000 +SN_link s0 steffe6 1000 +SN_link s0 steffe7 1000 +SN_link s0 steffe8 1000 +SN_link s0 steffe9 1000 +SN_link s0 steffe10 1000 +SN_link s0 steffe11 1000 +SN_link s0 steffe12 1000 +SN_link s0 steffe13 1000 +SN_link s0 steffe14 1000 +SN_link s0 steffe15 1000 +SN_link s0 steffe16 1000 +SN_link s0 steffe17 1000 +SN_link s0 steffe18 1000 +SN_link s0 steffe19 1000 +SN_link s0 steffe20 1000 diff --git a/setup.txt b/setup.txt index df97bab..5f0322b 100644 --- a/setup.txt +++ b/setup.txt @@ -16,6 +16,7 @@ pip3 install mininet pip3 install ryu pip3 install --upgrade pip pip3 install pillow +pip3 install pox pip3 install matplotlib sudo apt-get install mininet