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