#124 - Allow the ns-3 sources to be built in debug mode
[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 = "peeramide.irisa.fr"
80         self.fedora_user = "inria_test"
81         #self.fedora_user = "inria_alina"
82         self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
83
84     def test_simple_p2p_ping(self):
85         ec = ExperimentController(exp_id = "test-ns3-p2p-ping")
86         
87         node = ec.register_resource("LinuxNode")
88         ec.set(node, "hostname", self.fedora_host)
89         ec.set(node, "username", self.fedora_user)
90         ec.set(node, "identity", self.fedora_identity)
91         ec.set(node, "cleanProcesses", True)
92         #ec.set(node, "cleanHome", True)
93
94         simu = ec.register_resource("LinuxNS3Simulation")
95         ec.set(simu, "verbose", True)
96         ec.set(simu, "nsLog", "V4Ping:Node")
97         ec.register_connection(simu, node)
98
99         nsnode1 = add_ns3_node(ec, simu)
100         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
101
102         nsnode2 = add_ns3_node(ec, simu)
103         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
104
105         # Create channel
106         chan = ec.register_resource("ns3::PointToPointChannel")
107         ec.set(chan, "Delay", "0s")
108         ec.register_connection(chan, dev1)
109         ec.register_connection(chan, dev2)
110
111         ### create pinger
112         ping = ec.register_resource("ns3::V4Ping")
113         ec.set (ping, "Remote", "10.0.0.2")
114         ec.set (ping, "Interval", "1s")
115         ec.set (ping, "Verbose", True)
116         ec.set (ping, "StartTime", "0s")
117         ec.set (ping, "StopTime", "20s")
118         ec.register_connection(ping, nsnode1)
119
120         ec.deploy()
121
122         ec.wait_finished([ping])
123         
124         stdout = ec.trace(simu, "stdout") 
125
126         expected = "20 packets transmitted, 20 received, 0% packet loss"
127         self.assertTrue(stdout.find(expected) > -1)
128
129         ec.shutdown()
130
131     def test_simple_cmsa_ping(self):
132         ec = ExperimentController(exp_id = "test-ns3-csma-ping")
133         
134         node = ec.register_resource("LinuxNode")
135         ec.set(node, "hostname", self.fedora_host)
136         ec.set(node, "username", self.fedora_user)
137         ec.set(node, "identity", self.fedora_identity)
138         ec.set(node, "cleanProcesses", True)
139         #ec.set(node, "cleanHome", True)
140
141         simu = ec.register_resource("LinuxNS3Simulation")
142         ec.set(simu, "verbose", True)
143         ec.set(simu, "nsLog", "V4Ping:Node")
144         ec.set(simu, "buildMode", "debug")
145         ec.register_connection(simu, node)
146
147         nsnode1 = add_ns3_node(ec, simu)
148         dev1 = add_csma_device(ec, nsnode1, "10.0.0.1", "30")
149
150         nsnode2 = add_ns3_node(ec, simu)
151         dev2 = add_csma_device(ec, nsnode2, "10.0.0.2", "30")
152
153         # Create channel
154         chan = ec.register_resource("ns3::CsmaChannel")
155         ec.set(chan, "Delay", "0s")
156         ec.register_connection(chan, dev1)
157         ec.register_connection(chan, dev2)
158
159         ### create pinger
160         ping = ec.register_resource("ns3::V4Ping")
161         ec.set (ping, "Remote", "10.0.0.2")
162         ec.set (ping, "Interval", "1s")
163         ec.set (ping, "Verbose", True)
164         ec.set (ping, "StartTime", "0s")
165         ec.set (ping, "StopTime", "20s")
166         ec.register_connection(ping, nsnode1)
167
168         ec.deploy()
169
170         ec.wait_finished([ping])
171         
172         stdout = ec.trace(simu, "stdout") 
173
174         expected = "20 packets transmitted, 20 received, 0% packet loss"
175         self.assertTrue(stdout.find(expected) > -1)
176
177         ec.shutdown()
178
179     def test_real_time(self):
180         ec = ExperimentController(exp_id = "test-ns3-real-time")
181         
182         node = ec.register_resource("LinuxNode")
183         ec.set(node, "hostname", self.fedora_host)
184         ec.set(node, "username", self.fedora_user)
185         ec.set(node, "identity", self.fedora_identity)
186         ec.set(node, "cleanProcesses", True)
187         #ec.set(node, "cleanHome", True)
188
189         simu = ec.register_resource("LinuxNS3Simulation")
190         ec.set(simu, "verbose", True)
191         ec.set(simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl")
192         ec.set(simu, "checksumEnabled", True)
193         ec.register_connection(simu, node)
194
195         nsnode1 = add_ns3_node(ec, simu)
196         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
197
198         nsnode2 = add_ns3_node(ec, simu)
199         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
200
201         # Create channel
202         chan = ec.register_resource("ns3::PointToPointChannel")
203         ec.set(chan, "Delay", "0s")
204         ec.register_connection(chan, dev1)
205         ec.register_connection(chan, dev2)
206
207         ### create pinger
208         ping = ec.register_resource("ns3::V4Ping")
209         ec.set (ping, "Remote", "10.0.0.2")
210         ec.set (ping, "Interval", "1s")
211         ec.set (ping, "Verbose", True)
212         ec.set (ping, "StartTime", "0s")
213         ec.set (ping, "StopTime", "20s")
214         ec.register_connection(ping, nsnode1)
215
216         ec.deploy()
217
218         ec.wait_finished([ping])
219        
220         stdout = ec.trace(simu, "stdout") 
221
222         expected = "20 packets transmitted, 20 received, 0% packet loss"
223         self.assertTrue(stdout.find(expected) > -1)
224
225         rm = ec.get_resource(ping)
226         start_time = rm.start_time
227         stop_time = rm.stop_time
228         delta =  stop_time - start_time
229
230         self.assertTrue(delta.seconds >= 20)
231         self.assertTrue(delta.seconds < 25)
232
233         ec.shutdown()
234
235     def test_dev2p_traces(self):
236         ec = ExperimentController(exp_id = "test-ns3-dev2p-traces")
237         
238         node = ec.register_resource("LinuxNode")
239         ec.set(node, "hostname", self.fedora_host)
240         ec.set(node, "username", self.fedora_user)
241         ec.set(node, "identity", self.fedora_identity)
242         ec.set(node, "cleanProcesses", True)
243         #ec.set(node, "cleanHome", True)
244
245         simu = ec.register_resource("LinuxNS3Simulation")
246         ec.set(simu, "verbose", True)
247         ec.set(simu, "nsLog", "V4Ping:Node")
248         ec.register_connection(simu, node)
249
250         nsnode1 = add_ns3_node(ec, simu)
251         dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
252
253         nsnode2 = add_ns3_node(ec, simu)
254         dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
255
256         # Create channel
257         chan = ec.register_resource("ns3::PointToPointChannel")
258         ec.set(chan, "Delay", "0s")
259         ec.register_connection(chan, dev1)
260         ec.register_connection(chan, dev2)
261
262         ### create pinger
263         ping = ec.register_resource("ns3::V4Ping")
264         ec.set (ping, "Remote", "10.0.0.2")
265         ec.set (ping, "Interval", "1s")
266         ec.set (ping, "Verbose", True)
267         ec.set (ping, "StartTime", "0s")
268         ec.set (ping, "StopTime", "20s")
269         ec.register_connection(ping, nsnode1)
270
271         # enable traces
272         ec.enable_trace(dev1, "pcap")
273         ec.enable_trace(dev1, "promiscPcap")
274         ec.enable_trace(dev1, "ascii")
275
276         ec.enable_trace(dev2, "pcap")
277         ec.enable_trace(dev2, "promiscPcap")
278         ec.enable_trace(dev2, "ascii")
279
280         ec.deploy()
281
282         ec.wait_finished([ping])
283
284         # Trace verification
285         rm_simu = ec.get_resource(simu)
286
287         # TODO: Fix this in ns-3: pcap traces do not flush until the Simulator 
288         #   process is ended, so we can't get the traces of the 'pcap' and
289         #   'promiscPcap' traces.
290         #
291         #for trace in ["pcap", "promiscPcap", "ascii"]:
292         for trace in ["ascii"]:
293             for guid in [dev1, dev2]:
294                 output = ec.trace(guid, trace)
295
296                 size = ec.trace(guid, trace, attr = TraceAttr.SIZE)
297                 self.assertEquals(size, len(output))
298                 self.assertTrue(size > 100)
299                 
300                 block = ec.trace(guid, trace, attr = TraceAttr.STREAM, block = 5, offset = 1)
301                 self.assertEquals(block, output[5:10])
302
303                 trace_path = ec.trace(guid, trace, attr = TraceAttr.PATH)
304                 rm = ec.get_resource(guid)
305                 path = os.path.join(rm_simu.run_home, rm._trace_filename.get(trace))
306                 self.assertEquals(trace_path, path)
307
308         ec.shutdown()
309
310 if __name__ == '__main__':
311     unittest.main()
312