Fix #123 [NS3] Upload a local ns-3 sources tar
[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 class LinuxNS3ClientTest(unittest.TestCase):
77     def setUp(self):
78         #self.fedora_host = "nepi2.pl.sophia.inria.fr"
79         self.fedora_host = "planetlabpc1.upf.edu"
80         #self.fedora_host = "peeramide.irisa.fr"
81         self.fedora_user = "inria_nepi"
82         #self.fedora_user = "inria_alina"
83         self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
84
85     def test_simple_p2p_ping(self):
86         ec = ExperimentController(exp_id = "test-ns3-p2p-ping")
87         
88         node = ec.register_resource("LinuxNode")
89         ec.set(node, "hostname", self.fedora_host)
90         ec.set(node, "username", self.fedora_user)
91         ec.set(node, "identity", self.fedora_identity)
92         ec.set(node, "cleanProcesses", True)
93         #ec.set(node, "cleanHome", True)
94
95         simu = ec.register_resource("LinuxNS3Simulation")
96         ec.register_connection(simu, node)
97
98         nsnode1 = add_ns3_node(ec, simu)
99         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
100
101         nsnode2 = add_ns3_node(ec, simu)
102         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
103
104         # Create channel
105         chan = ec.register_resource("ns3::PointToPointChannel")
106         ec.set(chan, "Delay", "0s")
107         ec.register_connection(chan, dev1)
108         ec.register_connection(chan, dev2)
109
110         ### create pinger
111         ping = ec.register_resource("ns3::V4Ping")
112         ec.set (ping, "Remote", "10.0.0.2")
113         ec.set (ping, "Interval", "1s")
114         ec.set (ping, "Verbose", True)
115         ec.set (ping, "StartTime", "0s")
116         ec.set (ping, "StopTime", "20s")
117         ec.register_connection(ping, nsnode1)
118
119         ec.deploy()
120
121         ec.wait_finished([ping])
122         
123         stdout = ec.trace(simu, "stdout") 
124
125         expected = "20 packets transmitted, 20 received, 0% packet loss"
126         self.assertTrue(stdout.find(expected) > -1)
127
128         ec.shutdown()
129
130     def test_simple_cmsa_ping(self):
131         ec = ExperimentController(exp_id = "test-ns3-csma-ping")
132         
133         node = ec.register_resource("LinuxNode")
134         ec.set(node, "hostname", self.fedora_host)
135         ec.set(node, "username", self.fedora_user)
136         ec.set(node, "identity", self.fedora_identity)
137         ec.set(node, "cleanProcesses", True)
138         #ec.set(node, "cleanHome", True)
139
140         simu = ec.register_resource("LinuxNS3Simulation")
141         ec.register_connection(simu, node)
142
143         nsnode1 = add_ns3_node(ec, simu)
144         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
145
146         nsnode2 = add_ns3_node(ec, simu)
147         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
148
149         # Create channel
150         chan = ec.register_resource("ns3::CsmaChannel")
151         ec.set(chan, "Delay", "0s")
152         ec.register_connection(chan, dev1)
153         ec.register_connection(chan, dev2)
154
155         ### create pinger
156         ping = ec.register_resource("ns3::V4Ping")
157         ec.set (ping, "Remote", "10.0.0.2")
158         ec.set (ping, "Interval", "1s")
159         ec.set (ping, "Verbose", True)
160         ec.set (ping, "StartTime", "0s")
161         ec.set (ping, "StopTime", "20s")
162         ec.register_connection(ping, nsnode1)
163
164         ec.deploy()
165
166         ec.wait_finished([ping])
167         
168         stdout = ec.trace(simu, "stdout") 
169
170         expected = "20 packets transmitted, 20 received, 0% packet loss"
171         self.assertTrue(stdout.find(expected) > -1)
172
173         ec.shutdown()
174
175     def test_compile_local_source(self):
176         ec = ExperimentController(exp_id = "test-ns3-local-source")
177         
178         node = ec.register_resource("LinuxNode")
179         ec.set(node, "hostname", self.fedora_host)
180         ec.set(node, "username", self.fedora_user)
181         ec.set(node, "identity", self.fedora_identity)
182         ec.set(node, "cleanProcesses", True)
183         #ec.set(node, "cleanHome", True)
184
185         simu = ec.register_resource("LinuxNS3Simulation")
186         sources = os.path.join(os.path.dirname(os.path.realpath(__file__)), 
187                 "ns-3.18-user.tar.gz")
188         ec.set(simu, "sources", sources)
189         ec.register_connection(simu, node)
190
191         nsnode1 = add_ns3_node(ec, simu)
192         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
193
194         nsnode2 = add_ns3_node(ec, simu)
195         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
196
197         # Create channel
198         chan = ec.register_resource("ns3::CsmaChannel")
199         ec.set(chan, "Delay", "0s")
200         ec.register_connection(chan, dev1)
201         ec.register_connection(chan, dev2)
202
203         ### create pinger
204         ping = ec.register_resource("ns3::V4Ping")
205         ec.set (ping, "Remote", "10.0.0.2")
206         ec.set (ping, "Interval", "1s")
207         ec.set (ping, "Verbose", True)
208         ec.set (ping, "StartTime", "0s")
209         ec.set (ping, "StopTime", "20s")
210         ec.register_connection(ping, nsnode1)
211
212         ec.deploy()
213
214         ec.wait_finished([ping])
215         
216         stdout = ec.trace(simu, "stdout") 
217
218         expected = "20 packets transmitted, 20 received, 0% packet loss"
219         self.assertTrue(stdout.find(expected) > -1)
220         
221         ec.shutdown()
222
223     def test_compile_debug_mode(self):
224         ec = ExperimentController(exp_id = "test-ns3-debug-mode")
225         
226         node = ec.register_resource("LinuxNode")
227         ec.set(node, "hostname", self.fedora_host)
228         ec.set(node, "username", self.fedora_user)
229         ec.set(node, "identity", self.fedora_identity)
230         ec.set(node, "cleanProcesses", True)
231         #ec.set(node, "cleanHome", True)
232
233         simu = ec.register_resource("LinuxNS3Simulation")
234         ec.set(simu, "verbose", True)
235         ec.set(simu, "nsLog", "V4Ping:Node")
236         ec.set(simu, "buildMode", "debug")
237         ec.register_connection(simu, node)
238
239         nsnode1 = add_ns3_node(ec, simu)
240         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
241
242         nsnode2 = add_ns3_node(ec, simu)
243         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
244
245         # Create channel
246         chan = ec.register_resource("ns3::CsmaChannel")
247         ec.set(chan, "Delay", "0s")
248         ec.register_connection(chan, dev1)
249         ec.register_connection(chan, dev2)
250
251         ### create pinger
252         ping = ec.register_resource("ns3::V4Ping")
253         ec.set (ping, "Remote", "10.0.0.2")
254         ec.set (ping, "Interval", "1s")
255         ec.set (ping, "Verbose", True)
256         ec.set (ping, "StartTime", "0s")
257         ec.set (ping, "StopTime", "20s")
258         ec.register_connection(ping, nsnode1)
259
260         ec.deploy()
261
262         ec.wait_finished([ping])
263         
264         stdout = ec.trace(simu, "stdout") 
265
266         expected = "20 packets transmitted, 20 received, 0% packet loss"
267         self.assertTrue(stdout.find(expected) > -1)
268         
269         stderr = ec.trace(simu, "stderr")
270         expected = "V4Ping:Read32"
271         self.assertTrue(stderr.find(expected) > -1)
272
273         ec.shutdown()
274
275     def test_real_time(self):
276         ec = ExperimentController(exp_id = "test-ns3-real-time")
277         
278         node = ec.register_resource("LinuxNode")
279         ec.set(node, "hostname", self.fedora_host)
280         ec.set(node, "username", self.fedora_user)
281         ec.set(node, "identity", self.fedora_identity)
282         ec.set(node, "cleanProcesses", True)
283         #ec.set(node, "cleanHome", True)
284
285         simu = ec.register_resource("LinuxNS3Simulation")
286         ec.set(simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl")
287         ec.set(simu, "checksumEnabled", True)
288         ec.set(simu, "verbose", True)
289         ec.register_connection(simu, node)
290
291         nsnode1 = add_ns3_node(ec, simu)
292         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
293
294         nsnode2 = add_ns3_node(ec, simu)
295         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
296
297         # Create channel
298         chan = ec.register_resource("ns3::PointToPointChannel")
299         ec.set(chan, "Delay", "0s")
300         ec.register_connection(chan, dev1)
301         ec.register_connection(chan, dev2)
302
303         ### create pinger
304         ping = ec.register_resource("ns3::V4Ping")
305         ec.set (ping, "Remote", "10.0.0.2")
306         ec.set (ping, "Interval", "1s")
307         ec.set (ping, "Verbose", True)
308         ec.set (ping, "StartTime", "0s")
309         ec.set (ping, "StopTime", "20s")
310         ec.register_connection(ping, nsnode1)
311
312         ec.deploy()
313
314         ec.wait_finished([ping])
315       
316         stdout = ec.trace(simu, "stdout") 
317
318         expected = "20 packets transmitted, 20 received, 0% packet loss"
319         self.assertTrue(stdout.find(expected) > -1)
320
321         rm = ec.get_resource(ping)
322         start_time = rm.start_time
323         stop_time = rm.stop_time
324         delta =  stop_time - start_time
325
326         self.assertTrue(delta.seconds >= 20)
327         self.assertTrue(delta.seconds < 25)
328
329         ec.shutdown()
330
331     def test_dev2p_traces(self):
332         ec = ExperimentController(exp_id = "test-ns3-dev2p-traces")
333         
334         node = ec.register_resource("LinuxNode")
335         ec.set(node, "hostname", self.fedora_host)
336         ec.set(node, "username", self.fedora_user)
337         ec.set(node, "identity", self.fedora_identity)
338         ec.set(node, "cleanProcesses", True)
339         #ec.set(node, "cleanHome", True)
340
341         simu = ec.register_resource("LinuxNS3Simulation")
342         ec.register_connection(simu, node)
343
344         nsnode1 = add_ns3_node(ec, simu)
345         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
346
347         nsnode2 = add_ns3_node(ec, simu)
348         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
349
350         # Create channel
351         chan = ec.register_resource("ns3::PointToPointChannel")
352         ec.set(chan, "Delay", "0s")
353         ec.register_connection(chan, dev1)
354         ec.register_connection(chan, dev2)
355
356         ### create pinger
357         ping = ec.register_resource("ns3::V4Ping")
358         ec.set (ping, "Remote", "10.0.0.2")
359         ec.set (ping, "Interval", "1s")
360         ec.set (ping, "Verbose", True)
361         ec.set (ping, "StartTime", "0s")
362         ec.set (ping, "StopTime", "20s")
363         ec.register_connection(ping, nsnode1)
364
365         # enable traces
366         ec.enable_trace(dev1, "pcap")
367         ec.enable_trace(dev1, "promiscPcap")
368         ec.enable_trace(dev1, "ascii")
369
370         ec.enable_trace(dev2, "pcap")
371         ec.enable_trace(dev2, "promiscPcap")
372         ec.enable_trace(dev2, "ascii")
373
374         ec.deploy()
375
376         ec.wait_finished([ping])
377
378         # Trace verification
379         rm_simu = ec.get_resource(simu)
380
381         # TODO: Fix this in ns-3: pcap traces do not flush until the Simulator 
382         #   process is ended, so we can't get the traces of the 'pcap' and
383         #   'promiscPcap' traces.
384         #
385         #for trace in ["pcap", "promiscPcap", "ascii"]:
386         for trace in ["ascii"]:
387             for guid in [dev1, dev2]:
388                 output = ec.trace(guid, trace)
389
390                 size = ec.trace(guid, trace, attr = TraceAttr.SIZE)
391                 self.assertEquals(size, len(output))
392                 self.assertTrue(size > 100)
393                 
394                 block = ec.trace(guid, trace, attr = TraceAttr.STREAM, block = 5, offset = 1)
395                 self.assertEquals(block, output[5:10])
396
397                 trace_path = ec.trace(guid, trace, attr = TraceAttr.PATH)
398                 rm = ec.get_resource(guid)
399                 path = os.path.join(rm_simu.run_home, rm._trace_filename.get(trace))
400                 self.assertEquals(trace_path, path)
401
402         ec.shutdown()
403
404 if __name__ == '__main__':
405     unittest.main()
406