a2c7bb21e61d9dd0560471d15dd7e23c6a8aec3c
[nepi.git] / examples / ccn_emu_live / dce_4_nodes_linear.py
1 #!/usr/bin/env python\r
2 #\r
3 #    NEPI, a framework to manage network experiments\r
4 #    Copyright (C) 2013 INRIA\r
5 #\r
6 #    This program is free software: you can redistribute it and/or modify\r
7 #    it under the terms of the GNU General Public License version 2 as\r
8 #    published by the Free Software Foundation;\r
9 #\r
10 #    This program is distributed in the hope that it will be useful,\r
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 #    GNU General Public License for more details.\r
14 #\r
15 #    You should have received a copy of the GNU General Public License\r
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
17 #\r
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>\r
19 \r
20 \r
21 from nepi.execution.ec import ExperimentController \r
22 from nepi.execution.runner import ExperimentRunner\r
23 from nepi.util.netgraph import TopologyType\r
24 import nepi.data.processing.ccn.parser as ccn_parser\r
25 \r
26 import networkx\r
27 import socket\r
28 import os\r
29 import numpy\r
30 from scipy import stats\r
31 from matplotlib import pyplot\r
32 import math\r
33 import random\r
34 \r
35 def avg_interest_rtt(ec, run):\r
36     logs_dir = ec.run_dir\r
37     \r
38     # Parse downloaded CCND logs\r
39     (graph,\r
40       content_names,\r
41       interest_expiry_count,\r
42       interest_dupnonce_count,\r
43       interest_count,\r
44       content_count) = ccn_parser.process_content_history_logs(\r
45         logs_dir, ec.netgraph.topology)\r
46 \r
47     # statistics on RTT\r
48     rtts = [content_names[content_name]["rtt"] \\r
49             for content_name in content_names]
50 \r
51     # sample mean and standard deviation\r
52     sample = numpy.array(rtts)\r
53     n, min_max, mean, var, skew, kurt = stats.describe(sample)\r
54     std = math.sqrt(var)\r
55     ci = stats.t.interval(0.95, n-1, loc = mean, \r
56             scale = std/math.sqrt(n))\r
57 \r
58     global metrics\r
59     metrics.append((mean, ci[0], ci[1]))\r
60     \r
61     return mean\r
62 \r
63 def normal_law(ec, run, sample):\r
64     x = numpy.array(sample)\r
65     n = len(sample)\r
66     std = x.std()\r
67     se = std / math.sqrt(n)\r
68     m = x.mean()\r
69     se95 = se * 2\r
70     \r
71     return m * 0.05 >= se95\r
72 \r
73 def post_process(ec, runs):\r
74     global metrics\r
75     \r
76     # plot convergence graph\r
77     y = numpy.array([float(m[0]) for m in metrics])\r
78     low = numpy.array([float(m[1]) for m in metrics])\r
79     high = numpy.array([float(m[2]) for m in metrics])\r
80     error = [y - low, high - y]\r
81     x = range(1,runs + 1)\r
82 \r
83     # plot average RTT and confidence interval for each iteration\r
84     pyplot.errorbar(x, y, yerr = error, fmt='o')\r
85     pyplot.plot(x, y, 'r-')\r
86     pyplot.xlim([0.5, runs + 0.5])\r
87     pyplot.xticks(numpy.arange(1, len(y)+1, 1))\r
88     pyplot.xlabel('Iteration')\r
89     pyplot.ylabel('Average RTT')\r
90     pyplot.grid()\r
91     pyplot.savefig("plot.png")\r
92     pyplot.show()\r
93 \r
94 content_name = "ccnx:/test/bunny.ts"\r
95 \r
96 STOP_TIME = "5000s"\r
97 \r
98 repofile = os.path.join(\r
99         os.path.dirname(os.path.realpath(__file__)), \r
100         "repoFile1.0.8.2")\r
101 \r
102 def get_simulator(ec):\r
103     simulator = ec.filter_resources("linux::ns3::Simulation")\r
104 \r
105     if not simulator:\r
106         node = ec.register_resource("linux::Node")\r
107         ec.set(node, "hostname", "localhost")\r
108 \r
109         simu = ec.register_resource("linux::ns3::Simulation")\r
110         ec.register_connection(simu, node)\r
111         return simu\r
112 \r
113     return simulator[0]\r
114 \r
115 def add_collector(ec, trace_name, subdir, newname = None):\r
116     collector = ec.register_resource("Collector")\r
117     ec.set(collector, "traceName", trace_name)\r
118     ec.set(collector, "subDir", subdir)\r
119     if newname:\r
120         ec.set(collector, "rename", newname)\r
121 \r
122     return collector\r
123 \r
124 def add_dce_host(ec, nid):\r
125     simu = get_simulator(ec)\r
126     \r
127     host = ec.register_resource("ns3::Node")\r
128     ec.set(host, "enableStack", True)\r
129     ec.register_connection(host, simu)\r
130 \r
131     # Annotate the graph\r
132     ec.netgraph.annotate_node(nid, "host", host)\r
133     \r
134 def add_dce_ccnd(ec, nid):\r
135     # Retrieve annotation from netgraph\r
136     host = ec.netgraph.node_annotation(nid, "host")\r
137     \r
138     # Add dce ccnd to the dce node\r
139     ccnd = ec.register_resource("linux::ns3::dce::CCND")\r
140     ec.set (ccnd, "stackSize", 1<<20)\r
141     ec.set (ccnd, "debug", 7)\r
142     ec.set (ccnd, "capacity", 50000)\r
143     ec.set (ccnd, "StartTime", "1s")\r
144     ec.set (ccnd, "StopTime", STOP_TIME)\r
145     ec.register_connection(ccnd, host)\r
146 \r
147     # Collector to retrieve ccnd log\r
148     collector = add_collector(ec, "stderr", str(nid), "log")\r
149     ec.register_connection(collector, ccnd)\r
150 \r
151     # Annotate the graph\r
152     ec.netgraph.annotate_node(nid, "ccnd", ccnd)\r
153 \r
154 def add_dce_ccnr(ec, nid):\r
155     # Retrieve annotation from netgraph\r
156     host = ec.netgraph.node_annotation(nid, "host")\r
157     \r
158     # Add a CCN content repository to the dce node\r
159     ccnr = ec.register_resource("linux::ns3::dce::CCNR")\r
160     ec.set (ccnr, "repoFile1", repofile) \r
161     ec.set (ccnr, "stackSize", 1<<20)\r
162     ec.set (ccnr, "StartTime", "2s")\r
163     ec.set (ccnr, "StopTime", STOP_TIME)\r
164     ec.register_connection(ccnr, host)\r
165 \r
166 def add_dce_ccncat(ec, nid):\r
167     # Retrieve annotation from netgraph\r
168     host = ec.netgraph.node_annotation(nid, "host")\r
169    \r
170     # Add a ccncat application to the dce host\r
171     ccncat = ec.register_resource("linux::ns3::dce::CCNCat")\r
172     ec.set (ccncat, "contentName", content_name)\r
173     ec.set (ccncat, "stackSize", 1<<20)\r
174     ec.set (ccncat, "StartTime", "8s")\r
175     ec.set (ccncat, "StopTime", STOP_TIME)\r
176     ec.register_connection(ccncat, host)\r
177 \r
178 def add_dce_fib_entry(ec, nid1, nid2):\r
179     # Retrieve annotations from netgraph\r
180     host1 = ec.netgraph.node_annotation(nid1, "host")\r
181     net = ec.netgraph.edge_net_annotation(nid1, nid2)\r
182     ip2 = net[nid2]\r
183 \r
184     # Add FIB entry between peer hosts\r
185     ccndc = ec.register_resource("linux::ns3::dce::FIBEntry")\r
186     ec.set (ccndc, "protocol", "udp") \r
187     ec.set (ccndc, "uri", "ccnx:/") \r
188     ec.set (ccndc, "host", ip2)\r
189     ec.set (ccndc, "stackSize", 1<<20)\r
190     ec.set (ccndc, "StartTime", "2s")\r
191     ec.set (ccndc, "StopTime", STOP_TIME)\r
192     ec.register_connection(ccndc, host1)\r
193 \r
194 def add_dce_net_iface(ec, nid1, nid2):\r
195     # Retrieve annotations from netgraph\r
196     host = ec.netgraph.node_annotation(nid1, "host")\r
197     net = ec.netgraph.edge_net_annotation(nid1, nid2)\r
198     ip1 = net[nid1]\r
199     prefix = net["prefix"]\r
200 \r
201     dev = ec.register_resource("ns3::PointToPointNetDevice")\r
202     ec.set(dev,"DataRate", "5Mbps")\r
203     ec.set(dev, "ip", ip1)\r
204     ec.set(dev, "prefix", prefix)\r
205     ec.register_connection(host, dev)\r
206 \r
207     queue = ec.register_resource("ns3::DropTailQueue")\r
208     ec.register_connection(dev, queue)\r
209 \r
210     return dev\r
211 \r
212 def add_edge(ec, nid1, nid2):\r
213     ### Add network interfaces to hosts\r
214     p2p1 = add_dce_net_iface(ec, nid1, nid2)\r
215     p2p2 = add_dce_net_iface(ec, nid2, nid1)\r
216 \r
217     # Create point to point link between interfaces\r
218     chan = ec.register_resource("ns3::PointToPointChannel")\r
219     ec.set(chan, "Delay", "0ms")\r
220 \r
221     ec.register_connection(chan, p2p1)\r
222     ec.register_connection(chan, p2p2)\r
223 \r
224     #### Add routing between CCN nodes\r
225     add_dce_fib_entry(ec, nid1, nid2)\r
226     add_dce_fib_entry(ec, nid2, nid1)\r
227 \r
228 def add_node(ec, nid):\r
229     ### Add CCN nodes (ec.netgraph holds the topology graph)\r
230     add_dce_host(ec, nid)\r
231     add_dce_ccnd(ec, nid)\r
232         \r
233     if nid == ec.netgraph.targets()[0]:\r
234         add_dce_ccnr(ec, nid)\r
235 \r
236     if nid == ec.netgraph.sources()[0]:\r
237         add_dce_ccncat(ec, nid)\r
238 \r
239 def wait_guids(ec):\r
240     return ec.filter_resources("linux::ns3::dce::CCNCat")\r
241 \r
242 if __name__ == '__main__':\r
243 \r
244     metrics = []\r
245 \r
246     # topology translation to NEPI model\r
247     ec = ExperimentController("dce_4n_linear",\r
248         topo_type = TopologyType.LINEAR, \r
249         node_count = 4,\r
250         assign_st = True,\r
251         assign_ips = True,\r
252         add_node_callback = add_node,\r
253         add_edge_callback = add_edge)\r
254 \r
255     #### Run experiment until metric convergence\r
256     rnr = ExperimentRunner()\r
257     runs = rnr.run(ec,\r
258             min_runs = 10,\r
259             max_runs = 100, \r
260             compute_metric_callback = avg_interest_rtt,\r
261             evaluate_convergence_callback = normal_law,\r
262             wait_guids = wait_guids(ec))\r
263    \r
264     ### post processing\r
265     post_process(ec, runs)\r
266 \r
267 \r