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