Add MinindnAdhoc and ability to configure mobility in configuration file
Change-Id: I7feec7616ed7cf9f0ebb51b4e8c704201931abc9
diff --git a/minindn/wifi/minindnwifi.py b/minindn/wifi/minindnwifi.py
index ba3c434..bf290b8 100644
--- a/minindn/wifi/minindnwifi.py
+++ b/minindn/wifi/minindnwifi.py
@@ -32,10 +32,13 @@
from mn_wifi.topo import Topo as Topo_WiFi
from mn_wifi.net import Mininet_wifi
from mn_wifi.link import WirelessLink
+from mn_wifi.link import wmediumd, adhoc
from minindn.minindn import Minindn
from minindn.helpers.nfdc import Nfdc
+import ast
+
class MinindnWifi(Minindn):
""" Class for handling default args, Mininet-wifi object and home directories """
def __init__(self, parser=argparse.ArgumentParser(), topo=None, topoFile=None, noTopo=False,
@@ -82,6 +85,10 @@
else:
self.net = Mininet_wifi(ifb=self.args.ifb, link=link, **mininetParams)
+ # process mobility if specified
+ if not noTopo:
+ self.processMobility(self.topoFile)
+
# Prevents crashes running mixed topos
nodes = self.net.stations + self.net.hosts + self.net.cars
self.initParams(nodes)
@@ -93,7 +100,7 @@
Minindn.ndnSecurityDisabled = '/dummy/KEY/-%9C%28r%B8%AA%3B%60' in output.decode("utf-8")
info('Dummy key chain patch is installed in ndn-cxx. Security will be disabled.\n')
else:
- debug(error)
+ debug(error + "\n")
except:
pass
@@ -116,24 +123,31 @@
parser.add_argument('--mobility',action='store_true',dest='mobility',default=False,
help='Enable custom mobility for topology (defined in topology file)')
- parser.add_argument('--model-mob',action='store_true',dest='modelMob',default=False,
- help='Enable model mobility for topology (defined in topology file)')
-
parser.add_argument('--ifb',action='store_true',dest='ifb',default=False,
help='Simulate delay on receiver-side by use of virtual IFB devices (see docs)')
return parser
@staticmethod
+ def convert_params(params):
+ converted_params = {}
+ for key, value in params.items():
+ try:
+ converted_params[key] = ast.literal_eval(value)
+ except (ValueError, SyntaxError):
+ converted_params[key] = value
+ return converted_params
+
+ @staticmethod
def processTopo(topoFile):
config = configparser.ConfigParser(delimiters=' ')
config.read(topoFile)
topo = Topo_WiFi()
items = config.items('stations')
- debug("Stations")
+ debug("Stations\n")
for item in items:
- debug(item[0].split(':'))
+ debug(str(item[0].split(':'))+"\n")
name = item[0].split(':')[0]
params = {}
for param in item[1].split(' '):
@@ -148,21 +162,21 @@
topo.addStation(name, **params)
try:
- debug("Switches")
+ debug("Switches\n")
items = config.items('switches')
for item in items:
- debug(item[0].split(':'))
+ debug(str(item[0].split(':'))+"\n")
name = item[0].split(':')[0]
topo.addSwitch(name)
except configparser.NoSectionError:
- debug("Switches are optional")
+ debug("Switches are optional\n")
pass
try:
debug("APs")
items = config.items('accessPoints')
for item in items:
- debug(item[0].split(':'))
+ debug(str(item[0].split(':'))+"\n")
name = item[0].split(':')[0]
ap_params = {}
for param in item[1].split(' '):
@@ -175,14 +189,14 @@
ap_params[key] = value
topo.addAccessPoint(name, **ap_params)
except configparser.NoSectionError:
- debug("APs are optional")
+ debug("APs are optional\n")
pass
items = config.items('links')
debug("Links")
for item in items:
link = item[0].split(':')
- debug(link)
+ debug(str(link) + "\n")
params = {}
for param in item[1].split(' '):
if param == "_":
@@ -200,10 +214,10 @@
faces = {}
try:
items = config.items('faces')
- debug("Faces")
+ debug("Faces\n")
for item in items:
face_a, face_b = item[0].split(':')
- debug(item)
+ debug(str(item)+"\n")
cost = -1
for param in item[1].split(' '):
if param.split("=")[0] == 'cost':
@@ -214,11 +228,51 @@
else:
faces[face_a].append(face_info)
except configparser.NoSectionError:
- debug("Faces section is optional")
+ debug("Faces section is optional\n")
pass
return (topo, faces)
+ def processMobility(self, topoFile):
+ config = configparser.ConfigParser(delimiters=' ')
+ config.read(topoFile)
+
+ try:
+ debug("Mobility\n")
+ items = config.items('mobility')
+ if len(items) == 0:
+ return
+ params = {}
+ for param in items[0][1].split(' '):
+ if param == "_":
+ continue
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ params[key] = value
+ params = self.convert_params(params)
+ self.startMobilityModel(**params)
+
+ items = config.items('stations')
+ debug("Start Mobility\n")
+ for item in items:
+ debug(str(item[0].split(':'))+"\n")
+ name = item[0].split(':')[0]
+ params = {}
+ for param in item[1].split(' '):
+ if param == "_":
+ continue
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ if key in ['range']:
+ value = int(value)
+ params[key] = value
+ # by default, nodes are moving
+ if "moving" not in params or params["moving"] == "True":
+ self.net.mobility(self.net[name],'start', time=0, **params)
+
+ except configparser.NoSectionError:
+ debug("Mobility section is optional\n")
+
def startMobility(self, max_x=1000, max_y=1000, **kwargs):
""" Method to run a basic mobility setup on your net"""
self.net.plotGraph(max_x=max_x, max_y=max_y)
@@ -304,4 +358,141 @@
created_faces[nodeB].append(nodeALink)
for station_name in batch_faces.keys():
self.nfdcBatchProcessing(self.net[station_name], batch_faces[station_name])
- return created_faces
\ No newline at end of file
+ return created_faces
+
+class MinindnAdhoc(MinindnWifi):
+ """
+ Class for ad hoc network of Mininet-wifi
+ Topology example: topologies/wifi/adhoc-topology.conf
+ The link type is wmediumd by default
+ """
+ def __init__(self, parser=argparse.ArgumentParser(), topo=None, topoFile=None, noTopo=False,
+ link=wmediumd, workDir=None, **mininetParams):
+ # call parent constructor
+ super().__init__(parser, topo, topoFile, noTopo, link, workDir, **mininetParams)
+ if not self.topoFile:
+ info("Without topoFile, ad hoc links are not added to the network, and you need to"
+ " add them manually. The example topology file can be found in"
+ " topologies/wifi/adhoc-topology.conf\n")
+ else:
+ self.addAdhocLinks()
+
+ @staticmethod
+ def parseArgs(parent):
+ parser = argparse.ArgumentParser(prog='minindn-adhoc', parents=[parent], add_help=False)
+
+ # nargs='?' required here since optional argument
+ parser.add_argument('topoFile', nargs='?', default='/usr/local/etc/mini-ndn/adhoc-topology.conf',
+ help='If no template_file is given, topologies/wifi/adhoc-topology.conf will be used.')
+
+ parser.add_argument('--work-dir', action='store', dest='workDir', default='/tmp/minindn',
+ help='Specify the working directory; default is /tmp/minindn')
+
+ parser.add_argument('--result-dir', action='store', dest='resultDir', default=None,
+ help='Specify the full path destination folder where experiment results will be moved')
+
+ parser.add_argument('--mobility',action='store_true',dest='mobility',default=False,
+ help='Enable custom mobility for topology (defined in topology file)')
+
+ parser.add_argument('--ifb',action='store_true',dest='ifb',default=False,
+ help='Simulate delay on receiver-side by use of virtual IFB devices (see docs)')
+
+ return parser
+
+ @staticmethod
+ def processTopo(topoFile):
+ config = configparser.ConfigParser(delimiters=' ')
+ config.read(topoFile)
+ topo = Topo_WiFi()
+
+ items = config.items('stations')
+ debug("Stations\n")
+ id = 0
+ for item in items:
+ debug(str(item[0].split(':'))+"\n")
+ name = item[0].split(':')[0]
+ params = {}
+ for param in item[1].split(' '):
+ if param == "_":
+ continue
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ if key in ['range']:
+ value = int(value)
+ params[key] = value
+ # ip6 address for each station using id
+ if 'ip6' not in params:
+ params['ip6'] = 'fe80::{}'.format(id)
+ topo.addStation(name, **params)
+ id += 1
+
+ faces = {}
+ try:
+ items = config.items('faces')
+ debug("Faces\n")
+ for item in items:
+ face_a, face_b = item[0].split(':')
+ debug(str(item)+"\n")
+ cost = -1
+ for param in item[1].split(' '):
+ if param.split("=")[0] == 'cost':
+ cost = param.split("=")[1]
+ face_info = (face_b, int(cost))
+ if face_a not in faces:
+ faces[face_a] = [face_info]
+ else:
+ faces[face_a].append(face_info)
+ except configparser.NoSectionError:
+ debug("Faces section is optional\n")
+ pass
+
+ return (topo, faces)
+
+ """Add adhoc links to the network"""
+ # In the topo.py, all the links require two stations, but in adhoc topology, we need to add links for all the nodes.
+ def addAdhocLinks(self):
+ config = configparser.ConfigParser(delimiters=' ')
+ config.read(self.topoFile)
+
+ # read adhoc network parameters
+ # return if adhoc network is not defined
+ if 'adhocNetwork' not in config.sections():
+ info("Adhoc network is not defined in the topology file\n")
+ return
+
+ adhoc_params = config.items('adhocNetwork')
+ params = {}
+ for param in adhoc_params[0][1].split(' '):
+ if param == "_":
+ continue
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ if key in ['range']:
+ value = int(value)
+ params[key] = value
+ params = self.convert_params(params)
+
+ # return if ssid, mode, channel not defined in params
+ if 'ssid' not in params or 'mode' not in params or 'channel' not in params:
+ info("ssid, mode, channel not defined in adhoc network parameters\n")
+ return
+ networkParams = params
+
+ # add adhoc links
+ debug("Links\n")
+ items = config.items('stations')
+ for item in items:
+ debug(str(item[0].split(':'))+"\n")
+ name = item[0].split(':')[0]
+ params = {}
+ for param in item[1].split(' '):
+ if param == "_":
+ continue
+ key = param.split('=')[0]
+ value = param.split('=')[1]
+ params[key] = value
+ params = self.convert_params(params)
+ # replace | with space in bitrates because space is not allowed in the configuration file
+ if 'bitrates' in params:
+ params['bitrates'] = params['bitrates'].replace("|", " ")
+ self.net.addLink(name, cls=adhoc, intf='{}-wlan0'.format(name), **networkParams, **params)