Adding trace support for ns3 RMs
[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 class LinuxNS3ClientTest(unittest.TestCase):
66     def setUp(self):
67         self.fedora_host = "nepi2.pl.sophia.inria.fr"
68         self.fedora_user = "inria_test"
69
70     def test_simple_ping(self):
71         ec = ExperimentController(exp_id = "test-ns3-ping")
72         
73         node = ec.register_resource("LinuxNode")
74         ec.set(node, "hostname", self.fedora_host)
75         ec.set(node, "username", self.fedora_user)
76         ec.set(node, "cleanProcesses", True)
77         #ec.set(node, "cleanHome", True)
78
79         simu = ec.register_resource("LinuxNS3Simulation")
80         ec.set(simu, "verbose", True)
81         ec.set(simu, "nsLog", "V4Ping:Node")
82         ec.register_connection(simu, node)
83
84         nsnode1 = add_ns3_node(ec, simu)
85         p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
86
87         nsnode2 = add_ns3_node(ec, simu)
88         p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
89
90         # Create channel
91         chan = ec.register_resource("ns3::PointToPointChannel")
92         ec.set(chan, "Delay", "0s")
93         ec.register_connection(chan, p1)
94         ec.register_connection(chan, p2)
95
96         ### create pinger
97         ping = ec.register_resource("ns3::V4Ping")
98         ec.set (ping, "Remote", "10.0.0.2")
99         ec.set (ping, "Interval", "1s")
100         ec.set (ping, "Verbose", True)
101         ec.set (ping, "StartTime", "0s")
102         ec.set (ping, "StopTime", "20s")
103         ec.register_connection(ping, nsnode1)
104
105         ec.deploy()
106
107         ec.wait_finished([ping])
108         
109         stdout = ec.trace(simu, "stdout") 
110
111         expected = "20 packets transmitted, 20 received, 0% packet loss"
112         self.assertTrue(stdout.find(expected) > -1)
113
114         ec.shutdown()
115
116     def test_real_time(self):
117         ec = ExperimentController(exp_id = "test-ns3-real-time")
118         
119         node = ec.register_resource("LinuxNode")
120         ec.set(node, "hostname", self.fedora_host)
121         ec.set(node, "username", self.fedora_user)
122         ec.set(node, "cleanProcesses", True)
123         #ec.set(node, "cleanHome", True)
124
125         simu = ec.register_resource("LinuxNS3Simulation")
126         ec.set(simu, "verbose", True)
127         ec.set(simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl")
128         ec.set(simu, "checksumEnabled", True)
129         ec.register_connection(simu, node)
130
131         nsnode1 = add_ns3_node(ec, simu)
132         p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
133
134         nsnode2 = add_ns3_node(ec, simu)
135         p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
136
137         # Create channel
138         chan = ec.register_resource("ns3::PointToPointChannel")
139         ec.set(chan, "Delay", "0s")
140         ec.register_connection(chan, p1)
141         ec.register_connection(chan, p2)
142
143         ### create pinger
144         ping = ec.register_resource("ns3::V4Ping")
145         ec.set (ping, "Remote", "10.0.0.2")
146         ec.set (ping, "Interval", "1s")
147         ec.set (ping, "Verbose", True)
148         ec.set (ping, "StartTime", "0s")
149         ec.set (ping, "StopTime", "20s")
150         ec.register_connection(ping, nsnode1)
151
152         ec.deploy()
153
154         ec.wait_finished([ping])
155        
156         stdout = ec.trace(simu, "stdout") 
157
158         expected = "20 packets transmitted, 20 received, 0% packet loss"
159         self.assertTrue(stdout.find(expected) > -1)
160
161         rm = ec.get_resource(ping)
162         start_time = rm.start_time
163         stop_time = rm.stop_time
164         delta =  stop_time - start_time
165
166         self.assertTrue(delta.seconds >= 20)
167         self.assertTrue(delta.seconds < 25)
168
169         ec.shutdown()
170
171     def test_p2p_traces(self):
172         ec = ExperimentController(exp_id = "test-ns3-p2p-traces")
173         
174         node = ec.register_resource("LinuxNode")
175         ec.set(node, "hostname", self.fedora_host)
176         ec.set(node, "username", self.fedora_user)
177         ec.set(node, "cleanProcesses", True)
178         #ec.set(node, "cleanHome", True)
179
180         simu = ec.register_resource("LinuxNS3Simulation")
181         ec.set(simu, "verbose", True)
182         ec.set(simu, "nsLog", "V4Ping:Node")
183         ec.register_connection(simu, node)
184
185         nsnode1 = add_ns3_node(ec, simu)
186         p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
187
188         nsnode2 = add_ns3_node(ec, simu)
189         p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
190
191         # Create channel
192         chan = ec.register_resource("ns3::PointToPointChannel")
193         ec.set(chan, "Delay", "0s")
194         ec.register_connection(chan, p1)
195         ec.register_connection(chan, p2)
196
197         ### create pinger
198         ping = ec.register_resource("ns3::V4Ping")
199         ec.set (ping, "Remote", "10.0.0.2")
200         ec.set (ping, "Interval", "1s")
201         ec.set (ping, "Verbose", True)
202         ec.set (ping, "StartTime", "0s")
203         ec.set (ping, "StopTime", "20s")
204         ec.register_connection(ping, nsnode1)
205
206         # enable traces
207         ec.enable_trace(p1, "pcap")
208         ec.enable_trace(p1, "promiscPcap")
209         ec.enable_trace(p1, "ascii")
210
211         ec.enable_trace(p2, "pcap")
212         ec.enable_trace(p2, "promiscPcap")
213         ec.enable_trace(p2, "ascii")
214
215         ec.deploy()
216
217         ec.wait_finished([ping])
218
219         # Trace verification
220         rm_simu = ec.get_resource(simu)
221
222         # TODO: Fix this in ns-3: pcap traces do not flush until the Simulator 
223         #   process is ended, so we can't get the traces of the 'pcap' and
224         #   'promiscPcap' traces.
225         #
226         #for trace in ["pcap", "promiscPcap", "ascii"]:
227         for trace in ["ascii"]:
228             for guid in [p1, p2]:
229                 output = ec.trace(guid, trace)
230
231                 size = ec.trace(guid, trace, attr = TraceAttr.SIZE)
232                 self.assertEquals(size, len(output))
233                 self.assertTrue(size > 100)
234                 
235                 block = ec.trace(guid, trace, attr = TraceAttr.STREAM, block = 5, offset = 1)
236                 self.assertEquals(block, output[5:10])
237
238                 trace_path = ec.trace(guid, trace, attr = TraceAttr.PATH)
239                 rm = ec.get_resource(guid)
240                 path = os.path.join(rm_simu.run_home, rm._trace_filename.get(trace))
241                 self.assertEquals(trace_path, path)
242
243         ec.shutdown()
244
245 if __name__ == '__main__':
246     unittest.main()
247