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