blob: 54b4aad5da59782ede699d909c4b4347fbecbf5e [file] [log] [blame]
Alexander Laneea2d5d62019-10-04 16:48:52 -05001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
dulalsaurab20855442021-05-21 20:37:03 +00003# Copyright (C) 2015-2021, The University of Memphis,
Alexander Laneea2d5d62019-10-04 16:48:52 -05004# Arizona Board of Regents,
5# Regents of the University of California.
6#
7# This file is part of Mini-NDN.
8# See AUTHORS.md for a complete list of Mini-NDN authors and contributors.
9#
10# Mini-NDN is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# Mini-NDN is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with Mini-NDN, e.g., in COPYING.md file.
22# If not, see <http://www.gnu.org/licenses/>.
23
awlanea169f572022-04-08 17:21:29 -050024import os
Alexander Laneea2d5d62019-10-04 16:48:52 -050025import argparse
26import sys
Alexander Laneea2d5d62019-10-04 16:48:52 -050027import configparser
dulalsaurab20855442021-05-21 20:37:03 +000028from subprocess import Popen, PIPE
Alexander Laneea2d5d62019-10-04 16:48:52 -050029
Alexander Laneea2d5d62019-10-04 16:48:52 -050030from mininet.log import info, debug
31
32from mn_wifi.topo import Topo as Topo_WiFi
33from mn_wifi.net import Mininet_wifi
Alexander Laneea2d5d62019-10-04 16:48:52 -050034from mn_wifi.link import WirelessLink
35
36from minindn.minindn import Minindn
37
38class MinindnWifi(Minindn):
Alex Lane407c5f02021-03-09 22:13:23 -060039 """ Class for handling default args, Mininet-wifi object and home directories """
awlanea169f572022-04-08 17:21:29 -050040 def __init__(self, parser=argparse.ArgumentParser(), topo=None, topoFile=None, noTopo=False, link=WirelessLink, workDir=None, **mininetParams):
Alexander Laneea2d5d62019-10-04 16:48:52 -050041 """Create Mini-NDN-Wifi object
42 parser: Parent parser of Mini-NDN-Wifi parser (use to specify experiment arguments)
43 topo: Mininet topo object (optional)
44 topoFile: topology file location (optional)
Alex Lane407c5f02021-03-09 22:13:23 -060045 noTopo: Allows specification of topology after network object is initialized (optional)
46 link: Allows specification of default Mininet/Mininet-Wifi link type for connections between nodes (optional)
Alexander Laneea2d5d62019-10-04 16:48:52 -050047 mininetParams: Any params to pass to Mininet-WiFi
48 """
49 self.parser = self.parseArgs(parser)
50 self.args = self.parser.parse_args()
51
awlanea169f572022-04-08 17:21:29 -050052 if not workDir:
53 Minindn.workDir = os.path.abspath(self.args.workDir)
54 else:
55 Minindn.workDir = os.path.abspath(workDir)
56
Alexander Laneea2d5d62019-10-04 16:48:52 -050057 Minindn.resultDir = self.args.resultDir
58
59 self.topoFile = None
60 if not topoFile:
61 # Args has default topology if none specified
62 self.topoFile = self.args.topoFile
63 else:
64 self.topoFile = topoFile
65
Alex Lane407c5f02021-03-09 22:13:23 -060066 if topo is None and not noTopo:
Alexander Laneea2d5d62019-10-04 16:48:52 -050067 try:
68 info('Using topology file {}\n'.format(self.topoFile))
69 self.topo = self.processTopo(self.topoFile)
70 except configparser.NoSectionError as e:
71 info('Error reading config file: {}\n'.format(e))
72 sys.exit(1)
73 else:
74 self.topo = topo
75
Alex Lane407c5f02021-03-09 22:13:23 -060076 if not noTopo:
77 self.net = Mininet_wifi(topo=self.topo, ifb=self.args.ifb, link=link, **mininetParams)
78 else:
79 self.net = Mininet_wifi(ifb=self.args.ifb, link=link, **mininetParams)
Alexander Laneea2d5d62019-10-04 16:48:52 -050080
Alex Lane407c5f02021-03-09 22:13:23 -060081 # Prevents crashes running mixed topos
82 nodes = self.net.stations + self.net.hosts + self.net.cars
83 self.initParams(nodes)
84
Alexander Laneea2d5d62019-10-04 16:48:52 -050085 try:
86 process = Popen(['ndnsec-get-default', '-k'], stdout=PIPE, stderr=PIPE)
87 output, error = process.communicate()
88 if process.returncode == 0:
awlanec32a07b2022-04-19 14:53:41 -050089 Minindn.ndnSecurityDisabled = '/dummy/KEY/-%9C%28r%B8%AA%3B%60' in output.decode("utf-8")
Alex Lane407c5f02021-03-09 22:13:23 -060090 info('Dummy key chain patch is installed in ndn-cxx. Security will be disabled.\n')
Alexander Laneea2d5d62019-10-04 16:48:52 -050091 else:
Alex Lane407c5f02021-03-09 22:13:23 -060092 debug(error)
Alexander Laneea2d5d62019-10-04 16:48:52 -050093 except:
94 pass
95
96 self.cleanups = []
97
98 @staticmethod
99 def parseArgs(parent):
100 parser = argparse.ArgumentParser(prog='minindn-wifi', parents=[parent], add_help=False)
101
102 # nargs='?' required here since optional argument
103 parser.add_argument('topoFile', nargs='?', default='/usr/local/etc/mini-ndn/singleap-topology.conf',
104 help='If no template_file is given, topologies/wifi/singleap-topology.conf will be used.')
105
106 parser.add_argument('--work-dir', action='store', dest='workDir', default='/tmp/minindn',
107 help='Specify the working directory; default is /tmp/minindn')
108
109 parser.add_argument('--result-dir', action='store', dest='resultDir', default=None,
110 help='Specify the full path destination folder where experiment results will be moved')
111
112 parser.add_argument('--mobility',action='store_true',dest='mobility',default=False,
113 help='Enable custom mobility for topology (defined in topology file)')
114
115 parser.add_argument('--model-mob',action='store_true',dest='modelMob',default=False,
116 help='Enable model mobility for topology (defined in topology file)')
117
118 parser.add_argument('--ifb',action='store_true',dest='ifb',default=False,
119 help='Simulate delay on receiver-side by use of virtual IFB devices (see docs)')
120
121 return parser
122
123 @staticmethod
124 def processTopo(topoFile):
125 config = configparser.ConfigParser(delimiters=' ')
126 config.read(topoFile)
127 topo = Topo_WiFi()
128
129 items = config.items('stations')
130 debug("Stations")
131 for item in items:
132 debug(item[0].split(':'))
133 name = item[0].split(':')[0]
134 params = {}
135 for param in item[1].split(' '):
136 if param == "_":
137 continue
138 key = param.split('=')[0]
139 value = param.split('=')[1]
140 if key in ['range']:
141 value = int(value)
142 params[key] = value
143
144 topo.addStation(name, **params)
145
146 try:
147 debug("Switches")
148 items = config.items('switches')
149 for item in items:
150 debug(item[0].split(':'))
151 name = item[0].split(':')[0]
152 topo.addSwitch(name)
153 except configparser.NoSectionError:
154 debug("Switches are optional")
155 pass
156
157 try:
158 debug("APs")
159 items = config.items('accessPoints')
160 for item in items:
161 debug(item[0].split(':'))
162 name = item[0].split(':')[0]
163 ap_params = {}
164 for param in item[1].split(' '):
165 if param == "_":
166 continue
167 key = param.split('=')[0]
168 value = param.split('=')[1]
169 if key in ['range']:
170 value = int(value)
171 ap_params[key] = value
172 topo.addAccessPoint(name, **ap_params)
173 except configparser.NoSectionError:
174 debug("APs are optional")
175 pass
176
177 items = config.items('links')
178 debug("Links")
179 for item in items:
180 link = item[0].split(':')
181 debug(link)
182 params = {}
183 for param in item[1].split(' '):
184 if param == "_":
185 continue
186 key = param.split('=')[0]
187 value = param.split('=')[1]
188 if key in ['bw', 'jitter', 'max_queue_size']:
189 value = int(value)
190 if key == 'loss':
191 value = float(value)
192 params[key] = value
193
194 topo.addLink(link[0], link[1], **params)
195
196 return topo
197
198 def startMobility(self, max_x=1000, max_y=1000, **kwargs):
199 """ Method to run a basic mobility setup on your net"""
200 self.net.plotGraph(max_x=max_x, max_y=max_y)
201 self.net.startMobility(**kwargs)
202
203 def startMobilityModel(self, max_x=1000, max_y=1000, **kwargs):
204 """ Method to run a mobility model on your net until exited"""
205 self.net.plotGraph(max_x=max_x, max_y=max_y)
206 self.net.setMobilityModel(**kwargs)