3 # NEPI, a framework to manage network experiments
4 # Copyright (C) 2013 INRIA
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
21 from nepi.execution.ec import ExperimentController
22 from nepi.execution.trace import TraceAttr
24 from test_utils import skipIfNotAlive
32 def add_ns3_node(ec, simu):
33 node = ec.register_resource("ns3::Node")
34 ec.register_connection(node, simu)
36 ipv4 = ec.register_resource("ns3::Ipv4L3Protocol")
37 ec.register_connection(node, ipv4)
39 arp = ec.register_resource("ns3::ArpL3Protocol")
40 ec.register_connection(node, arp)
42 icmp = ec.register_resource("ns3::Icmpv4L4Protocol")
43 ec.register_connection(node, icmp)
45 udp = ec.register_resource("ns3::UdpL4Protocol")
46 ec.register_connection(node, udp)
50 def add_point2point_device(ec, node, ip, prefix):
51 dev = ec.register_resource("ns3::PointToPointNetDevice")
53 ec.set(dev, "prefix", prefix)
54 ec.register_connection(node, dev)
56 queue = ec.register_resource("ns3::DropTailQueue")
57 ec.register_connection(dev, queue)
61 def add_csma_device(ec, node, ip, prefix):
62 dev = ec.register_resource("ns3::CsmaNetDevice")
64 ec.set(dev, "prefix", prefix)
65 ec.register_connection(node, dev)
67 queue = ec.register_resource("ns3::DropTailQueue")
68 ec.register_connection(dev, queue)
72 def add_wifi_device(ec, node, ip, prefix,
73 access_point = False):
74 dev = ec.register_resource("ns3::WifiNetDevice")
76 ec.set(dev, "prefix", prefix)
77 ec.register_connection(node, dev)
79 phy = ec.register_resource("ns3::YansWifiPhy")
80 ec.set(phy, "Standard", "WIFI_PHY_STANDARD_80211a")
81 ec.register_connection(dev, phy)
83 error = ec.register_resource("ns3::NistErrorRateModel")
84 ec.register_connection(phy, error)
86 manager = ec.register_resource("ns3::ArfWifiManager")
87 ec.register_connection(dev, manager)
90 mac = ec.register_resource("ns3::ApWifiMac")
92 mac = ec.register_resource("ns3::StaWifiMac")
94 ec.set(mac, "Standard", "WIFI_PHY_STANDARD_80211a")
95 ec.register_connection(dev, mac)
99 def add_random_mobility(ec, node, x, y, z, speed, bounds_width,
101 position = "%d:%d:%d" % (x, y, z)
102 bounds = "0|%d|0|%d" % (bounds_width, bounds_height)
103 speed = "ns3::UniformRandomVariable[Min=%d|Max=%s]" % (speed, speed)
104 pause = "ns3::ConstantRandomVariable[Constant=1.0]"
106 mobility = ec.register_resource("ns3::RandomDirection2dMobilityModel")
107 ec.set(mobility, "Position", position)
108 ec.set(mobility, "Bounds", bounds)
109 ec.set(mobility, "Speed", speed)
110 ec.set(mobility, "Pause", pause)
111 ec.register_connection(node, mobility)
114 def add_constant_mobility(ec, node, x, y, z):
115 mobility = ec.register_resource("ns3::ConstantPositionMobilityModel")
116 position = "%d:%d:%d" % (x, y, z)
117 ec.set(mobility, "Position", position)
118 ec.register_connection(node, mobility)
121 def add_wifi_channel(ec):
122 channel = ec.register_resource("ns3::YansWifiChannel")
123 delay = ec.register_resource("ns3::ConstantSpeedPropagationDelayModel")
124 ec.register_connection(channel, delay)
126 loss = ec.register_resource("ns3::LogDistancePropagationLossModel")
127 ec.register_connection(channel, loss)
131 class LinuxNS3SimulationSerializationTest(unittest.TestCase):
133 #self.fedora_host = "nepi2.pl.sophia.inria.fr"
134 self.fedora_host = "planetlab1.informatik.uni-erlangen.de"
135 self.fedora_user = "inria_nepi"
136 self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
139 def t_wifi_serialize(self, host, user = None, identity = None):
140 bounds_width = bounds_height = 200
144 dirpath = tempfile.mkdtemp()
146 ec = ExperimentController(exp_id = "test-ns3-wifi-ping")
148 node = ec.register_resource("LinuxNode")
149 if host == "localhost":
150 ec.set(node, "hostname", "localhost")
152 ec.set(node, "hostname", host)
153 ec.set(node, "username", user)
154 ec.set(node, "identity", identity)
156 ec.set(node, "cleanProcesses", True)
157 #ec.set(node, "cleanHome", True)
159 simu = ec.register_resource("LinuxNS3Simulation")
160 ec.set(simu, "verbose", True)
161 ec.register_connection(simu, node)
163 nsnode1 = add_ns3_node(ec, simu)
164 dev1, phy1 = add_wifi_device(ec, nsnode1, "10.0.0.1", "24", access_point = True)
165 mobility1 = add_constant_mobility(ec, nsnode1, x, y, 0)
167 nsnode2 = add_ns3_node(ec, simu)
168 dev2, phy2 = add_wifi_device(ec, nsnode2, "10.0.0.2", "24", access_point = False)
169 mobility1 = add_constant_mobility(ec, nsnode2, x, y, 0)
170 #mobility2 = add_random_mobility(ec, nsnode2, x, y, 0, speed, bounds_width, bounds_height)
173 chan = add_wifi_channel(ec)
174 ec.register_connection(chan, phy1)
175 ec.register_connection(chan, phy2)
178 ping = ec.register_resource("ns3::V4Ping")
179 ec.set (ping, "Remote", "10.0.0.1")
180 ec.set (ping, "Interval", "1s")
181 ec.set (ping, "Verbose", True)
182 ec.set (ping, "StartTime", "1s")
183 ec.set (ping, "StopTime", "21s")
184 ec.register_connection(ping, nsnode2)
186 filepath = ec.save(dirpath)
191 ec.wait_finished([ping])
193 stdout = ec.trace(simu, "stdout")
195 expected = "20 packets transmitted, 20 received, 0% packet loss"
196 self.assertTrue(stdout.find(expected) > -1)
200 # Load serialized experiment
201 ec2 = ExperimentController.load(filepath)
205 ec2.wait_finished([ping])
207 self.assertEquals(len(ec.resources), len(ec2.resources))
209 stdout = ec2.trace(simu, "stdout")
211 expected = "20 packets transmitted, 20 received, 0% packet loss"
212 self.assertTrue(stdout.find(expected) > -1)
216 shutil.rmtree(dirpath)
219 def t_routing_serialize(self, host, user = None, identity = None):
224 n1 -- p2p -- n2 -- csma -- n5 -- p2p -- n6
230 dirpath = tempfile.mkdtemp()
232 ec = ExperimentController(exp_id = "test-ns3-routes")
234 node = ec.register_resource("LinuxNode")
235 if host == "localhost":
236 ec.set(node, "hostname", host)
238 ec.set(node, "hostname", host)
239 ec.set(node, "username", user)
240 ec.set(node, "identity", identity)
242 ec.set(node, "cleanProcesses", True)
243 #ec.set(node, "cleanHome", True)
245 simu = ec.register_resource("LinuxNS3Simulation")
246 ec.set(simu, "verbose", True)
247 ec.register_connection(simu, node)
249 nsnode1 = add_ns3_node(ec, simu)
250 p2p12 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
252 nsnode2 = add_ns3_node(ec, simu)
253 p2p21 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
254 csma2 = add_csma_device(ec, nsnode2, "10.0.1.1", "24")
256 nsnode3 = add_ns3_node(ec, simu)
257 csma3 = add_csma_device(ec, nsnode3, "10.0.1.2", "24")
259 nsnode4 = add_ns3_node(ec, simu)
260 csma4 = add_csma_device(ec, nsnode4, "10.0.1.3", "24")
262 nsnode5 = add_ns3_node(ec, simu)
263 p2p56 = add_point2point_device(ec, nsnode5, "10.0.2.1", "30")
264 csma5 = add_csma_device(ec, nsnode5, "10.0.1.4", "24")
266 nsnode6 = add_ns3_node(ec, simu)
267 p2p65 = add_point2point_device(ec, nsnode6, "10.0.2.2", "30")
270 p2p_chan1 = ec.register_resource("ns3::PointToPointChannel")
271 ec.set(p2p_chan1, "Delay", "0s")
272 ec.register_connection(p2p_chan1, p2p12)
273 ec.register_connection(p2p_chan1, p2p21)
276 csma_chan = ec.register_resource("ns3::CsmaChannel")
277 ec.set(csma_chan, "Delay", "0s")
278 ec.register_connection(csma_chan, csma2)
279 ec.register_connection(csma_chan, csma3)
280 ec.register_connection(csma_chan, csma4)
281 ec.register_connection(csma_chan, csma5)
284 p2p_chan2 = ec.register_resource("ns3::PointToPointChannel")
285 ec.set(p2p_chan2, "Delay", "0s")
286 ec.register_connection(p2p_chan2, p2p56)
287 ec.register_connection(p2p_chan2, p2p65)
289 # Add routes - n1 - n6
290 r1 = ec.register_resource("ns3::Route")
291 ec.set(r1, "network", "10.0.2.0")
292 ec.set(r1, "prefix", "30")
293 ec.set(r1, "nexthop", "10.0.0.2")
294 ec.register_connection(r1, nsnode1)
296 # Add routes - n2 - n6
297 r2 = ec.register_resource("ns3::Route")
298 ec.set(r2, "network", "10.0.2.0")
299 ec.set(r2, "prefix", "30")
300 ec.set(r2, "nexthop", "10.0.1.4")
301 ec.register_connection(r2, nsnode2)
303 # Add routes - n5 - n1
304 r5 = ec.register_resource("ns3::Route")
305 ec.set(r5, "network", "10.0.0.0")
306 ec.set(r5, "prefix", "30")
307 ec.set(r5, "nexthop", "10.0.1.1")
308 ec.register_connection(r5, nsnode5)
310 # Add routes - n6 - n1
311 r6 = ec.register_resource("ns3::Route")
312 ec.set(r6, "network", "10.0.0.0")
313 ec.set(r6, "prefix", "30")
314 ec.set(r6, "nexthop", "10.0.2.1")
315 ec.register_connection(r6, nsnode6)
318 ping = ec.register_resource("ns3::V4Ping")
319 ec.set (ping, "Remote", "10.0.2.2")
320 ec.set (ping, "Interval", "1s")
321 ec.set (ping, "Verbose", True)
322 ec.set (ping, "StartTime", "1s")
323 ec.set (ping, "StopTime", "21s")
324 ec.register_connection(ping, nsnode1)
326 filepath = ec.save(dirpath)
331 ec.wait_finished([ping])
333 stdout = ec.trace(simu, "stdout")
335 expected = "20 packets transmitted, 20 received, 0% packet loss"
336 self.assertTrue(stdout.find(expected) > -1)
340 # Load serialized experiment
341 ec2 = ExperimentController.load(filepath)
345 ec2.wait_finished([ping])
347 self.assertEquals(len(ec.resources), len(ec2.resources))
349 stdout = ec2.trace(simu, "stdout")
351 expected = "20 packets transmitted, 20 received, 0% packet loss"
352 self.assertTrue(stdout.find(expected) > -1)
356 shutil.rmtree(dirpath)
359 def t_dce_serialize(self, host, user = None, identity = None):
360 dirpath = tempfile.mkdtemp()
362 ec = ExperimentController(exp_id = "test-ns3-dce")
364 node = ec.register_resource("LinuxNode")
365 if host == "localhost":
366 ec.set(node, "hostname", host)
368 ec.set(node, "hostname", host)
369 ec.set(node, "username", user)
370 ec.set(node, "identity", identity)
372 ec.set(node, "cleanProcesses", True)
373 #ec.set(node, "cleanHome", True)
375 simu = ec.register_resource("LinuxNS3Simulation")
376 ec.set(simu, "verbose", True)
377 ec.register_connection(simu, node)
379 nsnode1 = add_ns3_node(ec, simu)
380 p2p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
381 ec.set(p2p1, "DataRate", "5Mbps")
383 nsnode2 = add_ns3_node(ec, simu)
384 p2p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
385 ec.set(p2p2, "DataRate", "5Mbps")
388 chan = ec.register_resource("ns3::PointToPointChannel")
389 ec.set(chan, "Delay", "2ms")
391 ec.register_connection(chan, p2p1)
392 ec.register_connection(chan, p2p2)
394 ### create applications
395 udp_perf = ec.register_resource("ns3::DceApplication")
396 ec.set (udp_perf, "binary", "udp-perf")
397 ec.set (udp_perf, "stackSize", 1<<20)
398 ec.set (udp_perf, "arguments", "--duration=10;--nodes=2")
399 ec.set (udp_perf, "StartTime", "1s")
400 ec.set (udp_perf, "StopTime", "20s")
401 ec.register_connection(udp_perf, nsnode1)
403 udp_perf_client = ec.register_resource("ns3::DceApplication")
404 ec.set (udp_perf_client, "binary", "udp-perf")
405 ec.set (udp_perf_client, "stackSize", 1<<20)
406 ec.set (udp_perf_client, "arguments", "--client;--nodes=2;--host=10.0.0.1;--duration=10")
407 ec.set (udp_perf_client, "StartTime", "2s")
408 ec.set (udp_perf_client, "StopTime", "20s")
409 ec.register_connection(udp_perf_client, nsnode2)
411 filepath = ec.save(dirpath)
415 ec.wait_finished([udp_perf_client])
417 # Give time to flush the streams
421 expected = "udp-perf --duration=10 --nodes=2"
422 cmdline = ec.trace(udp_perf, "cmdline")
423 self.assertTrue(cmdline.find(expected) > -1, cmdline)
425 expected = "Start Time: NS3 Time: 1s ("
426 status = ec.trace(udp_perf, "status")
427 self.assertTrue(status.find(expected) > -1, status)
429 expected = "received=1500 bytes, 1 reads (@1500 bytes) 1500"
430 stdout = ec.trace(udp_perf, "stdout")
431 self.assertTrue(stdout.find(expected) > -1, stdout)
435 # Load serialized experiment
436 ec2 = ExperimentController.load(filepath)
439 ec2.wait_finished([udp_perf_client])
441 # Give time to flush the streams
444 self.assertEquals(len(ec.resources), len(ec2.resources))
446 expected = "udp-perf --duration=10 --nodes=2"
447 cmdline = ec2.trace(udp_perf, "cmdline")
448 self.assertTrue(cmdline.find(expected) > -1, cmdline)
450 expected = "Start Time: NS3 Time: 1s ("
451 status = ec2.trace(udp_perf, "status")
452 self.assertTrue(status.find(expected) > -1, status)
454 expected = "received=1500 bytes, 1 reads (@1500 bytes) 1500"
455 stdout = ec2.trace(udp_perf, "stdout")
456 self.assertTrue(stdout.find(expected) > -1, stdout)
460 shutil.rmtree(dirpath)
462 def test_wifi_serialize_fedora(self):
463 self.t_wifi_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
465 def test_wifi_serialize_local(self):
466 self.t_wifi_serialize("localhost")
468 def test_routing_serialize_fedora(self):
469 self.t_routing_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
471 def test_routing_serialize_local(self):
472 self.t_routing_serialize("localhost")
474 def test_dce_serialize_fedora(self):
475 self.t_dce_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
477 def test_dce_serialize_local(self):
478 self.t_dce_serialize("localhost")
481 if __name__ == '__main__':