examples/ccn_flooding/dce.py with 4 nodes
[nepi.git] / examples / ccn_flooding / dce.py
1 #!/usr/bin/env python
2
3 ###############################################################################
4 #
5 #    NEPI, a framework to manage network experiments
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU General Public License as published by
9 #    the Free Software Foundation, either version 3 of the License, or
10 #    (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
21 #
22 ###############################################################################
23
24 from nepi.execution.ec import ExperimentController 
25 from nepi.execution.runner import ExperimentRunner
26 from nepi.util.netgraph import NetGraph, TopologyType
27 import nepi.data.processing.ccn.parser as ccn_parser
28
29 import networkx
30 import socket
31 import os
32
33 content_name = "ccnx:/test/bunny.ts"
34
35 STOP_TIME = "5000s"
36
37 operating_system = "f14"
38
39 repofile = os.path.join(
40         os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
41
42 def get_simulator(ec):
43     simulator = ec.filter_resources("LinuxNS3Simulation")
44
45     if not simulator:
46         node = ec.register_resource("LinuxNode")
47         ec.set(node, "hostname", "localhost")
48
49         simu = ec.register_resource("LinuxNS3Simulation")
50         ec.register_connection(simu, node)
51         return simu
52
53     return simulator[0]
54
55 def add_collector(ec, trace_name, subdir, newname = None):
56     collector = ec.register_resource("Collector")
57     ec.set(collector, "traceName", trace_name)
58     ec.set(collector, "subDir", subdir)
59     if newname:
60         ec.set(collector, "rename", newname)
61
62     return collector
63
64 def add_dce_host(ec, nid):
65     simu = get_simulator(ec)
66     
67     host = ec.register_resource("ns3::Node")
68     ec.set(host, "enableStack", True)
69     ec.register_connection(host, simu)
70
71     # Annotate the graph
72     ec.netgraph.annotate_node(nid, "host", host)
73     
74 def add_dce_ccnd(ec, nid):
75     # Retrieve annotation from netgraph
76     host = ec.netgraph.node_annotation(nid, "host")
77     
78     # Add dce ccnd to the dce node
79     ccnd = ec.register_resource("ns3::LinuxDceCCND")
80     ec.set (ccnd, "stackSize", 1<<20)
81     ec.set (ccnd, "debug", 7)
82     ec.set (ccnd, "capacity", 50000)
83     ec.set (ccnd, "StartTime", "1s")
84     ec.set (ccnd, "StopTime", STOP_TIME)
85     ec.register_connection(ccnd, host)
86
87     # Collector to retrieve ccnd log
88     collector = add_collector(ec, "stderr", nid, "log")
89     ec.register_connection(collector, ccnd)
90
91     # Annotate the graph
92     ec.netgraph.annotate_node(nid, "ccnd", ccnd)
93
94 def add_dce_ccnr(ec, nid):
95     # Retrieve annotation from netgraph
96     host = ec.netgraph.node_annotation(nid, "host")
97     
98     # Add a CCN content repository to the dce node
99     ccnr = ec.register_resource("ns3::LinuxDceCCNR")
100     ec.set (ccnr, "repoFile1", repofile) 
101     ec.set (ccnr, "stackSize", 1<<20)
102     ec.set (ccnr, "StartTime", "2s")
103     ec.set (ccnr, "StopTime", STOP_TIME)
104     ec.register_connection(ccnr, host)
105
106 def add_dce_ccncat(ec, nid):
107     # Retrieve annotation from netgraph
108     host = ec.netgraph.node_annotation(nid, "host")
109    
110     ccnpeek = ec.register_resource("ns3::LinuxDceCCNPeek")
111     #ec.set (ccnpeek, "contentName", "ccnx:/chunk0")
112     ec.set (ccnpeek, "contentName", content_name)
113     ec.set (ccnpeek, "stackSize", 1<<20)
114     ec.set (ccnpeek, "StartTime", "5s")
115     ec.set (ccnpeek, "StopTime", STOP_TIME)
116     ec.register_connection(ccnpeek, host)
117
118     collector = add_collector(ec, "stdout", nid, "peek")
119     ec.register_connection(collector, ccnpeek)
120
121     # Add a ccncat application to the dce host
122     ccncat = ec.register_resource("ns3::LinuxDceCCNCat")
123     ec.set (ccncat, "contentName", content_name)
124     ec.set (ccncat, "stackSize", 1<<20)
125     ec.set (ccncat, "StartTime", "8s")
126     ec.set (ccncat, "StopTime", STOP_TIME)
127     ec.register_connection(ccncat, host)
128
129 def add_dce_fib_entry(ec, nid1, nid2):
130     # Retrieve annotations from netgraph
131     host1 = ec.netgraph.node_annotation(nid1, "host")
132     net = ec.netgraph.edge_net_annotation(nid1, nid2)
133     ip2 = net[nid2]
134
135     # Add FIB entry between peer hosts
136     ccndc = ec.register_resource("ns3::LinuxDceFIBEntry")
137     ec.set (ccndc, "protocol", "udp") 
138     ec.set (ccndc, "uri", "ccnx:/") 
139     ec.set (ccndc, "host", ip2)
140     ec.set (ccndc, "stackSize", 1<<20)
141     ec.set (ccndc, "StartTime", "2s")
142     ec.set (ccndc, "StopTime", STOP_TIME)
143     ec.register_connection(ccndc, host1)
144
145 def add_dce_net_iface(ec, nid1, nid2):
146     # Retrieve annotations from netgraph
147     host = ec.netgraph.node_annotation(nid1, "host")
148     net = ec.netgraph.edge_net_annotation(nid1, nid2)
149     ip1 = net[nid1]
150     prefix = net["prefix"]
151
152     dev = ec.register_resource("ns3::PointToPointNetDevice")
153     ec.set(dev,"DataRate", "5Mbps")
154     ec.set(dev, "ip", ip1)
155     ec.set(dev, "prefix", prefix)
156     ec.register_connection(host, dev)
157
158     queue = ec.register_resource("ns3::DropTailQueue")
159     ec.register_connection(dev, queue)
160
161     return dev
162
163 def avg_interests(ec, run):
164     ## Process logs
165     logs_dir = ec.run_dir
166
167     (graph,
168         content_names,
169         interest_expiry_count,
170         interest_dupnonce_count,
171         interest_count,
172         content_count) = ccn_parser.process_content_history_logs(
173                 logs_dir, 
174                 ec.netgraph.topology)
175
176     shortest_path = networkx.shortest_path(graph, 
177             source = ec.netgraph.sources()[0], 
178             target = ec.netgraph.targets()[0])
179
180     ### Compute metric: Avg number of Interests seen per content name
181     ###                 normalized by the number of nodes in the shortest path
182     content_name_count = len(content_names.values())
183     nodes_in_shortest_path = len(shortest_path) - 1
184     metric = interest_count / (float(content_name_count) * float(nodes_in_shortest_path))
185
186     # TODO: DUMP RESULTS TO FILE
187     # TODO: DUMP GRAPH DELAYS!
188     f = open("/tmp/metric", "w+")
189     f.write("%.2f\n" % metric)
190     f.close()
191     print " METRIC", metric
192
193     return metric
194
195 def add_dce_edge(ec, nid1, nid2):
196     ### Add network interfaces to hosts
197     p2p1 = add_dce_net_iface(ec, nid1, nid2)
198     p2p2 = add_dce_net_iface(ec, nid2, nid1)
199
200     # Create point to poing link between interfaces
201     chan = ec.register_resource("ns3::PointToPointChannel")
202     ec.set(chan, "Delay", "0ms")
203
204     ec.register_connection(chan, p2p1)
205     ec.register_connection(chan, p2p2)
206
207     #### Add routing between CCN nodes
208     add_dce_fib_entry(ec, nid1, nid2)
209     add_dce_fib_entry(ec, nid2, nid1)
210
211 def add_dce_node(ec, nid):
212     ### Add CCN nodes (ec.netgraph holds the topology graph)
213     add_dce_host(ec, nid)
214     add_dce_ccnd(ec, nid)
215         
216     if nid == ec.netgraph.targets()[0]:
217         add_dce_ccnr(ec, nid)
218
219     if nid == ec.netgraph.sources()[0]:
220         add_dce_ccncat(ec, nid)
221
222 if __name__ == '__main__':
223
224     #### Create NEPI Experiment Description with LINEAR topology 
225     ec = ExperimentController("dce_ccn", 
226             topo_type = TopologyType.LINEAR, 
227             node_count = 4,
228             assign_st = True,
229             assign_ips = True,
230             add_node_callback = add_dce_node, 
231             add_edge_callback = add_dce_edge)
232     
233     print "Results stored at", ec.exp_dir
234
235     #### Retrieve the consumer to wait for ot to finish
236     ccncat = ec.filter_resources("ns3::LinuxDceCCNCat")
237    
238     #### Run experiment until metric convergences
239     rnr = ExperimentRunner()
240     runs = rnr.run(ec, min_runs = 1, max_runs = 1, 
241             compute_metric_callback = avg_interests,
242             wait_guids = ccncat,
243             wait_time = 0)
244