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