Fix #122 [NS3] Implement wireless model scenarios with mobility
[nepi.git] / test / resources / linux / ns3 / ns3simulation.py
1 #!/usr/bin/env python
2 #
3 #    NEPI, a framework to manage network experiments
4 #    Copyright (C) 2013 INRIA
5 #
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.
10 #
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.
15 #
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/>.
18 #
19 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20
21
22 #
23 # Network topology
24 #
25 #       n0    n1   n2   n3
26 #       |     |    |    |
27 #       -----------------
28 #
29 #  node n0 sends IGMP traffic to node n3
30
31
32 from nepi.execution.ec import ExperimentController 
33 from nepi.execution.trace import TraceAttr
34
35 import os
36 import time
37 import unittest
38
39 def add_ns3_node(ec, simu):
40     node = ec.register_resource("ns3::Node")
41     ec.register_connection(node, simu)
42
43     ipv4 = ec.register_resource("ns3::Ipv4L3Protocol")
44     ec.register_connection(node, ipv4)
45
46     arp = ec.register_resource("ns3::ArpL3Protocol")
47     ec.register_connection(node, arp)
48     
49     icmp = ec.register_resource("ns3::Icmpv4L4Protocol")
50     ec.register_connection(node, icmp)
51
52     return node
53
54 def add_point2point_device(ec, node, address, prefix):
55     dev = ec.register_resource("ns3::PointToPointNetDevice")
56     ec.set(dev, "ip", address)
57     ec.set(dev, "prefix", prefix)
58     ec.register_connection(node, dev)
59
60     queue = ec.register_resource("ns3::DropTailQueue")
61     ec.register_connection(dev, queue)
62
63     return dev
64
65 def add_csma_device(ec, node, address, prefix):
66     dev = ec.register_resource("ns3::CsmaNetDevice")
67     ec.set(dev, "ip", address)
68     ec.set(dev, "prefix", prefix)
69     ec.register_connection(node, dev)
70
71     queue = ec.register_resource("ns3::DropTailQueue")
72     ec.register_connection(dev, queue)
73
74     return dev
75
76 def add_wifi_device(ec, node, address, prefix, 
77         access_point = False):
78     dev = ec.register_resource("ns3::WifiNetDevice")
79     ec.set(dev, "ip", address)
80     ec.set(dev, "prefix", prefix)
81     ec.register_connection(node, dev)
82
83     phy = ec.register_resource("ns3::YansWifiPhy")
84     ec.set(phy, "Standard", "WIFI_PHY_STANDARD_80211a")
85     ec.register_connection(dev, phy)
86
87     error = ec.register_resource("ns3::NistErrorRateModel")
88     ec.register_connection(phy, error)
89
90     manager = ec.register_resource("ns3::ArfWifiManager")
91     ec.register_connection(dev, manager)
92
93     if access_point:
94         mac = ec.register_resource("ns3::ApWifiMac")
95     else:
96         mac = ec.register_resource("ns3::StaWifiMac")
97
98     ec.set(mac, "Standard", "WIFI_PHY_STANDARD_80211a")
99     ec.register_connection(dev, mac)
100
101     return dev, phy
102
103 def add_random_mobility(ec, node, x, y, z, speed, bounds_width, 
104         bounds_height):
105     position = "%d:%d:%d" % (x, y, z)
106     bounds = "0|%d|0|%d" % (bounds_width, bounds_height) 
107     speed = "ns3::UniformRandomVariable[Min=%d|Max=%s]" % (speed, speed)
108     pause = "ns3::ConstantRandomVariable[Constant=1.0]"
109     
110     mobility = ec.register_resource("ns3::RandomDirection2dMobilityModel")
111     ec.set(mobility, "Position", position)
112     ec.set(mobility, "Bounds", bounds)
113     ec.set(mobility, "Speed", speed)
114     ec.set(mobility, "Pause",  pause)
115     ec.register_connection(node, mobility)
116     return mobility
117
118 def add_constant_mobility(ec, node, x, y, z):
119     mobility = ec.register_resource("ns3::ConstantPositionMobilityModel") 
120     position = "%d:%d:%d" % (x, y, z)
121     ec.set(mobility, "Position", position)
122     ec.register_connection(node, mobility)
123     return mobility
124
125 def add_wifi_channel(ec):
126     channel = ec.register_resource("ns3::YansWifiChannel")
127     delay = ec.register_resource("ns3::ConstantSpeedPropagationDelayModel")
128     ec.register_connection(channel, delay)
129
130     loss  = ec.register_resource("ns3::LogDistancePropagationLossModel")
131     ec.register_connection(channel, loss)
132
133     return channel
134
135 class LinuxNS3ClientTest(unittest.TestCase):
136     def setUp(self):
137         #self.fedora_host = "nepi2.pl.sophia.inria.fr"
138         self.fedora_host = "planetlabpc1.upf.edu"
139         #self.fedora_host = "peeramide.irisa.fr"
140         self.fedora_user = "inria_nepi"
141         self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
142
143     def test_simple_p2p_ping(self):
144         ec = ExperimentController(exp_id = "test-ns3-p2p-ping")
145         
146         node = ec.register_resource("LinuxNode")
147         ec.set(node, "hostname", self.fedora_host)
148         ec.set(node, "username", self.fedora_user)
149         ec.set(node, "identity", self.fedora_identity)
150         ec.set(node, "cleanProcesses", True)
151         #ec.set(node, "cleanHome", True)
152
153         simu = ec.register_resource("LinuxNS3Simulation")
154         ec.register_connection(simu, node)
155
156         nsnode1 = add_ns3_node(ec, simu)
157         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
158
159         nsnode2 = add_ns3_node(ec, simu)
160         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
161
162         # Create channel
163         chan = ec.register_resource("ns3::PointToPointChannel")
164         ec.set(chan, "Delay", "0s")
165         ec.register_connection(chan, dev1)
166         ec.register_connection(chan, dev2)
167
168         ### create pinger
169         ping = ec.register_resource("ns3::V4Ping")
170         ec.set (ping, "Remote", "10.0.0.2")
171         ec.set (ping, "Interval", "1s")
172         ec.set (ping, "Verbose", True)
173         ec.set (ping, "StartTime", "0s")
174         ec.set (ping, "StopTime", "20s")
175         ec.register_connection(ping, nsnode1)
176
177         ec.deploy()
178
179         ec.wait_finished([ping])
180         
181         stdout = ec.trace(simu, "stdout") 
182
183         expected = "20 packets transmitted, 20 received, 0% packet loss"
184         self.assertTrue(stdout.find(expected) > -1)
185
186         ec.shutdown()
187
188     def test_simple_cmsa_ping(self):
189         ec = ExperimentController(exp_id = "test-ns3-csma-ping")
190         
191         node = ec.register_resource("LinuxNode")
192         ec.set(node, "hostname", self.fedora_host)
193         ec.set(node, "username", self.fedora_user)
194         ec.set(node, "identity", self.fedora_identity)
195         ec.set(node, "cleanProcesses", True)
196         #ec.set(node, "cleanHome", True)
197
198         simu = ec.register_resource("LinuxNS3Simulation")
199         ec.register_connection(simu, node)
200
201         nsnode1 = add_ns3_node(ec, simu)
202         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
203
204         nsnode2 = add_ns3_node(ec, simu)
205         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
206
207         # Create channel
208         chan = ec.register_resource("ns3::CsmaChannel")
209         ec.set(chan, "Delay", "0s")
210         ec.register_connection(chan, dev1)
211         ec.register_connection(chan, dev2)
212
213         ### create pinger
214         ping = ec.register_resource("ns3::V4Ping")
215         ec.set (ping, "Remote", "10.0.0.2")
216         ec.set (ping, "Interval", "1s")
217         ec.set (ping, "Verbose", True)
218         ec.set (ping, "StartTime", "0s")
219         ec.set (ping, "StopTime", "20s")
220         ec.register_connection(ping, nsnode1)
221
222         ec.deploy()
223
224         ec.wait_finished([ping])
225         
226         stdout = ec.trace(simu, "stdout") 
227
228         expected = "20 packets transmitted, 20 received, 0% packet loss"
229         self.assertTrue(stdout.find(expected) > -1)
230
231         ec.shutdown()
232
233     def test_compile_local_source(self):
234         ec = ExperimentController(exp_id = "test-ns3-local-source")
235         
236         node = ec.register_resource("LinuxNode")
237         ec.set(node, "hostname", self.fedora_host)
238         ec.set(node, "username", self.fedora_user)
239         ec.set(node, "identity", self.fedora_identity)
240         ec.set(node, "cleanProcesses", True)
241         #ec.set(node, "cleanHome", True)
242
243         simu = ec.register_resource("LinuxNS3Simulation")
244         sources = os.path.join(os.path.dirname(os.path.realpath(__file__)), 
245                 "ns-3.18-user.tar.gz")
246         ec.set(simu, "sources", sources)
247         ec.register_connection(simu, node)
248
249         nsnode1 = add_ns3_node(ec, simu)
250         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
251
252         nsnode2 = add_ns3_node(ec, simu)
253         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
254
255         # Create channel
256         chan = ec.register_resource("ns3::CsmaChannel")
257         ec.set(chan, "Delay", "0s")
258         ec.register_connection(chan, dev1)
259         ec.register_connection(chan, dev2)
260
261         ### create pinger
262         ping = ec.register_resource("ns3::V4Ping")
263         ec.set (ping, "Remote", "10.0.0.2")
264         ec.set (ping, "Interval", "1s")
265         ec.set (ping, "Verbose", True)
266         ec.set (ping, "StartTime", "0s")
267         ec.set (ping, "StopTime", "20s")
268         ec.register_connection(ping, nsnode1)
269
270         ec.deploy()
271
272         ec.wait_finished([ping])
273         
274         stdout = ec.trace(simu, "stdout") 
275
276         expected = "20 packets transmitted, 20 received, 0% packet loss"
277         self.assertTrue(stdout.find(expected) > -1)
278         
279         ec.shutdown()
280
281     def test_compile_debug_mode(self):
282         ec = ExperimentController(exp_id = "test-ns3-debug-mode")
283         
284         node = ec.register_resource("LinuxNode")
285         ec.set(node, "hostname", self.fedora_host)
286         ec.set(node, "username", self.fedora_user)
287         ec.set(node, "identity", self.fedora_identity)
288         ec.set(node, "cleanProcesses", True)
289         #ec.set(node, "cleanHome", True)
290
291         simu = ec.register_resource("LinuxNS3Simulation")
292         ec.set(simu, "verbose", True)
293         ec.set(simu, "nsLog", "V4Ping:Node")
294         ec.set(simu, "buildMode", "debug")
295         ec.register_connection(simu, node)
296
297         nsnode1 = add_ns3_node(ec, simu)
298         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
299
300         nsnode2 = add_ns3_node(ec, simu)
301         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
302
303         # Create channel
304         chan = ec.register_resource("ns3::CsmaChannel")
305         ec.set(chan, "Delay", "0s")
306         ec.register_connection(chan, dev1)
307         ec.register_connection(chan, dev2)
308
309         ### create pinger
310         ping = ec.register_resource("ns3::V4Ping")
311         ec.set (ping, "Remote", "10.0.0.2")
312         ec.set (ping, "Interval", "1s")
313         ec.set (ping, "Verbose", True)
314         ec.set (ping, "StartTime", "0s")
315         ec.set (ping, "StopTime", "20s")
316         ec.register_connection(ping, nsnode1)
317
318         ec.deploy()
319
320         ec.wait_finished([ping])
321         
322         stdout = ec.trace(simu, "stdout") 
323
324         expected = "20 packets transmitted, 20 received, 0% packet loss"
325         self.assertTrue(stdout.find(expected) > -1)
326         
327         stderr = ec.trace(simu, "stderr")
328         expected = "V4Ping:Read32"
329         self.assertTrue(stderr.find(expected) > -1)
330
331         ec.shutdown()
332
333     def test_real_time(self):
334         ec = ExperimentController(exp_id = "test-ns3-real-time")
335         
336         node = ec.register_resource("LinuxNode")
337         ec.set(node, "hostname", self.fedora_host)
338         ec.set(node, "username", self.fedora_user)
339         ec.set(node, "identity", self.fedora_identity)
340         ec.set(node, "cleanProcesses", True)
341         #ec.set(node, "cleanHome", True)
342
343         simu = ec.register_resource("LinuxNS3Simulation")
344         ec.set(simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl")
345         ec.set(simu, "checksumEnabled", True)
346         ec.set(simu, "verbose", True)
347         ec.register_connection(simu, node)
348
349         nsnode1 = add_ns3_node(ec, simu)
350         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
351
352         nsnode2 = add_ns3_node(ec, simu)
353         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
354
355         # Create channel
356         chan = ec.register_resource("ns3::PointToPointChannel")
357         ec.set(chan, "Delay", "0s")
358         ec.register_connection(chan, dev1)
359         ec.register_connection(chan, dev2)
360
361         ### create pinger
362         ping = ec.register_resource("ns3::V4Ping")
363         ec.set (ping, "Remote", "10.0.0.2")
364         ec.set (ping, "Interval", "1s")
365         ec.set (ping, "Verbose", True)
366         ec.set (ping, "StartTime", "0s")
367         ec.set (ping, "StopTime", "20s")
368         ec.register_connection(ping, nsnode1)
369
370         ec.deploy()
371
372         ec.wait_finished([ping])
373       
374         stdout = ec.trace(simu, "stdout") 
375
376         expected = "20 packets transmitted, 20 received, 0% packet loss"
377         self.assertTrue(stdout.find(expected) > -1)
378
379         rm = ec.get_resource(ping)
380         start_time = rm.start_time
381         stop_time = rm.stop_time
382         delta =  stop_time - start_time
383
384         self.assertTrue(delta.seconds >= 20)
385         self.assertTrue(delta.seconds < 25)
386
387         ec.shutdown()
388
389     def test_dev2p_traces(self):
390         ec = ExperimentController(exp_id = "test-ns3-dev2p-traces")
391         
392         node = ec.register_resource("LinuxNode")
393         ec.set(node, "hostname", self.fedora_host)
394         ec.set(node, "username", self.fedora_user)
395         ec.set(node, "identity", self.fedora_identity)
396         ec.set(node, "cleanProcesses", True)
397         #ec.set(node, "cleanHome", True)
398
399         simu = ec.register_resource("LinuxNS3Simulation")
400         ec.register_connection(simu, node)
401
402         nsnode1 = add_ns3_node(ec, simu)
403         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
404
405         nsnode2 = add_ns3_node(ec, simu)
406         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
407
408         # Create channel
409         chan = ec.register_resource("ns3::PointToPointChannel")
410         ec.set(chan, "Delay", "0s")
411         ec.register_connection(chan, dev1)
412         ec.register_connection(chan, dev2)
413
414         ### create pinger
415         ping = ec.register_resource("ns3::V4Ping")
416         ec.set (ping, "Remote", "10.0.0.2")
417         ec.set (ping, "Interval", "1s")
418         ec.set (ping, "Verbose", True)
419         ec.set (ping, "StartTime", "0s")
420         ec.set (ping, "StopTime", "20s")
421         ec.register_connection(ping, nsnode1)
422
423         # enable traces
424         ec.enable_trace(dev1, "pcap")
425         ec.enable_trace(dev1, "promiscPcap")
426         ec.enable_trace(dev1, "ascii")
427
428         ec.enable_trace(dev2, "pcap")
429         ec.enable_trace(dev2, "promiscPcap")
430         ec.enable_trace(dev2, "ascii")
431
432         ec.deploy()
433
434         ec.wait_finished([ping])
435
436         # Trace verification
437         rm_simu = ec.get_resource(simu)
438
439         # TODO: Fix this in ns-3: pcap traces do not flush until the Simulator 
440         #   process is ended, so we can't get the traces of the 'pcap' and
441         #   'promiscPcap' traces.
442         #
443         #for trace in ["pcap", "promiscPcap", "ascii"]:
444         for trace in ["ascii"]:
445             for guid in [dev1, dev2]:
446                 output = ec.trace(guid, trace)
447
448                 size = ec.trace(guid, trace, attr = TraceAttr.SIZE)
449                 self.assertEquals(size, len(output))
450                 self.assertTrue(size > 100)
451                 
452                 block = ec.trace(guid, trace, attr = TraceAttr.STREAM, block = 5, offset = 1)
453                 self.assertEquals(block, output[5:10])
454
455                 trace_path = ec.trace(guid, trace, attr = TraceAttr.PATH)
456                 rm = ec.get_resource(guid)
457                 path = os.path.join(rm_simu.run_home, rm._trace_filename.get(trace))
458                 self.assertEquals(trace_path, path)
459
460         ec.shutdown()
461
462     def test_simple_wifi_ping(self):
463         bounds_width = bounds_height = 200
464         x = y = 100
465         speed = 1
466
467         ec = ExperimentController(exp_id = "test-ns3-wifi-ping")
468         
469         node = ec.register_resource("LinuxNode")
470         ec.set(node, "hostname", self.fedora_host)
471         ec.set(node, "username", self.fedora_user)
472         ec.set(node, "identity", self.fedora_identity)
473         ec.set(node, "cleanProcesses", True)
474         #ec.set(node, "cleanHome", True)
475
476         simu = ec.register_resource("LinuxNS3Simulation")
477         ec.set(simu, "verbose", True)
478         ec.register_connection(simu, node)
479
480         nsnode1 = add_ns3_node(ec, simu)
481         dev1, phy1 = add_wifi_device(ec, nsnode1, "10.0.0.1", "24", access_point = True)
482         mobility1 = add_constant_mobility(ec, nsnode1, x, y, 0)
483
484         nsnode2 = add_ns3_node(ec, simu)
485         dev2, phy2 = add_wifi_device(ec, nsnode2, "10.0.0.2", "24", access_point = False)
486         mobility1 = add_constant_mobility(ec, nsnode2, x, y, 0)
487         #mobility2 = add_random_mobility(ec, nsnode2, x, y, 0, speed, bounds_width, bounds_height)
488
489         # Create channel
490         chan = add_wifi_channel(ec)
491         ec.register_connection(chan, phy1)
492         ec.register_connection(chan, phy2)
493
494         ### create pinger
495         ping = ec.register_resource("ns3::V4Ping")
496         ec.set (ping, "Remote", "10.0.0.1")
497         ec.set (ping, "Interval", "1s")
498         ec.set (ping, "Verbose", True)
499         ec.set (ping, "StartTime", "1s")
500         ec.set (ping, "StopTime", "21s")
501         ec.register_connection(ping, nsnode2)
502
503         ec.deploy()
504
505         ec.wait_finished([ping])
506         
507         stdout = ec.trace(simu, "stdout")
508
509         expected = "20 packets transmitted, 20 received, 0% packet loss"
510         self.assertTrue(stdout.find(expected) > -1)
511
512         ec.shutdown()
513
514 if __name__ == '__main__':
515     unittest.main()
516