#!/usr/bin/env python
###############################################################################
#
# NEPI, a framework to manage network experiments
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
# Author: Alina Quereilhac
#
###############################################################################
from nepi.execution.ec import ExperimentController
from nepi.execution.runner import ExperimentRunner
from nepi.util.netgraph import NetGraph, TopologyType
import nepi.data.processing.ccn.parser as ccn_parser
import networkx
import socket
import os
PL_NODES = dict({
0: "iraplab1.iralab.uni-karlsruhe.de",
1: "planetvs2.informatik.uni-stuttgart.de",
2: "dfn-ple1.x-win.dfn.de",
3: "planetlab2.extern.kuleuven.be",
4: "mars.planetlab.haw-hamburg.de",
5: "planetlab-node3.it-sudparis.eu",
6: "node2pl.planet-lab.telecom-lille1.eu",
7: "planetlab1.informatik.uni-wuerzburg.de",
8: "planet1.l3s.uni-hannover.de",
9: "planetlab1.wiwi.hu-berlin.de",
10: "pl2.uni-rostock.de",
11: "planetlab1.u-strasbg.fr",
12: "peeramidion.irisa.fr",
13: "planetlab2.unineuchatel.ch",
})
pl_slice = os.environ.get("PL_SLICE")
pl_user = os.environ.get("PL_USER")
pl_password = os.environ.get("PL_PASS")
pl_ssh_key = os.environ.get("PL_SSHKEY")
content_name = "ccnx:/test/bunny.ts"
pipeline = 4 # Default value for ccncat
operating_system = "f14"
country = "germany"
repofile = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "repoFile1.0.8.2")
def add_collector(ec, trace_name, subdir, newname = None):
collector = ec.register_resource("Collector")
ec.set(collector, "traceName", trace_name)
ec.set(collector, "subDir", subdir)
if newname:
ec.set(collector, "rename", newname)
return collector
def add_pl_host(ec, nid):
hostname = PL_NODES[nid]
# Add a planetlab host to the experiment description
host = ec.register_resource("PlanetlabNode")
ec.set(host, "hostname", hostname)
ec.set(host, "username", pl_slice)
ec.set(host, "identity", pl_ssh_key)
#ec.set(host, "pluser", pl_user)
#ec.set(host, "plpassword", pl_password)
#ec.set(host, "country", country)
#ec.set(host, "operatingSystem", operating_system)
ec.set(host, "cleanExperiment", True)
ec.set(host, "cleanProcesses", True)
# Annotate the graph
ec.netgraph.annotate_node(nid, "hostname", hostname)
ec.netgraph.annotate_node(nid, "host", host)
# Annotate the graph node with an ip address
ip = socket.gethostbyname(hostname)
ec.netgraph.annotate_node_ip(nid, ip)
def add_pl_ccnd(ec, nid):
# Retrieve annotation from netgraph
host = ec.netgraph.node_annotation(nid, "host")
# Add a CCN daemon to the planetlab node
ccnd = ec.register_resource("LinuxCCND")
ec.set(ccnd, "debug", 7)
ec.register_connection(ccnd, host)
# Collector to retrieve ccnd log
collector = add_collector(ec, "stderr", nid, "log")
ec.register_connection(collector, ccnd)
# Annotate the graph
ec.netgraph.annotate_node(nid, "ccnd", ccnd)
def add_pl_ccnr(ec, nid):
# Retrieve annotation from netgraph
ccnd = ec.netgraph.node_annotation(nid, "ccnd")
# Add a CCN content repository to the planetlab node
ccnr = ec.register_resource("LinuxCCNR")
ec.set(ccnr, "repoFile1", repofile)
ec.register_connection(ccnr, ccnd)
def add_pl_ccncat(ec, nid):
# Retrieve annotation from netgraph
ccnd = ec.netgraph.node_annotation(nid, "ccnd")
# Add a CCN cat application to the planetlab node
ccncat = ec.register_resource("LinuxCCNCat")
ec.set(ccncat, "pipeline", pipeline)
ec.set(ccncat, "contentName", content_name)
ec.register_connection(ccncat, ccnd)
def add_pl_fib_entry(ec, nid1, nid2):
# Retrieve annotations from netgraph
ccnd1 = ec.netgraph.node_annotation(nid1, "ccnd")
hostname2 = ec.netgraph.node_annotation(nid2, "hostname")
# Add a FIB entry between one planetlab node and its peer
entry = ec.register_resource("LinuxFIBEntry")
ec.set(entry, "host", hostname2)
ec.register_connection(entry, ccnd1)
# Collector to retrieve peering ping output (to measure neighbors delay)
ec.enable_trace(entry, "ping")
collector = add_collector(ec, "ping", nid1)
ec.register_connection(collector, entry)
return entry
def avg_interests(ec, run):
## Process logs
logs_dir = ec.run_dir
(graph,
content_names,
interest_expiry_count,
interest_dupnonce_count,
interest_count,
content_count) = ccn_parser.process_content_history_logs(
logs_dir,
ec.netgraph.topology,
parse_ping_logs = True)
shortest_path = networkx.shortest_path(graph,
source = ec.netgraph.sources()[0],
target = ec.netgraph.targets()[0])
### Compute metric: Avg number of Interests seen per content name
### normalized by the number of nodes in the shortest path
content_name_count = len(content_names.values())
nodes_in_shortest_path = len(shortest_path) - 1
metric = interest_count / (float(content_name_count) * float(nodes_in_shortest_path))
# TODO: DUMP RESULTS TO FILE
# TODO: DUMP GRAPH DELAYS!
f = open("/tmp/metric", "a+")
f.write("%.2f\n" % metric)
f.close()
print " METRIC", metric
return metric
def add_pl_edge(ec, nid1, nid2):
#### Add connections between CCN nodes
add_pl_fib_entry(ec, nid1, nid2)
add_pl_fib_entry(ec, nid2, nid1)
def add_pl_node(ec, nid):
### Add CCN nodes (ec.netgraph holds the topology graph)
add_pl_host(ec, nid)
add_pl_ccnd(ec, nid)
if nid == ec.netgraph.targets()[0]:
add_pl_ccnr(ec, nid)
if nid == ec.netgraph.sources()[0]:
add_pl_ccncat(ec, nid)
if __name__ == '__main__':
#### Create NEPI Experiment Description with LINEAR topology
ec = ExperimentController("pl_ccn",
topo_type = TopologyType.LINEAR,
node_count = 4,
#assign_ips = True,
assign_st = True,
add_node_callback = add_pl_node,
add_edge_callback = add_pl_edge)
print "Results stored at", ec.exp_dir
#### Retrieve the content producing resource to wait for ot to finish
ccncat = ec.filter_resources("LinuxCCNCat")
#### Run experiment until metric convergences
rnr = ExperimentRunner()
runs = rnr.run(ec, min_runs = 10, max_runs = 300,
compute_metric_callback = avg_interests,
wait_guids = ccncat,
wait_time = 0)