3 ###############################################################################
5 # NEPI, a framework to manage network experiments
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.
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.
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/>.
20 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
22 ###############################################################################
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
33 content_name = "ccnx:/test/bunny.ts"
37 operating_system = "f14"
39 repofile = os.path.join(
40 os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
42 def get_simulator(ec):
43 simulator = ec.filter_resources("LinuxNS3Simulation")
46 node = ec.register_resource("LinuxNode")
47 ec.set(node, "hostname", "localhost")
49 simu = ec.register_resource("LinuxNS3Simulation")
50 ec.register_connection(simu, node)
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)
60 ec.set(collector, "rename", newname)
64 def add_dce_host(ec, nid):
65 simu = get_simulator(ec)
67 host = ec.register_resource("ns3::Node")
68 ec.set(host, "enableStack", True)
69 ec.register_connection(host, simu)
72 ec.netgraph.annotate_node(nid, "host", host)
74 def add_dce_ccnd(ec, nid):
75 # Retrieve annotation from netgraph
76 host = ec.netgraph.node_annotation(nid, "host")
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)
87 # Collector to retrieve ccnd log
88 collector = add_collector(ec, "stderr", nid, "log")
89 ec.register_connection(collector, ccnd)
92 ec.netgraph.annotate_node(nid, "ccnd", ccnd)
94 def add_dce_ccnr(ec, nid):
95 # Retrieve annotation from netgraph
96 host = ec.netgraph.node_annotation(nid, "host")
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)
106 def add_dce_ccncat(ec, nid):
107 # Retrieve annotation from netgraph
108 host = ec.netgraph.node_annotation(nid, "host")
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)
118 collector = add_collector(ec, "stdout", nid, "peek")
119 ec.register_connection(collector, ccnpeek)
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)
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)
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)
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)
150 prefix = net["prefix"]
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)
158 queue = ec.register_resource("ns3::DropTailQueue")
159 ec.register_connection(dev, queue)
163 def avg_interests(ec, run):
165 logs_dir = ec.run_dir
169 interest_expiry_count,
170 interest_dupnonce_count,
172 content_count) = ccn_parser.process_content_history_logs(
174 ec.netgraph.topology)
176 shortest_path = networkx.shortest_path(graph,
177 source = ec.netgraph.sources()[0],
178 target = ec.netgraph.targets()[0])
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))
186 # TODO: DUMP RESULTS TO FILE
187 # TODO: DUMP GRAPH DELAYS!
188 f = open("/tmp/metric", "w+")
189 f.write("%.2f\n" % metric)
191 print " METRIC", metric
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)
200 # Create point to poing link between interfaces
201 chan = ec.register_resource("ns3::PointToPointChannel")
202 ec.set(chan, "Delay", "0ms")
204 ec.register_connection(chan, p2p1)
205 ec.register_connection(chan, p2p2)
207 #### Add routing between CCN nodes
208 add_dce_fib_entry(ec, nid1, nid2)
209 add_dce_fib_entry(ec, nid2, nid1)
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)
216 if nid == ec.netgraph.targets()[0]:
217 add_dce_ccnr(ec, nid)
219 if nid == ec.netgraph.sources()[0]:
220 add_dce_ccncat(ec, nid)
222 if __name__ == '__main__':
224 #### Create NEPI Experiment Description with LINEAR topology
225 ec = ExperimentController("dce_ccn",
226 topo_type = TopologyType.LINEAR,
230 add_node_callback = add_dce_node,
231 add_edge_callback = add_dce_edge)
233 print "Results stored at", ec.exp_dir
235 #### Retrieve the consumer to wait for ot to finish
236 ccncat = ec.filter_resources("ns3::LinuxDceCCNCat")
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,