3 # NEPI, a framework to manage network experiments
4 # Copyright (C) 2013 INRIA
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;
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.
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/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20 from __future__ import print_function
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
32 0: "iraplab1.iralab.uni-karlsruhe.de",
33 1: "planetvs2.informatik.uni-stuttgart.de",
34 2: "dfn-ple1.x-win.dfn.de",
35 3: "planetlab2.extern.kuleuven.be",
36 4: "mars.planetlab.haw-hamburg.de",
37 5: "planetlab-node3.it-sudparis.eu",
38 6: "node2pl.planet-lab.telecom-lille1.eu",
39 7: "planetlab1.informatik.uni-wuerzburg.de",
40 8: "planet1.l3s.uni-hannover.de",
41 9: "planetlab1.wiwi.hu-berlin.de",
42 10: "pl2.uni-rostock.de",
43 11: "planetlab1.u-strasbg.fr",
44 12: "peeramidion.irisa.fr",
45 13: "planetlab2.unineuchatel.ch",
48 pl_slice = os.environ.get("PL_SLICE")
49 pl_user = os.environ.get("PL_USER")
50 pl_password = os.environ.get("PL_PASS")
51 pl_ssh_key = os.environ.get("PL_SSHKEY")
53 content_name = "ccnx:/test/bunny.ts"
55 pipeline = 4 # Default value for ccncat
57 operating_system = "f14"
61 repofile = os.path.join(
62 os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
64 def add_collector(ec, trace_name, subdir, newname = None):
65 collector = ec.register_resource("Collector")
66 ec.set(collector, "traceName", trace_name)
67 ec.set(collector, "subDir", subdir)
69 ec.set(collector, "rename", newname)
73 def add_pl_host(ec, nid):
74 hostname = PL_NODES[nid]
76 # Add a planetlab host to the experiment description
77 host = ec.register_resource("planetlab::Node")
78 ec.set(host, "hostname", hostname)
79 ec.set(host, "username", pl_slice)
80 ec.set(host, "identity", pl_ssh_key)
81 #ec.set(host, "pluser", pl_user)
82 #ec.set(host, "plpassword", pl_password)
83 #ec.set(host, "country", country)
84 #ec.set(host, "operatingSystem", operating_system)
85 ec.set(host, "cleanExperiment", True)
86 ec.set(host, "cleanProcesses", True)
89 ec.netgraph.annotate_node(nid, "hostname", hostname)
90 ec.netgraph.annotate_node(nid, "host", host)
92 # Annotate the graph node with an ip address
93 ip = socket.gethostbyname(hostname)
94 ec.netgraph.annotate_node_ip(nid, ip)
96 def add_pl_ccnd(ec, nid):
97 # Retrieve annotation from netgraph
98 host = ec.netgraph.node_annotation(nid, "host")
100 # Add a CCN daemon to the planetlab node
101 ccnd = ec.register_resource("linux::CCND")
102 ec.set(ccnd, "debug", 7)
103 ec.register_connection(ccnd, host)
105 # Collector to retrieve ccnd log
106 collector = add_collector(ec, "stderr", nid, "log")
107 ec.register_connection(collector, ccnd)
110 ec.netgraph.annotate_node(nid, "ccnd", ccnd)
112 def add_pl_ccnr(ec, nid):
113 # Retrieve annotation from netgraph
114 ccnd = ec.netgraph.node_annotation(nid, "ccnd")
116 # Add a CCN content repository to the planetlab node
117 ccnr = ec.register_resource("linux::CCNR")
119 ec.set(ccnr, "repoFile1", repofile)
120 ec.register_connection(ccnr, ccnd)
122 def add_pl_ccncat(ec, nid):
123 # Retrieve annotation from netgraph
124 ccnd = ec.netgraph.node_annotation(nid, "ccnd")
126 # Add a CCN cat application to the planetlab node
127 ccncat = ec.register_resource("linux::CCNCat")
128 ec.set(ccncat, "pipeline", pipeline)
129 ec.set(ccncat, "contentName", content_name)
130 ec.register_connection(ccncat, ccnd)
132 def add_pl_fib_entry(ec, nid1, nid2):
133 # Retrieve annotations from netgraph
134 ccnd1 = ec.netgraph.node_annotation(nid1, "ccnd")
135 hostname2 = ec.netgraph.node_annotation(nid2, "hostname")
137 # Add a FIB entry between one planetlab node and its peer
138 entry = ec.register_resource("linux::FIBEntry")
139 ec.set(entry, "host", hostname2)
140 ec.register_connection(entry, ccnd1)
142 # Collector to retrieve peering ping output (to measure neighbors delay)
143 ec.enable_trace(entry, "ping")
144 collector = add_collector(ec, "ping", nid1)
145 ec.register_connection(collector, entry)
149 def avg_interests(ec, run):
151 logs_dir = ec.run_dir
155 interest_expiry_count,
156 interest_dupnonce_count,
158 content_count) = ccn_parser.process_content_history_logs(
160 ec.netgraph.topology,
161 parse_ping_logs = True)
163 shortest_path = networkx.shortest_path(graph,
164 source = ec.netgraph.sources()[0],
165 target = ec.netgraph.targets()[0])
167 ### Compute metric: Avg number of Interests seen per content name
168 ### normalized by the number of nodes in the shortest path
169 content_name_count = len(content_names)
170 nodes_in_shortest_path = len(shortest_path) - 1
171 metric = interest_count / (float(content_name_count) * float(nodes_in_shortest_path))
173 # TODO: DUMP RESULTS TO FILE
174 # TODO: DUMP GRAPH DELAYS!
175 with open("/tmp/metric", "a+") as f:
176 f.write("%.2f\n" % metric)
177 print(" METRIC", metric)
181 def add_pl_edge(ec, nid1, nid2):
182 #### Add connections between CCN nodes
183 add_pl_fib_entry(ec, nid1, nid2)
184 add_pl_fib_entry(ec, nid2, nid1)
186 def add_pl_node(ec, nid):
187 ### Add CCN nodes (ec.netgraph holds the topology graph)
191 if nid == ec.netgraph.targets()[0]:
194 if nid == ec.netgraph.sources()[0]:
195 add_pl_ccncat(ec, nid)
197 if __name__ == '__main__':
199 #### Create NEPI Experiment Description with LINEAR topology
200 ec = ExperimentController("pl_ccn",
201 topo_type = TopologyType.LINEAR,
205 add_node_callback = add_pl_node,
206 add_edge_callback = add_pl_edge)
208 print("Results stored at", ec.exp_dir)
210 #### Retrieve the content producing resource to wait for ot to finish
211 ccncat = ec.filter_resources("linux::CCNCat")
213 #### Run experiment until metric convergences
214 rnr = ExperimentRunner()
215 runs = rnr.run(ec, min_runs = 10, max_runs = 300,
216 compute_metric_callback = avg_interests,