7b6c487c2e6e058677adab659eb4c521886e41d1
[nepi.git] / test / resources / ns3 / ns3wrapper.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
21 # Test based on ns-3 csma/examples/csma-ping.cc file
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.resources.ns3.ns3wrapper import NS3Wrapper
33
34 import StringIO
35 import subprocess
36 import sys
37 import time
38 import unittest
39
40 class NS3WrapperTest(unittest.TestCase):
41     def setUp(self):
42         pass
43
44     def test_csma_ping(self):
45         wrapper = NS3Wrapper()
46
47         ### create 4  nodes
48         # NodeContainer c;
49         c = wrapper.create("NodeContainer")
50
51         # c.Create (4);
52         wrapper.invoke(c, "Create", 4)
53
54         ### connect the nodes to a shared channel
55         # CsmaHelper csma;
56         csma = wrapper.create("CsmaHelper")
57
58         # csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
59         dr = wrapper.create("DataRate", 5000000)
60         drv = wrapper.create("DataRateValue", dr)
61         wrapper.invoke(csma, "SetChannelAttribute", "DataRate", drv)
62
63         # csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
64         ms = wrapper.create("MilliSeconds", 2)
65         delay = wrapper.create("TimeValue", ms)
66         wrapper.invoke(csma, "SetChannelAttribute", "Delay", delay)
67
68         # csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
69         encap = wrapper.create("StringValue", "Llc")
70         wrapper.invoke(csma, "SetDeviceAttribute", "EncapsulationMode", encap)
71
72         # NetDeviceContainer devs = csma.Install (c);
73         devs = wrapper.invoke(csma, "Install", c)
74
75         ### add IP stack to all nodes
76         # InternetStackHelper ipStack;
77         ipStack = wrapper.create("InternetStackHelper")
78         
79         # ipStack.Install (c);
80         wrapper.invoke(ipStack, "Install", c)
81
82         ### assign ip addresses
83         #Ipv4AddressHelper ip;
84         ip = wrapper.create("Ipv4AddressHelper")
85
86         # ip.SetBase ("192.168.1.0", "255.255.255.0");
87         ip4 = wrapper.create("Ipv4Address", "192.168.1.0")
88         mask4 = wrapper.create("Ipv4Mask", "255.255.255.0")
89         wrapper.invoke(ip, "SetBase", ip4, mask4)
90
91         # Ipv4InterfaceContainer addresses = ip.Assign (devs);
92         addresses = wrapper.invoke(ip, "Assign", devs)
93
94         ### Create source
95         # Config::SetDefault ("ns3::Ipv4RawSocketImpl::Protocol", StringValue ("2"));
96         proto = wrapper.create("StringValue", "2")
97         wrapper.invoke("singleton::Config", "SetDefault", 
98                 "ns3::Ipv4RawSocketImpl::Protocol", proto)
99
100         # InetSocketAddress dst = InetSocketAddress (addresses.GetAddress (3));
101         addr3 = wrapper.invoke(addresses, "GetAddress", 3)
102         dst = wrapper.create("InetSocketAddress", addr3)
103
104         # OnOffHelper onoff = OnOffHelper ("ns3::Ipv4RawSocketFactory", dst);
105         onoff = wrapper.create("OnOffHelper", "ns3::Ipv4RawSocketFactory", dst)
106
107         # onoff.SetAttribute ("DataRate", DataRateValue (DataRate (15000)));
108         dr2 = wrapper.create("DataRate", 15000)
109         drv2 = wrapper.create("DataRateValue", dr2)
110         wrapper.invoke(onoff, "SetAttribute", "DataRate", drv2)
111
112         # onoff.SetAttribute ("PacketSize", UintegerValue (1200));
113         uiv = wrapper.create("UintegerValue", 1200)
114         wrapper.invoke(onoff, "SetAttribute", "PacketSize", uiv)
115
116         # ApplicationContainer apps = onoff.Install (c.Get (0));
117         n1 = wrapper.invoke(c, "Get", 0)
118         apps = wrapper.invoke(onoff, "Install", n1)
119         
120         # apps.Start (Seconds (1.0));
121         s1 = wrapper.create("Seconds", 1.0)
122         wrapper.invoke(apps, "Start", s1)
123         
124         # apps.Stop (Seconds (10.0));
125         s2 = wrapper.create("Seconds", 10.0)
126         wrapper.invoke(apps, "Stop", s2)
127
128         ### create sink
129         # PacketSinkHelper sink = PacketSinkHelper ("ns3::Ipv4RawSocketFactory", dst);
130         sink = wrapper.create("PacketSinkHelper", "ns3::Ipv4RawSocketFactory", dst)
131         
132         # apps = sink.Install (c.Get (3));
133         n3 = wrapper.invoke(c, "Get", 3)
134         apps = wrapper.invoke (sink, "Install", n3)
135         
136         # apps.Start (Seconds (0.0));
137         s3 = wrapper.create ("Seconds", 0.0)
138         wrapper.invoke (apps, "Start", s3)
139         
140         # apps.Stop (Seconds (11.0));
141         s4 = wrapper.create ("Seconds", 11.0)
142         wrapper.invoke (apps, "Stop", s4)
143
144         ### create pinger
145         #V4PingHelper ping = V4PingHelper (addresses.GetAddress (2));
146         addr2 = wrapper.invoke(addresses, "GetAddress", 2)
147         ping = wrapper.create("V4PingHelper", addr2)
148         
149         #NodeContainer pingers;
150         pingers = wrapper.create("NodeContainer")
151         
152         #pingers.Add (c.Get (0));
153         n0 = wrapper.invoke(c, "Get", 0)
154         wrapper.invoke(pingers, "Add", n0)
155         
156         #pingers.Add (c.Get (1));
157         n1 = wrapper.invoke(c, "Get", 1)
158         wrapper.invoke(pingers, "Add", n1)
159         
160         #pingers.Add (c.Get (3));
161         n3 = wrapper.invoke(c, "Get", 3)
162         wrapper.invoke(pingers, "Add", n3)
163         
164         #apps = ping.Install (pingers);
165         apps = wrapper.invoke(ping, "Install", pingers)
166         
167         #apps.Start (Seconds (2.0));
168         s5 = wrapper.create ("Seconds", 2.0)
169         wrapper.invoke (apps, "Start", s5)
170         
171         #apps.Stop (Seconds (5.0));
172         s6 = wrapper.create ("Seconds", 5.0)
173         wrapper.invoke (apps, "Stop", s6)
174
175         ### configure tracing
176         #csma.EnablePcapAll ("csma-ping", false);
177         wrapper.invoke(csma, "EnablePcapAll", "/tmp/csma-ping-pcap", False)
178  
179         #csma.EnableAsciiAll ("csma-ping", false);
180         wrapper.invoke(csma, "EnableAsciiAll", "/tmp/csma-ping-ascii")
181  
182         def SinkRx(packet, address):
183             print packet
184
185         def PingRtt(context, rtt):
186             print context, rtt
187       
188         # XXX: No biding for MakeCallback
189         #Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx", 
190         # MakeCallback (&SinkRx));
191         #cb = wrapper.create("MakeCallback", SinkRx)
192         #wrapper.invoke("singleton::Config", "ConnectWithoutContext", 
193         #        "/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx", cb)
194
195         # Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", 
196         # MakeCallback (&PingRtt));
197         #cb2 = wrapper.create("MakeCallback", PingRtt)
198         #wrapper.invoke("singleton::Config", "ConnectWithoutContext", 
199         #        "/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt", 
200         #        cb2)
201
202         # Packet::EnablePrinting ();
203         wrapper.invoke("singleton::Packet", "EnablePrinting")
204
205         ### run Simulation
206         # Simulator::Run ();
207         wrapper.invoke("singleton::Simulator", "Run")
208
209         # Simulator::Destroy ();
210         wrapper.invoke("singleton::Simulator", "Destroy")
211
212         p = subprocess.Popen("ls /tmp/csma-ping-* | wc -w", stdout = subprocess.PIPE, 
213                 stderr = subprocess.PIPE, shell = True)
214         (out, err) = p.communicate()
215
216         self.assertEquals(int(out), 8)
217
218         p = subprocess.Popen("rm /tmp/csma-ping-*",  shell = True)
219         p.communicate()
220
221     def test_start(self):
222         # Instantiate ns-3
223         wrapper = NS3Wrapper()
224
225         ### create 2  nodes
226         c = wrapper.create("NodeContainer")
227
228         # c.Create (2);
229         wrapper.invoke(c, "Create", 2)
230
231         ### connect the nodes to a shared channel
232         # CsmaHelper csma;
233         csma = wrapper.create("CsmaHelper")
234
235         # csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
236         dr = wrapper.create("DataRate", 5000000)
237         drv = wrapper.create("DataRateValue", dr)
238         wrapper.invoke(csma, "SetChannelAttribute", "DataRate", drv)
239
240         # csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
241         ms = wrapper.create("MilliSeconds", 2)
242         delay = wrapper.create("TimeValue", ms)
243         wrapper.invoke(csma, "SetChannelAttribute", "Delay", delay)
244
245         # NetDeviceContainer devs = csma.Install (c);
246         devs = wrapper.invoke(csma, "Install", c)
247
248         ### add IP stack to all nodes
249         # InternetStackHelper ipStack;
250         ipStack = wrapper.create("InternetStackHelper")
251         
252         # ipStack.Install (c);
253         wrapper.invoke(ipStack, "Install", c)
254
255         ### assign ip addresses
256         #Ipv4AddressHelper ip;
257         ip = wrapper.create("Ipv4AddressHelper")
258
259         # ip.SetBase ("192.168.1.0", "255.255.255.0");
260         ip4 = wrapper.create("Ipv4Address", "192.168.1.0")
261         mask4 = wrapper.create("Ipv4Mask", "255.255.255.0")
262         wrapper.invoke(ip, "SetBase", ip4, mask4)
263
264         # Ipv4InterfaceContainer addresses = ip.Assign (devs);
265         addresses = wrapper.invoke(ip, "Assign", devs)
266
267         ### create pinger
268         #V4PingHelper ping = V4PingHelper (addresses.GetAddress (1));
269         addr1 = wrapper.invoke(addresses, "GetAddress", 1)
270         ping = wrapper.create("V4PingHelper", addr1)
271         btrue = wrapper.create("BooleanValue", True)
272         wrapper.invoke(ping, "SetAttribute", "Verbose", btrue)
273         
274         #apps = ping.Install (pingers);
275         n0 = wrapper.invoke(c, "Get", 0)
276         apps = wrapper.invoke(ping, "Install", n0)
277         
278         #apps.Start (Seconds (0.0));
279         s = wrapper.create ("Seconds", 0.0)
280         wrapper.invoke (apps, "Start", s)
281         
282         #apps.Stop (Seconds (5.0));
283         s = wrapper.create ("Seconds", 5.0)
284         wrapper.invoke (apps, "Stop", s)
285
286         ### run Simulation
287         # Simulator::Stop (6.0);
288         wrapper.stop(time = "6s")
289
290         # Simulator::Run ();
291         wrapper.start()
292
293         # wait until simulation is over
294         wrapper.shutdown()
295
296         # TODO: Add assertions !!
297
298     def test_runtime_attr_modify(self):
299         wrapper = NS3Wrapper()
300        
301         # Define a real time simulation 
302         stype = wrapper.create("StringValue", "ns3::RealtimeSimulatorImpl")
303         wrapper.invoke("singleton::GlobalValue", "Bind", "SimulatorImplementationType", stype)
304         btrue = wrapper.create("BooleanValue", True)
305         wrapper.invoke("singleton::GlobalValue", "Bind", "ChecksumEnabled", btrue)
306
307         ### create 2  nodes
308         ## NODE 1
309         n1 = wrapper.create("Node")
310
311         ## Install internet stack
312         ipv41 = wrapper.create("Ipv4L3Protocol")
313         wrapper.invoke(n1, "AggregateObject", ipv41)
314
315         arp1 = wrapper.create("ArpL3Protocol")
316         wrapper.invoke(n1, "AggregateObject", arp1)
317         
318         icmp1 = wrapper.create("Icmpv4L4Protocol")
319         wrapper.invoke(n1, "AggregateObject", icmp1)
320
321         ## Add IPv4 routing
322         lr1 = wrapper.create("Ipv4ListRouting")
323         wrapper.invoke(ipv41, "SetRoutingProtocol", lr1)
324         sr1 = wrapper.create("Ipv4StaticRouting")
325         wrapper.invoke(lr1, "AddRoutingProtocol", sr1, 1)
326
327         ## NODE 2
328         n2 = wrapper.create("Node")
329
330         ## Install internet stack
331         ipv42 = wrapper.create("Ipv4L3Protocol")
332         wrapper.invoke(n2, "AggregateObject", ipv42)
333
334         arp2 = wrapper.create("ArpL3Protocol")
335         wrapper.invoke(n2, "AggregateObject", arp2)
336         
337         icmp2 = wrapper.create("Icmpv4L4Protocol")
338         wrapper.invoke(n2, "AggregateObject", icmp2)
339
340         ## Add IPv4 routing
341         lr2 = wrapper.create("Ipv4ListRouting")
342         wrapper.invoke(ipv42, "SetRoutingProtocol", lr2)
343         sr2 = wrapper.create("Ipv4StaticRouting")
344         wrapper.invoke(lr2, "AddRoutingProtocol", sr2, 1)
345
346         ##### Create p2p device and enable ascii tracing
347
348         p2pHelper = wrapper.create("PointToPointHelper")
349         asciiHelper = wrapper.create("AsciiTraceHelper")
350
351         # Iface for node1
352         p1 = wrapper.create("PointToPointNetDevice")
353         wrapper.invoke(n1, "AddDevice", p1)
354         q1 = wrapper.create("DropTailQueue")
355         wrapper.invoke(p1, "SetQueue", q1)
356       
357         # Add IPv4 address
358         ifindex1 = wrapper.invoke(ipv41, "AddInterface", p1)
359         mask1 = wrapper.create("Ipv4Mask", "/30")
360         addr1 = wrapper.create("Ipv4Address", "10.0.0.1")
361         inaddr1 = wrapper.create("Ipv4InterfaceAddress", addr1, mask1)
362         wrapper.invoke(ipv41, "AddAddress", ifindex1, inaddr1)
363         wrapper.invoke(ipv41, "SetMetric", ifindex1, 1)
364         wrapper.invoke(ipv41, "SetUp", ifindex1)
365
366         # Enable collection of Ascii format to a specific file
367         filepath1 = "/tmp/trace-p2p-1.tr"
368         stream1 = wrapper.invoke(asciiHelper, "CreateFileStream", filepath1)
369         wrapper.invoke(p2pHelper, "EnableAscii", stream1, p1)
370        
371         # Iface for node2
372         p2 = wrapper.create("PointToPointNetDevice")
373         wrapper.invoke(n2, "AddDevice", p2)
374         q2 = wrapper.create("DropTailQueue")
375         wrapper.invoke(p2, "SetQueue", q2)
376
377         # Add IPv4 address
378         ifindex2 = wrapper.invoke(ipv42, "AddInterface", p2)
379         mask2 = wrapper.create("Ipv4Mask", "/30")
380         addr2 = wrapper.create("Ipv4Address", "10.0.0.2")
381         inaddr2 = wrapper.create("Ipv4InterfaceAddress", addr2, mask2)
382         wrapper.invoke(ipv42, "AddAddress", ifindex2, inaddr2)
383         wrapper.invoke(ipv42, "SetMetric", ifindex2, 1)
384         wrapper.invoke(ipv42, "SetUp", ifindex2)
385
386         # Enable collection of Ascii format to a specific file
387         filepath2 = "/tmp/trace-p2p-2.tr"
388         stream2 = wrapper.invoke(asciiHelper, "CreateFileStream", filepath2)
389         wrapper.invoke(p2pHelper, "EnableAscii", stream2, p2)
390
391         # Create channel
392         chan = wrapper.create("PointToPointChannel")
393         wrapper.set(chan, "Delay", "0s")
394         wrapper.invoke(p1, "Attach", chan)
395         wrapper.invoke(p2, "Attach", chan)
396
397         ### create pinger
398         ping = wrapper.create("V4Ping")
399         wrapper.invoke(n1, "AddApplication", ping)
400         wrapper.set (ping, "Remote", "10.0.0.2")
401         wrapper.set (ping, "Interval", "1s")
402         wrapper.set (ping, "Verbose", True)
403         wrapper.set (ping, "StartTime", "0s")
404         wrapper.set (ping, "StopTime", "20s")
405
406         ### run Simulation
407         wrapper.stop(time = "21s")
408         wrapper.start()
409
410         time.sleep(1)
411
412         wrapper.set(chan, "Delay", "5s")
413
414         time.sleep(5)
415
416         wrapper.set(chan, "Delay", "0s")
417
418         # wait until simulation is over
419         wrapper.shutdown()
420
421         p = subprocess.Popen("rm /tmp/trace-p2p-*",  shell = True)
422         p.communicate()
423         
424         # TODO: Add assertions !!
425
426 if __name__ == '__main__':
427     unittest.main()
428