diff --git a/MininetNetPractice.py b/MininetNetPractice.py index 7631ed6..b10e1f2 100644 --- a/MininetNetPractice.py +++ b/MininetNetPractice.py @@ -6,6 +6,7 @@ from mininet.node import Node from mininet.cli import CLI from mininet.link import TCLink from mininet.log import setLogLevel +from copy import copy #TODO verify/temporaneo class MyRouter (Node): def config(self, **params): @@ -17,65 +18,79 @@ class MyRouter (Node): def build_topology(config_file): topo = Topo() - - 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] == 'host': #Parse hosts - host_name = parts[1] - host_ip = parts[2] - host_nexthop = 'via ' + parts[3] - topo.addHost(host_name, ip=host_ip, defaultRoute=host_nexthop) - - elif parts[0] == 'router': #Parse routers - router_name = parts[1] - router_ip = parts[2] - topo.addNode(router_name, cls=MyRouter, ip=router_ip) - - elif parts[0] == 'switch': #Parse switches - switch_name = parts[1] - topo.addSwitch(switch_name) - - elif parts[0] == 'linkSH': #Parse links switches to hosts - node1 = parts[1] - node2 = parts[2] - topo.addLink(node1, node2) - - elif parts[0] == 'linkSS': #Parse links switches to switches - node1 = parts[1] - node2 = parts[2] - topo.addLink(node1, node2) - - elif parts[0] == 'linkHR': #Parse links hosts to routers - node1 = parts[1] - node2 = parts[2] - intf_name2 = parts[3] - n2_ip = parts[4] - topo.addLink(node1, node2, intfName2=intf_name2, params2={'ip' : n2_ip}) - - elif parts[0] == 'linkRR': #Parse links routers to routers - node1 = parts[1] - node2 = parts[2] - intf_name1 = parts[3] - intf_name2 = parts[4] - ip1 = parts[5] - ip2 = parts[6] - topo.addLink(node1, node2, intfName1=intf_name1, intfName2=intf_name2, params1={'ip' : ip1}, params2={'ip' : ip2}) + elementsH = {} # Dictionary to store nodes + elementsR = {} # Dictionary to store nodes + elementsS = {} # Dictionary to store nodes + + h1 = topo.addHost('h1', ip='161.46.247.131/26', defaultRoute='via 161.46.247.129') + h2 = topo.addHost('h2', ip='161.46.247.196/27', defaultRoute='via 161.46.247.195') + + r1 = topo.addNode('r1', cls=MyRouter, ip='161.46.247.129/26') + + topo.addLink(h1, r1, intfName2='R23', params2={'ip' : '161.46.247.129/26'}) + topo.addLink(h2, r1, intfName2='R22', params2={'ip' : '161.46.247.195/27'}) + + # 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] == 'host': #Parse hosts + # host_name = parts[1] + # host_ip = parts[2] + # host_nexthop = 'via ' + parts[3] + # host = topo.addHost(host_name, ip=host_ip, defaultRoute=host_nexthop) + # host_c = copy(host) + # elementsH[host_name] = (host_c) + + # elif parts[0] == 'router': #Parse routers + # router_name = parts[1] + # router_ip = parts[2] + # router = topo.addNode(router_name, cls=MyRouter, ip=router_ip) + # router_c = copy(router) + # elementsR[router_name] = (router_c) + + # elif parts[0] == 'switch': #Parse switches + # switch_name = parts[1] + # switch = topo.addSwitch(switch_name) + # switch_c = copy(switch) + # elementsS[switch_name] = (switch_c) + + # elif parts[0] == 'linkSH': #Parse links switches to hosts + # node1 = parts[1] + # node2 = parts[2] + # # topo.addLink(node1, node2) + + # elif parts[0] == 'linkSS': #Parse links switches to switches + # node1 = parts[1] + # node2 = parts[2] + # # topo.addLink(node1, node2) + + # elif parts[0] == 'linkHR': #Parse links hosts to routers + # node1 = parts[1] + # node2 = parts[2] + # intf_name2 = parts[3] + # n2_ip = parts[4] + # topo.addLink(elementsH.get(node1), elementsR.get(node2), intfName2=intf_name2, params2={'ip' : n2_ip}) + + # elif parts[0] == 'linkRR': #Parse links routers to routers + # node1 = parts[1] + # node2 = parts[2] + # intf_name1 = parts[3] + # intf_name2 = parts[4] + # ip1 = parts[5] + # ip2 = parts[6] + # # topo.addLink(node1, node2, intfName1=intf_name1, intfName2=intf_name2, params1={'ip' : ip1}, params2={'ip' : ip2}) - # elif parts[0] == 'route': #Parse routing tables - # name = parts[1] - # for node in topo.nodes(): - # if node == name: - # (node).cmd('ip route add 0.0.0.0/0 via 10.0.0.1 dev r1-eth2') - # break - + # # elif parts[0] == 'route': #Parse routing tables + # # name = parts[1] + # # for node in topo.nodes(): + # # if node == name: + # # (node).cmd('ip route add 0.0.0.0/0 via 10.0.0.1 dev r1-eth2') + # # break - - # (topo.getNodeByName('r1')).cmd('ip route add 0.0.0.0/0 via 10.0.0.1 dev r1-eth2') return topo def run_topology(config_file): @@ -84,19 +99,23 @@ def run_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) + # net.addLink(h1, r1, intfName2='R23', params2={'ip' : '161.46.247.129/26'}) + # net.addLink(h2, r1, intfName2='R22', params2={'ip' : '161.46.247.195/27'}) + + # 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: diff --git a/MininetTopo.conf b/MininetTopo.conf index 4f27e8e..01f93e8 100644 --- a/MininetTopo.conf +++ b/MininetTopo.conf @@ -1,14 +1,14 @@ ######## Set hosts ######## ## host name ip defRoute ## ########################### -host h1 10.1.0.2/24 10.1.0.1 -host h2 10.2.0.2/24 10.2.0.1 +host h1 161.46.247.131/26 161.46.247.129 +host h2 161.46.247.196/27 161.46.247.195 #### Set routers ### ## router name ip ## #################### -router r1 10.1.0.1/24 -router r2 10.2.0.1/24 +router r1 161.46.247.129/26 +#router r2 10.2.0.1/24 ## Set switches ## ## switch name ## @@ -33,16 +33,16 @@ router r2 10.2.0.1/24 ##################### Set links ##################### ## linkHR host, router, router_intfName, router_ip ## ##################################################### -linkHR h1 r1 r1-eth1 10.1.0.1/24 -linkHR h2 r2 r2-eth1 10.2.0.1/24 +linkHR h1 r1 R23 161.46.247.129/26 +linkHR h2 r1 R22 161.46.247.195/27 ######################### Set links ######################### ## linkRR router1, router2, intfName1, intfName2, ip1, ip2 ## ############################################################# -linkRR r1 r2 r1-eth2 r2-eth2 10.0.0.0/31 10.0.0.1/31 +# linkRR r1 r2 r1-eth2 r2-eth2 10.0.0.0/31 10.0.0.1/31 ############# route table ############# ## route name source destRoute interf ## ######################################## -route r1 0.0.0.0/0 10.0.0.1 r1-eth2 -route r2 0.0.0.0/0 10.0.0.0 r2-eth2 +# route r1 0.0.0.0/0 10.0.0.1 r1-eth2 +# route r2 0.0.0.0/0 10.0.0.0 r2-eth2 diff --git a/provaRL.py b/provaRL.py deleted file mode 100644 index fdd723b..0000000 --- a/provaRL.py +++ /dev/null @@ -1,187 +0,0 @@ -import mininet -import time, socket, random -import numpy as np -from mininet.cli import CLI -from mininet.log import setLogLevel -from mininet.net import Mininet -from mininet.topo import Topo -from mininet.link import TCLink -import matplotlib.pyplot as plt - -# Define custom topology -class MyTopology(Topo): - def build(self): - # Create switches - s1 = self.addSwitch('s1') - s2 = self.addSwitch('s2') - - # Create hosts - h1 = self.addHost('h1') - h2 = self.addHost('h2') - - # Add links - self.addLink(h1, s1, cls=TCLink, delay='10ms', bw=1) - self.addLink(s1, s2, cls=TCLink, delay='50ms', bw=0.5) - self.addLink(s2, h2, cls=TCLink, delay='10ms', bw=1) - -# Define TCP agent -class MyTCPAgent: - def __init__(self): - # Initialize TCP agent - self.transmission_rounds = [] - self.congestion_window_sizes = [] - - - def handle_connection(self): - print("TCP connection establishment") - # Implement TCP connection establishment - - # Example TCP connection establishment using a socket - # self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # self.sock.connect(('localhost', 19191)) - - # Example TCP connection establishment simulation - time.sleep(1) # Simulating connection establishment delay - - def handle_data_transfer(self, tunnel, window_size): - print("Performing data transfer with tunnel:", tunnel, "and window size:", window_size) - # Implement TCP data transfer with the given tunnel and window size using socket programming - - # Implement TCP data transfer simulation - - # Placeholder logic: Simulating data transfer - time.sleep(0.1) # Simulating data transfer delay - - # Simulate congestion control by waiting for a fixed amount of time - time.sleep(0.1) - - # Record transmission round and final congestion window size - self.transmission_rounds.append(len(self.transmission_rounds) + 1) - self.congestion_window_sizes.append(window_size) - -# Define RL agent for tunnel selection -class TunnelSelectionAgent: - def __init__(self, tunnels): - # Initialize your RL agent for tunnel selection - self.rewards = [] - self.selected_tunnels = [] - self.tunnels = tunnels - self.current_tunnel = 0 - - def select_tunnel(self): - # Implement tunnel selection based on RL policy - # Placeholder logic: Select a tunnel randomly or based on some criteria - selected_tunnel = self.tunnels[self.current_tunnel] - self.current_tunnel = (self.current_tunnel + 1) % len(self.tunnels) - return selected_tunnel - - def update_policy(self, reward): - # Implement RL policy update based on rewards - self.rewards.append(reward) - self.selected_tunnels.append(self.select_tunnel()) - -# Define RL agent for window prediction -class WindowPredictionAgent: - def __init__(self): - # Initialize the RL agent for window prediction - self.window_sizes = [1, 2, 4, 8, 16, 32, 64] # Possible window sizes - self.alpha = 0.1 # Learning rate - self.gamma = 0.9 # Discount factor - self.q_table = {} # Q-table to store state-action values - - def predict_window_size(self): - # Get the current state (e.g., network conditions) - state = self.get_state() - - # Check if the state is in the Q-table - if state not in self.q_table: - # Initialize Q-values for all possible actions in the current state - self.q_table[state] = {window_size: 0 for window_size in self.window_sizes} - - # Choose the action (window size) based on epsilon-greedy policy - if random.random() < 0.2: # Exploration (20% of the time) - action = random.choice(self.window_sizes) - else: # Exploitation (80% of the time) - action = self.get_best_action(state) - - return action - - def get_state(self): - # Implement the logic to determine the current state based on network conditions - # For example, you can consider factors such as round-trip time, packet loss rate, or congestion signals - - # Placeholder logic: Return a random state - return random.randint(1, 10) - - def get_best_action(self, state): - # Find the action (window size) with the highest Q-value for the given state - best_action = max(self.q_table[state], key=self.q_table[state].get) - return best_action - - def update_policy(self, reward): - # Update the Q-value based on the reward received after taking an action - # Get the previous state and action - prev_state = self.get_state() # Replace with the actual previous state - prev_action = self.predict_window_size() # Replace with the actual previous action - - # Get the current state - curr_state = self.get_state() - - # Check if the current state is in the Q-table - if curr_state not in self.q_table: - # Initialize Q-values for all possible actions in the current state - self.q_table[curr_state] = {window_size: 0 for window_size in self.window_sizes} - - # Update the Q-value using the Q-learning update rule - 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() - - # Instantiate TCP and RL agents - tcp_agent = MyTCPAgent() - tunnels = ['myPrivate1'] - tunnel_agent = TunnelSelectionAgent(tunnels) - window_agent = WindowPredictionAgent() - - # Perform TCP connection establishment - tcp_agent.handle_connection() - - # 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 - tunnel = tunnel_agent.select_tunnel() - window_size = window_agent.predict_window_size() - - # Perform data transfer - tcp_agent.handle_data_transfer(tunnel, window_size) - - # Update RL agents based on rewards - 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 - plt.plot(tcp_agent.transmission_rounds, tcp_agent.congestion_window_sizes) - plt.xlabel('Transmission Round') - plt.ylabel('Congestion Window Size') - plt.title('TCP+RL Window Prediction') - plt.show() diff --git a/setup.txt b/setup.txt index 5bc5c1f..df97bab 100644 --- a/setup.txt +++ b/setup.txt @@ -15,7 +15,7 @@ pip3 install colorama pip3 install mininet pip3 install ryu pip3 install --upgrade pip -pip install pillow +pip3 install pillow pip3 install matplotlib sudo apt-get install mininet