c10879c512e7c877b68ba29f9808f1494ed2710a
[nepi.git] / test / resources / linux / ns3 / serialization.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 version 2 as
8 #    published by the Free Software Foundation;
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20 from nepi.execution.ec import ExperimentController 
21 from nepi.execution.trace import TraceAttr
22
23 from test_utils import skipIfNotAlive
24
25 import os
26 import shutil
27 import time
28 import tempfile
29 import unittest
30
31 def add_ns3_node(ec, simu):
32     node = ec.register_resource("ns3::Node")
33     ec.register_connection(node, simu)
34
35     ipv4 = ec.register_resource("ns3::Ipv4L3Protocol")
36     ec.register_connection(node, ipv4)
37
38     arp = ec.register_resource("ns3::ArpL3Protocol")
39     ec.register_connection(node, arp)
40     
41     icmp = ec.register_resource("ns3::Icmpv4L4Protocol")
42     ec.register_connection(node, icmp)
43
44     udp = ec.register_resource("ns3::UdpL4Protocol")
45     ec.register_connection(node, udp)
46
47     return node
48
49 def add_point2point_device(ec, node, ip, prefix):
50     dev = ec.register_resource("ns3::PointToPointNetDevice")
51     ec.set(dev, "ip", ip)
52     ec.set(dev, "prefix", prefix)
53     ec.register_connection(node, dev)
54
55     queue = ec.register_resource("ns3::DropTailQueue")
56     ec.register_connection(dev, queue)
57
58     return dev
59
60 def add_csma_device(ec, node, ip, prefix):
61     dev = ec.register_resource("ns3::CsmaNetDevice")
62     ec.set(dev, "ip", ip)
63     ec.set(dev, "prefix", prefix)
64     ec.register_connection(node, dev)
65
66     queue = ec.register_resource("ns3::DropTailQueue")
67     ec.register_connection(dev, queue)
68
69     return dev
70
71 def add_wifi_device(ec, node, ip, prefix, 
72         access_point = False):
73     dev = ec.register_resource("ns3::WifiNetDevice")
74     ec.set(dev, "ip", ip)
75     ec.set(dev, "prefix", prefix)
76     ec.register_connection(node, dev)
77
78     phy = ec.register_resource("ns3::YansWifiPhy")
79     ec.set(phy, "Standard", "WIFI_PHY_STANDARD_80211a")
80     ec.register_connection(dev, phy)
81
82     error = ec.register_resource("ns3::NistErrorRateModel")
83     ec.register_connection(phy, error)
84
85     manager = ec.register_resource("ns3::ArfWifiManager")
86     ec.register_connection(dev, manager)
87
88     if access_point:
89         mac = ec.register_resource("ns3::ApWifiMac")
90     else:
91         mac = ec.register_resource("ns3::StaWifiMac")
92
93     ec.set(mac, "Standard", "WIFI_PHY_STANDARD_80211a")
94     ec.register_connection(dev, mac)
95
96     return dev, phy
97
98 def add_random_mobility(ec, node, x, y, z, speed, bounds_width, 
99         bounds_height):
100     position = "%d:%d:%d" % (x, y, z)
101     bounds = "0|%d|0|%d" % (bounds_width, bounds_height) 
102     speed = "ns3::UniformRandomVariable[Min=%d|Max=%s]" % (speed, speed)
103     pause = "ns3::ConstantRandomVariable[Constant=1.0]"
104     
105     mobility = ec.register_resource("ns3::RandomDirection2dMobilityModel")
106     ec.set(mobility, "Position", position)
107     ec.set(mobility, "Bounds", bounds)
108     ec.set(mobility, "Speed", speed)
109     ec.set(mobility, "Pause",  pause)
110     ec.register_connection(node, mobility)
111     return mobility
112
113 def add_constant_mobility(ec, node, x, y, z):
114     mobility = ec.register_resource("ns3::ConstantPositionMobilityModel") 
115     position = "%d:%d:%d" % (x, y, z)
116     ec.set(mobility, "Position", position)
117     ec.register_connection(node, mobility)
118     return mobility
119
120 def add_wifi_channel(ec):
121     channel = ec.register_resource("ns3::YansWifiChannel")
122     delay = ec.register_resource("ns3::ConstantSpeedPropagationDelayModel")
123     ec.register_connection(channel, delay)
124
125     loss  = ec.register_resource("ns3::LogDistancePropagationLossModel")
126     ec.register_connection(channel, loss)
127
128     return channel
129
130 class LinuxNS3SimulationSerializationTest(unittest.TestCase):
131     def setUp(self):
132         #self.fedora_host = "nepi2.pl.sophia.inria.fr"
133         self.fedora_host = "planetlab1.informatik.uni-erlangen.de"
134         self.fedora_user = "inria_nepi"
135         self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
136
137     @skipIfNotAlive
138     def t_wifi_serialize(self, host, user = None, identity = None):
139         bounds_width = bounds_height = 200
140         x = y = 100
141         speed = 1
142
143         dirpath = tempfile.mkdtemp()
144         
145         ec = ExperimentController(exp_id = "test-ns3-wifi-ping")
146         
147         node = ec.register_resource("linux::Node")
148         if host == "localhost":
149             ec.set(node, "hostname", "localhost")
150         else:
151             ec.set(node, "hostname", host)
152             ec.set(node, "username", user)
153             ec.set(node, "identity", identity)
154
155         ec.set(node, "cleanProcesses", True)
156         #ec.set(node, "cleanHome", True)
157
158         simu = ec.register_resource("linux::ns3::Simulation")
159         ec.set(simu, "verbose", True)
160         ec.register_connection(simu, node)
161
162         nsnode1 = add_ns3_node(ec, simu)
163         dev1, phy1 = add_wifi_device(ec, nsnode1, "10.0.0.1", "24", access_point = True)
164         mobility1 = add_constant_mobility(ec, nsnode1, x, y, 0)
165
166         nsnode2 = add_ns3_node(ec, simu)
167         dev2, phy2 = add_wifi_device(ec, nsnode2, "10.0.0.2", "24", access_point = False)
168         mobility1 = add_constant_mobility(ec, nsnode2, x, y, 0)
169         #mobility2 = add_random_mobility(ec, nsnode2, x, y, 0, speed, bounds_width, bounds_height)
170
171         # Create channel
172         chan = add_wifi_channel(ec)
173         ec.register_connection(chan, phy1)
174         ec.register_connection(chan, phy2)
175
176         ### create pinger
177         ping = ec.register_resource("ns3::V4Ping")
178         ec.set (ping, "Remote", "10.0.0.1")
179         ec.set (ping, "Interval", "1s")
180         ec.set (ping, "Verbose", True)
181         ec.set (ping, "StartTime", "1s")
182         ec.set (ping, "StopTime", "21s")
183         ec.register_connection(ping, nsnode2)
184
185         filepath = ec.save(dirpath)
186         print filepath
187         
188         ec.deploy()
189
190         ec.wait_finished([ping])
191         
192         stdout = ec.trace(simu, "stdout")
193
194         expected = "20 packets transmitted, 20 received, 0% packet loss"
195         self.assertTrue(stdout.find(expected) > -1)
196
197         ec.shutdown()
198
199         # Load serialized experiment
200         ec2 = ExperimentController.load(filepath)
201         
202         ec2.deploy()
203
204         ec2.wait_finished([ping])
205         
206         self.assertEquals(len(ec.resources), len(ec2.resources))
207         
208         stdout = ec2.trace(simu, "stdout")
209  
210         expected = "20 packets transmitted, 20 received, 0% packet loss"
211         self.assertTrue(stdout.find(expected) > -1)
212         
213         ec2.shutdown()
214
215         shutil.rmtree(dirpath)
216
217     @skipIfNotAlive
218     def t_routing_serialize(self, host, user = None, identity = None):
219         """ 
220         network topology:
221                                 n4
222                                 |
223            n1 -- p2p -- n2 -- csma -- n5 -- p2p -- n6
224            |                    | 
225            ping n6              n3
226            
227
228         """
229         dirpath = tempfile.mkdtemp()
230         
231         ec = ExperimentController(exp_id = "test-ns3-routes")
232         
233         node = ec.register_resource("linux::Node")
234         if host == "localhost":
235             ec.set(node, "hostname", host)
236         else:
237             ec.set(node, "hostname", host)
238             ec.set(node, "username", user)
239             ec.set(node, "identity", identity)
240
241         ec.set(node, "cleanProcesses", True)
242         #ec.set(node, "cleanHome", True)
243
244         simu = ec.register_resource("linux::ns3::Simulation")
245         ec.set(simu, "verbose", True)
246         ec.register_connection(simu, node)
247
248         nsnode1 = add_ns3_node(ec, simu)
249         p2p12 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
250
251         nsnode2 = add_ns3_node(ec, simu)
252         p2p21 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
253         csma2 = add_csma_device(ec, nsnode2, "10.0.1.1", "24")
254
255         nsnode3 = add_ns3_node(ec, simu)
256         csma3 = add_csma_device(ec, nsnode3, "10.0.1.2", "24")
257
258         nsnode4 = add_ns3_node(ec, simu)
259         csma4 = add_csma_device(ec, nsnode4, "10.0.1.3", "24")
260
261         nsnode5 = add_ns3_node(ec, simu)
262         p2p56 = add_point2point_device(ec, nsnode5, "10.0.2.1", "30")
263         csma5 = add_csma_device(ec, nsnode5, "10.0.1.4", "24")
264
265         nsnode6 = add_ns3_node(ec, simu)
266         p2p65 = add_point2point_device(ec, nsnode6, "10.0.2.2", "30")
267
268         # P2P chan1
269         p2p_chan1 = ec.register_resource("ns3::PointToPointChannel")
270         ec.set(p2p_chan1, "Delay", "0s")
271         ec.register_connection(p2p_chan1, p2p12)
272         ec.register_connection(p2p_chan1, p2p21)
273
274         # CSMA chan
275         csma_chan = ec.register_resource("ns3::CsmaChannel")
276         ec.set(csma_chan, "Delay", "0s")
277         ec.register_connection(csma_chan, csma2)
278         ec.register_connection(csma_chan, csma3)
279         ec.register_connection(csma_chan, csma4)
280         ec.register_connection(csma_chan, csma5)
281
282         # P2P chan2
283         p2p_chan2 = ec.register_resource("ns3::PointToPointChannel")
284         ec.set(p2p_chan2, "Delay", "0s")
285         ec.register_connection(p2p_chan2, p2p56)
286         ec.register_connection(p2p_chan2, p2p65)
287
288         # Add routes - n1 - n6
289         r1 = ec.register_resource("ns3::Route")
290         ec.set(r1, "network", "10.0.2.0")
291         ec.set(r1, "prefix", "30")
292         ec.set(r1, "nexthop", "10.0.0.2")
293         ec.register_connection(r1, nsnode1)
294
295         # Add routes - n2 - n6
296         r2 = ec.register_resource("ns3::Route")
297         ec.set(r2, "network", "10.0.2.0")
298         ec.set(r2, "prefix", "30")
299         ec.set(r2, "nexthop", "10.0.1.4")
300         ec.register_connection(r2, nsnode2)
301
302         # Add routes - n5 - n1
303         r5 = ec.register_resource("ns3::Route")
304         ec.set(r5, "network", "10.0.0.0")
305         ec.set(r5, "prefix", "30")
306         ec.set(r5, "nexthop", "10.0.1.1")
307         ec.register_connection(r5, nsnode5)
308
309         # Add routes - n6 - n1
310         r6 = ec.register_resource("ns3::Route")
311         ec.set(r6, "network", "10.0.0.0")
312         ec.set(r6, "prefix", "30")
313         ec.set(r6, "nexthop", "10.0.2.1")
314         ec.register_connection(r6, nsnode6)
315
316         ### create pinger
317         ping = ec.register_resource("ns3::V4Ping")
318         ec.set (ping, "Remote", "10.0.2.2")
319         ec.set (ping, "Interval", "1s")
320         ec.set (ping, "Verbose", True)
321         ec.set (ping, "StartTime", "1s")
322         ec.set (ping, "StopTime", "21s")
323         ec.register_connection(ping, nsnode1)
324
325         filepath = ec.save(dirpath)
326         print filepath
327         
328         ec.deploy()
329
330         ec.wait_finished([ping])
331         
332         stdout = ec.trace(simu, "stdout")
333
334         expected = "20 packets transmitted, 20 received, 0% packet loss"
335         self.assertTrue(stdout.find(expected) > -1)
336
337         ec.shutdown()
338
339         # Load serialized experiment
340         ec2 = ExperimentController.load(filepath)
341         
342         ec2.deploy()
343
344         ec2.wait_finished([ping])
345         
346         self.assertEquals(len(ec.resources), len(ec2.resources))
347         
348         stdout = ec2.trace(simu, "stdout")
349  
350         expected = "20 packets transmitted, 20 received, 0% packet loss"
351         self.assertTrue(stdout.find(expected) > -1)
352         
353         ec2.shutdown()
354
355         shutil.rmtree(dirpath)
356
357     @skipIfNotAlive
358     def t_dce_serialize(self, host, user = None, identity = None):
359         dirpath = tempfile.mkdtemp()
360         
361         ec = ExperimentController(exp_id = "test-ns3-dce")
362         
363         node = ec.register_resource("linux::Node")
364         if host == "localhost":
365             ec.set(node, "hostname", host)
366         else:
367             ec.set(node, "hostname", host)
368             ec.set(node, "username", user)
369             ec.set(node, "identity", identity)
370
371         ec.set(node, "cleanProcesses", True)
372         #ec.set(node, "cleanHome", True)
373
374         simu = ec.register_resource("linux::ns3::Simulation")
375         ec.set(simu, "verbose", True)
376         ec.register_connection(simu, node)
377
378         nsnode1 = add_ns3_node(ec, simu)
379         p2p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
380         ec.set(p2p1, "DataRate", "5Mbps")
381
382         nsnode2 = add_ns3_node(ec, simu)
383         p2p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
384         ec.set(p2p2, "DataRate", "5Mbps")
385
386         # Create channel
387         chan = ec.register_resource("ns3::PointToPointChannel")
388         ec.set(chan, "Delay", "2ms")
389
390         ec.register_connection(chan, p2p1)
391         ec.register_connection(chan, p2p2)
392
393         ### create applications
394         udp_perf = ec.register_resource("linux::ns3::dce::Application")
395         ec.set (udp_perf, "binary", "udp-perf")
396         ec.set (udp_perf, "stackSize", 1<<20)
397         ec.set (udp_perf, "arguments", "--duration=10;--nodes=2")
398         ec.set (udp_perf, "StartTime", "1s")
399         ec.set (udp_perf, "StopTime", "20s")
400         ec.register_connection(udp_perf, nsnode1)
401
402         udp_perf_client = ec.register_resource("linux::ns3::dce::Application")
403         ec.set (udp_perf_client, "binary", "udp-perf")
404         ec.set (udp_perf_client, "stackSize", 1<<20)
405         ec.set (udp_perf_client, "arguments", "--client;--nodes=2;--host=10.0.0.1;--duration=10")
406         ec.set (udp_perf_client, "StartTime", "2s")
407         ec.set (udp_perf_client, "StopTime", "20s")
408         ec.register_connection(udp_perf_client, nsnode2)
409
410         filepath = ec.save(dirpath)
411         
412         ec.deploy()
413
414         ec.wait_finished([udp_perf_client])
415
416         # Give time to flush the streams
417         import time
418         time.sleep(5) 
419
420         expected = "udp-perf --duration=10 --nodes=2"
421         cmdline = ec.trace(udp_perf, "cmdline")
422         self.assertTrue(cmdline.find(expected) > -1, cmdline)
423
424         expected = "Start Time: NS3 Time:          1s ("
425         status = ec.trace(udp_perf, "status")
426         self.assertTrue(status.find(expected) > -1, status)
427
428         expected = "received=1500 bytes, 1 reads (@1500 bytes) 1500"
429         stdout = ec.trace(udp_perf, "stdout")
430         self.assertTrue(stdout.find(expected) > -1, stdout)
431
432         ec.shutdown()
433
434         # Load serialized experiment
435         ec2 = ExperimentController.load(filepath)
436         
437         ec2.deploy()
438         ec2.wait_finished([udp_perf_client])
439
440         # Give time to flush the streams
441         time.sleep(5) 
442        
443         self.assertEquals(len(ec.resources), len(ec2.resources))
444  
445         expected = "udp-perf --duration=10 --nodes=2"
446         cmdline = ec2.trace(udp_perf, "cmdline")
447         self.assertTrue(cmdline.find(expected) > -1, cmdline)
448
449         expected = "Start Time: NS3 Time:          1s ("
450         status = ec2.trace(udp_perf, "status")
451         self.assertTrue(status.find(expected) > -1, status)
452
453         expected = "received=1500 bytes, 1 reads (@1500 bytes) 1500"
454         stdout = ec2.trace(udp_perf, "stdout")
455         self.assertTrue(stdout.find(expected) > -1, stdout)
456
457         ec2.shutdown()
458
459         shutil.rmtree(dirpath)
460     
461     def test_wifi_serialize_fedora(self):
462         self.t_wifi_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
463
464     def test_wifi_serialize_local(self):
465         self.t_wifi_serialize("localhost")
466
467     def test_routing_serialize_fedora(self):
468         self.t_routing_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
469
470     def test_routing_serialize_local(self):
471         self.t_routing_serialize("localhost")
472
473     def test_dce_serialize_fedora(self):
474         self.t_dce_serialize(self.fedora_host, self.fedora_user, self.fedora_identity)
475
476     def test_dce_serialize_local(self):
477         self.t_dce_serialize("localhost")
478
479
480 if __name__ == '__main__':
481     unittest.main()
482