3 ###############################################################################
6 # Copyright (C) 2014 INRIA
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License version 2 as
10 # published by the Free Software Foundation;
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/>.
21 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
23 ###############################################################################
26 # This library contains functions to parse log files generated using ping.
33 # RE to match line starting "traceroute to"
34 _rre = re.compile("\d+ bytes from ((?P<hostname>[^\s]+) )?\(?(?P<ip>[^\s]+)\)??: icmp_.eq=\d+ ttl=\d+ time=(?P<time>[^\s]+) ms")
36 def parse_file(filename):
38 filename: path to traceroute file
42 with open(filename, "r") as f:
46 target_hostname = None
51 # match traceroute to ...
52 m = re.match(_rre, line)
56 target_ip = m.groupdict()["ip"]
57 # FIX THIS: Make sure the regular expression does not inlcude
58 # the ')' in the ip group
59 target_ip = target_ip.replace(")","")
60 target_hostname = m.groupdict()["hostname"]
61 time = m.groupdict()["time"]
62 data.append((target_ip, target_hostname, time))
66 def annotate_cn_node(graph, nid1, ips2nid, data):
67 for (target_ip, target_hostname, time) in data:
68 nid2 = ips2nid[target_ip]
70 if "delays" not in graph.edge[nid1][nid2]:
71 graph.edge[nid1][nid2]["delays"] = []
73 time = float(time.replace("ms", "").replace(" ",""))
75 graph.edge[nid1][nid2]["delays"].append(time)
77 def annotate_cn_graph(logs_dir, graph):
78 """ Add delay inormation to graph using data collected using
84 for nid in graph.nodes():
85 ips = graph.node[nid]["ips"]
89 # Walk through the ping logs...
92 for dirpath, dnames, fnames in os.walk(logs_dir):
93 # continue if we are not at the leaf level (if there are subdirectories)
97 # Each dirpath correspond to a different host
98 nid = os.path.basename(dirpath)
101 if fname.endswith(".ping"):
103 filename = os.path.join(dirpath, fname)
104 data = parse_file(filename)
105 annotate_cn_node(graph, nid, ips2nid, data)
108 msg = "No PING output files were found to parse at %s " % logs_dir
109 raise RuntimeError(msg)
111 # Take as weight the most frequent value
112 for nid1, nid2 in graph.edges():
113 delays = collections.Counter(graph.edge[nid1][nid2]["delays"])
114 weight = delays.most_common(1)[0][0]
115 del graph.edge[nid1][nid2]["delays"]
116 graph.edge[nid1][nid2]["weight"] = weight