|
|
|
#!/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()
|