7f490a4f1b3e27215519a60001876eee00762316
[nepi.git] / examples / ccn_emu_live / dce.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 from nepi.execution.ec import ExperimentController 
21 from nepi.execution.runner import ExperimentRunner
22 from nepi.util.netgraph import NetGraph, TopologyType
23 import nepi.data.processing.ccn.parser as ccn_parser
24
25 import networkx
26 import socket
27 import os
28
29 content_name = "ccnx:/test/bunny.ts"
30
31 STOP_TIME = "5000s"
32
33 repofile = os.path.join(
34         os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
35
36 def get_simulator(ec):
37     simulator = ec.filter_resources("linux::ns3::Simulation")
38
39     if not simulator:
40         node = ec.register_resource("linux::Node")
41         ec.set(node, "hostname", "localhost")
42
43         simu = ec.register_resource("linux::ns3::Simulation")
44         ec.set(simu, "enableDump", True)
45         ec.set(simu, "StopTime", STOP_TIME)
46         ec.register_connection(simu, node)
47         return simu
48
49     return simulator[0]
50
51 def add_collector(ec, trace_name, subdir, newname = None):
52     collector = ec.register_resource("Collector")
53     ec.set(collector, "traceName", trace_name)
54     ec.set(collector, "subDir", subdir)
55     if newname:
56         ec.set(collector, "rename", newname)
57
58     return collector
59
60 def add_dce_host(ec, nid):
61     simu = get_simulator(ec)
62     
63     host = ec.register_resource("ns3::Node")
64     ec.set(host, "enableStack", True)
65     ec.register_connection(host, simu)
66
67     # Annotate the graph
68     ec.netgraph.annotate_node(nid, "host", host)
69     
70 def add_dce_ccnd(ec, nid):
71     # Retrieve annotation from netgraph
72     host = ec.netgraph.node_annotation(nid, "host")
73     
74     # Add dce ccnd to the dce node
75     ccnd = ec.register_resource("linux::ns3::dce::CCND")
76     ec.set (ccnd, "stackSize", 1<<20)
77     ec.set (ccnd, "debug", 7)
78     ec.set (ccnd, "capacity", 50000)
79     ec.set (ccnd, "StartTime", "1s")
80     ec.register_connection(ccnd, host)
81
82     # Collector to retrieve ccnd log
83     collector = add_collector(ec, "stderr", nid, "log")
84     ec.register_connection(collector, ccnd)
85
86     # Annotate the graph
87     ec.netgraph.annotate_node(nid, "ccnd", ccnd)
88
89 def add_dce_ccnr(ec, nid):
90     # Retrieve annotation from netgraph
91     host = ec.netgraph.node_annotation(nid, "host")
92     
93     # Add a CCN content repository to the dce node
94     ccnr = ec.register_resource("linux::ns3::dce::CCNR")
95     ec.set (ccnr, "repoFile1", repofile) 
96     ec.set (ccnr, "stackSize", 1<<20)
97     ec.set (ccnr, "StartTime", "2s")
98     ec.register_connection(ccnr, host)
99
100 def add_dce_ccncat(ec, nid):
101     # Retrieve annotation from netgraph
102     host = ec.netgraph.node_annotation(nid, "host")
103    
104     # Add a ccncat application to the dce host
105     ccncat = ec.register_resource("linux::ns3::dce::CCNCat")
106     ec.set (ccncat, "contentName", content_name)
107     ec.set (ccncat, "stackSize", 1<<20)
108     ec.set (ccncat, "StartTime", "8s")
109     ec.register_connection(ccncat, host)
110
111 def add_dce_fib_entry(ec, nid1, nid2):
112     # Retrieve annotations from netgraph
113     host1 = ec.netgraph.node_annotation(nid1, "host")
114     net = ec.netgraph.edge_net_annotation(nid1, nid2)
115     ip2 = net[nid2]
116
117     # Add FIB entry between peer hosts
118     ccndc = ec.register_resource("linux::ns3::dce::FIBEntry")
119     ec.set (ccndc, "protocol", "udp") 
120     ec.set (ccndc, "uri", "ccnx:/") 
121     ec.set (ccndc, "host", ip2)
122     ec.set (ccndc, "stackSize", 1<<20)
123     ec.set (ccndc, "StartTime", "4s")
124     ec.register_connection(ccndc, host1)
125
126 def add_dce_net_iface(ec, nid1, nid2):
127     # Retrieve annotations from netgraph
128     host = ec.netgraph.node_annotation(nid1, "host")
129     net = ec.netgraph.edge_net_annotation(nid1, nid2)
130     ip1 = net[nid1]
131     prefix = net["prefix"]
132
133     dev = ec.register_resource("ns3::PointToPointNetDevice")
134     ec.set(dev,"DataRate", "5Mbps")
135     ec.set(dev, "ip", ip1)
136     ec.set(dev, "prefix", prefix)
137     ec.register_connection(host, dev)
138
139     queue = ec.register_resource("ns3::DropTailQueue")
140     ec.register_connection(dev, queue)
141
142     return dev
143
144 def avg_interests(ec, run):
145     ## Process logs
146     logs_dir = ec.run_dir
147
148     (graph,
149         content_names,
150         interest_expiry_count,
151         interest_dupnonce_count,
152         interest_count,
153         content_count) = ccn_parser.process_content_history_logs(
154                 logs_dir, 
155                 ec.netgraph.topology)
156
157     shortest_path = networkx.shortest_path(graph, 
158             source = ec.netgraph.sources()[0], 
159             target = ec.netgraph.targets()[0])
160
161     ### Compute metric: Avg number of Interests seen per content name
162     ###                 normalized by the number of nodes in the shortest path
163     content_name_count = len(content_names.values())
164     nodes_in_shortest_path = len(shortest_path) - 1
165     metric = interest_count / (float(content_name_count) * float(nodes_in_shortest_path))
166
167     # TODO: DUMP RESULTS TO FILE
168     # TODO: DUMP GRAPH DELAYS!
169     f = open("/tmp/metric", "a+")
170     f.write("%.2f\n" % metric)
171     f.close()
172     print " METRIC", metric
173
174     return metric
175
176 def add_dce_edge(ec, nid1, nid2):
177     ### Add network interfaces to hosts
178     p2p1 = add_dce_net_iface(ec, nid1, nid2)
179     p2p2 = add_dce_net_iface(ec, nid2, nid1)
180
181     # Create point to point link between interfaces
182     chan = ec.register_resource("ns3::PointToPointChannel")
183     ec.set(chan, "Delay", "0ms")
184
185     ec.register_connection(chan, p2p1)
186     ec.register_connection(chan, p2p2)
187
188     #### Add routing between CCN nodes
189     add_dce_fib_entry(ec, nid1, nid2)
190     add_dce_fib_entry(ec, nid2, nid1)
191
192 def add_dce_node(ec, nid):
193     ### Add CCN nodes (ec.netgraph holds the topology graph)
194     add_dce_host(ec, nid)
195     add_dce_ccnd(ec, nid)
196         
197     if nid == ec.netgraph.targets()[0]:
198         add_dce_ccnr(ec, nid)
199
200     if nid == ec.netgraph.sources()[0]:
201         add_dce_ccncat(ec, nid)
202
203 if __name__ == '__main__':
204
205     #### Create NEPI Experiment Description with LINEAR topology 
206     ec = ExperimentController("dce_ccn", 
207             topo_type = TopologyType.LINEAR, 
208             node_count = 2,
209             assign_st = True,
210             assign_ips = True,
211             add_node_callback = add_dce_node, 
212             add_edge_callback = add_dce_edge)
213     
214     print "Results stored at", ec.exp_dir
215
216     #### Retrieve the consumer to wait for ot to finish
217     ccncat = ec.filter_resources("linux::ns3::dce::CCNCat")
218    
219     #### Run experiment until metric convergences
220     rnr = ExperimentRunner()
221     runs = rnr.run(ec, min_runs = 1, max_runs = 1, 
222             compute_metric_callback = avg_interests,
223             wait_guids = ccncat,
224             wait_time = 0)
225