#!/usr/bin/env python from math import sqrt import os from signal import SIGINT from time import sleep from mininet.cli import CLI from mininet.net import Mininet from mininet.util import dumpNodeConnections, moveIntf, pmonitor from mininet.log import setLogLevel, info from mininet.link import TCLink from mininet.node import Node from sys import argv import xml.etree.ElementTree as ET from mininet.topo import Topo from mininet.link import TCLink # It would be nice if we didn't have to do this: # pylint: disable=arguments-differ class GraphmlTopo(Topo): ip_counter = (0,1) def increment_ip_counter(self): b3, b4 = GraphmlTopo.ip_counter if b4 < 254: b4 += 1 else: b3 += 1 b4 = 1 GraphmlTopo.ip_counter = b3, b4 def build(self, filename='topology.graphml', subnet=True): positions = dict() try: graph = ET.parse(filename).getroot() except Exception as error: print(error) exit(1) for node in graph.iter('{http://graphml.graphdrawing.org/xmlns}node'): node_id = int(node.get('id')) + 1 privateDirs = ['/var/log','/var/run'] self.addHost('h%i' % node_id, privateDirs=privateDirs) #, #cls=LinuxRouter) x_pos = node.find('.//data[@key="x"]') y_pos = node.find('.//data[@key="y"]') positions[node_id] = (x_pos, y_pos) for link in graph.iter('{http://graphml.graphdrawing.org/xmlns}edge'): link_id = int(link.get('id')) + 1 source = int(link.get('source')) + 1 target = int(link.get('target')) + 1 if subnet: intfName_s, addr1, params_s = self.format_intf_params(link_id, source) intfName_t, addr2, params_t = self.format_intf_params(link_id, target) else: intfName_s, addr1, params_s = self.format_intf_params_incremental(source, 16) intfName_t, addr2, params_t = self.format_intf_params_incremental(target, 16) linkopts = dict() # dict(bw=10, delay='5ms', loss=20, max_queue_size=1000, use_htb=True) # to implement a function which from nodes positions return linkopts self.addLink('h%i' % source, 'h%i' % target, key=link_id, cls=TCLink, intfName1=intfName_s, addr1=addr1, params1=params_s, intfName2=intfName_t, addr2=addr2 ,params2=params_t, **linkopts) def format_intf_params_incremental(self, node_id, subnet_mask_cidr): b3, b4 = GraphmlTopo.ip_counter self.increment_ip_counter() addr = '00:00:00:00:00:%02i' % (node_id) params = {'ip': '10.0.%i.%i/%i' % (b3, b4, subnet_mask_cidr)} return None, addr, params def format_intf_params(self, link_id, node_id): intf_name = 'h%i-eth%i' % (node_id, link_id) addr = '00:00:00:00:%02i:%02i' % (link_id, node_id) ip = '10.0.%i.%i/24' % (link_id, node_id) params = {'ip': ip} return intf_name, addr, params def eval_link_params(pos_1, pos_2, x=2): distance = sqrt((pos_1['x'] + pos_2['x'])^2 - (pos_1['y'] + pos_2['y'])^2) Tx_W = 2 Rx_W = 2 class LinuxRouter(Node): def config(self, **params): self.cmd('sysctl net.ipv4.ip_forward=1') def terminate(self): self.cmd('sysctl net.ipv4.ip_forward=0') super(LinuxRouter, self).terminate() def startRTMonitor(self): self.popenRTMonitor = self.popen('bash routing-table-monitor.sh') def stopRTMonitor(self): self.popenRTMonitor.send_signal(SIGINT) self.popenRTMonitor.wait() class OLSRRouter(LinuxRouter): def config(self, **params): super(OLSRRouter, self).config(**params) self.popenOLSR = self.popen('olsrd', '-nofork' , '-i', *self.intfNames()) def terminate(self): self.popenOLSR.send_signal(SIGINT) self.popenOLSR.wait() super(OLSRRouter, self).terminate() class OLSRRouterMonitored(OLSRRouter): def config(self, **params): self.startRTMonitor() super(OLSRRouterMonitored, self).config(**params) def terminate(self): if self.popenRTMonitor: self.popenRTMonitor.send_signal(SIGINT) super(OLSRRouterMonitored, self).terminate() class BATMANDRouter(LinuxRouter): def config(self, **params): super(BATMANDRouter, self).config(**params) batman_param=[]#sum([['-a', i.IP()+'/32'] for i in self.intfList()],[]) batman_param.extend(self.intfNames()) self.cmd('batmand', *batman_param) def terminate(self): # self.popenBATMAND.send_signal(SIGINT) # self.popenBATMAND.wait() super(BATMANDRouter, self).terminate() class BATMANDRouterMonitored(BATMANDRouter): def config(self, **params): self.startRTMonitor() super(BATMANDRouterMonitored, self).config(**params) def terminate(self): if self.popenRTMonitor: self.popenRTMonitor.send_signal(SIGINT) super(BATMANDRouterMonitored, self).terminate() def startRTMonitor(self): self.popenRTMonitor = self.popen( 'bash routing-table-monitor.sh -c "ip route show table 66"' ) class BATMANADVRouter(LinuxRouter): def config(self, **params): super(BATMANADVRouter, self).config(**params) if self.cmd('lsmod', '|', 'grep', '-q', 'batman') is not 0: self.cmd('modprobe', 'batman-adv') self.batman_intf = '%s-bat0' % self.name self.cmd() for intf in self.intfNames(): self.cmd('batctl', '-m', self.batman_intf, 'if', 'add', intf) moveIntf(self.batman_intf, self) id = int(self.name[1:]) self.cmd('ip', 'address', 'add', '192.168.123.%i/24' % id, 'dev', self.batman_intf) self.cmd('ip', 'link', 'set', 'up', 'dev', self.batman_intf) def terminate(self): self.cmd('batctl', '-m', self.batman_intf, 'if', 'destroy') super(BATMANADVRouter, self).terminate() def routing_table_monitor_test(net): info("monitoring routing tables\n") while (net.pingAll() != 0): sleep(5) info("routing tables converged\n") log("stop link h1-h14") disable_link(net['h1'], net['h14']) #net['h11'].stop() # sleep(60) # for host in net.hosts: # host.cmd('kill %bash') def log(event): os.system('echo "{}:\t\t$(date +"%T %N")" >> logs/global.log'.format(event)) def do_disable_link(self, line): net = self.mn h1, h2 = line.split(" ") disable_link(net[h1], net[h2]) def disable_link(host1, host2): intf1, intf2 = host1.connectionsTo(host2)[0] host1.cmd('iptables -A INPUT -m mac --mac-source', intf2.MAC(), '-j DROP') def do_enable_olsrd(self, line): net = self.mn enable_olsrd(net) def enable_olsrd(net): for host in net.hosts: host.cmd('olsrd -i ' + ' '.join(host.intfNames())) hosts = {'linuxrouter': LinuxRouter, 'olsrrouter': OLSRRouter, 'batmanadvrouter': BATMANADVRouter, 'batmandrouter': BATMANDRouter} topos = {'gmltopo': GraphmlTopo} CLI.do_enable_olsrd = do_enable_olsrd CLI.do_disable_link = do_disable_link def perfTest(): topo = GraphmlTopo(filename='rural2.graphml') net = Mininet(topo=topo, link=TCLink, host=OLSRRouterMonitored) net.start() info("Dumping host connections\n") dumpNodeConnections(net.hosts) CLI(net) net.stop() def perfTestBatman(): topo = GraphmlTopo(filename='rural2.graphml', subnet=False) net = Mininet(topo=topo, link=TCLink, host=BATMANDRouterMonitored) net.start() #routing_table_monitor_test(net) info("Dumping host connections\n") dumpNodeConnections(net.hosts) CLI(net) net.stop() if __name__ == '__main__': setLogLevel('info') # Prevent test_simpleperf from failing due to packet loss #perfTest() perfTestBatman()