blob: f7953f223d4a672f23a0031410a2f04968b4edf0 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Florin Coras3417d082019-06-12 08:12:58 -07002
3import sys
4import re
5import argparse
6import matplotlib.pyplot as plt
7from matplotlib.lines import Line2D
8
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02009
10class Point:
Florin Coras3417d082019-06-12 08:12:58 -070011 "CC event"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020012
Florin Coras3417d082019-06-12 08:12:58 -070013 def __init__(self, x, y):
14 self.x = x
15 self.y = y
16
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020017
Florin Coras3417d082019-06-12 08:12:58 -070018def listx(points):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020019 return list(map(lambda pt: pt.x, points))
20
Florin Coras3417d082019-06-12 08:12:58 -070021
22def listy(points):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020023 return list(map(lambda pt: pt.y, points))
24
Florin Coras3417d082019-06-12 08:12:58 -070025
26def plot_data(d):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020027 plt.figure(1)
Florin Coras3417d082019-06-12 08:12:58 -070028
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020029 cwndx = listx(d["cwnd"])
30 cwndy = listy(d["cwnd"])
31 congx = listx(d["congestion"])
32 congy = listy(d["congestion"])
33 rcvrdx = listx(d["recovered"])
34 rcvrdy = listy(d["recovered"])
35 rxttx = listx(d["rxtTimeout"])
36 rxtty = listy(d["rxtTimeout"])
Florin Coras3417d082019-06-12 08:12:58 -070037
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020038 # cwnd/ssthresh/cc events
39 plt.subplot(311)
40 plt.title("cwnd/ssthresh")
41 pcwnd = plt.plot(cwndx, cwndy, "r")
42 psst = plt.plot(cwndx, d["ssthresh"], "y-")
43 pcong = plt.plot(congx, congy, "yo")
44 precov = plt.plot(rcvrdx, rcvrdy, "co")
45 prxtt = plt.plot(rxttx, rxtty, "mo")
Florin Coras3417d082019-06-12 08:12:58 -070046
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020047 marker1 = Line2D(range(1), range(1), color="r")
48 marker2 = Line2D(range(1), range(1), color="y")
49 marker3 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="y")
50 marker4 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="c")
51 marker5 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="m")
52 plt.legend(
53 (marker1, marker2, marker3, marker4, marker5),
54 ("cwnd", "ssthresh", "congestion", "recovered", "rxt-timeout"),
55 loc=4,
56 )
57 axes = plt.gca()
58 axes.set_ylim([-20e4, max(cwndy) + 20e4])
Florin Coras3417d082019-06-12 08:12:58 -070059
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020060 # snd variables
61 plt.subplot(312)
62 plt.title("cc variables")
63 plt.plot(cwndx, d["space"], "g-", markersize=1)
64 plt.plot(cwndx, d["flight"], "b-", markersize=1)
65 plt.plot(cwndx, d["sacked"], "m:", markersize=1)
66 plt.plot(cwndx, d["lost"], "y:", markersize=1)
67 plt.plot(cwndx, d["cc-space"], "k:", markersize=1)
68 plt.plot(cwndx, cwndy, "ro", markersize=2)
Florin Coras3417d082019-06-12 08:12:58 -070069
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020070 plt.plot(congx, congy, "y^", markersize=10, markerfacecolor="y")
71 plt.plot(rcvrdx, rcvrdy, "c^", markersize=10, markerfacecolor="c")
72 plt.plot(rxttx, rxtty, "m^", markersize=10, markerfacecolor="m")
Florin Coras3417d082019-06-12 08:12:58 -070073
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020074 # plt.plot(cwndx, d["snd_wnd"], 'ko', markersize=1)
75 plt.legend(
76 (
77 "snd-space",
78 "flight",
79 "sacked",
80 "lost",
81 "cc-space",
82 "cwnd",
83 "congestion",
84 "recovered",
85 "rxt-timeout",
86 ),
87 loc=1,
88 )
Florin Coras3417d082019-06-12 08:12:58 -070089
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020090 # rto/srrt/rttvar
91 plt.subplot(313)
92 plt.title("rtt")
93 plt.plot(cwndx, d["srtt"], "g-")
94 plt.plot(cwndx, [x / 1000 for x in d["mrtt-us"]], "r-")
95 plt.plot(cwndx, d["rttvar"], "b-")
96 plt.legend(["srtt", "mrtt-us", "rttvar"])
97 axes = plt.gca()
98 # plt.plot(cwndx, rto, 'r-')
99 # axes.set_ylim([0, int(max(rto[2:len(rto)])) + 50])
Florin Coras3417d082019-06-12 08:12:58 -0700100
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 # show
102 plt.show()
Florin Coras3417d082019-06-12 08:12:58 -0700103
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200104
105def find_pattern(file_path, session_idx):
Florin Coras3417d082019-06-12 08:12:58 -0700106 is_active_open = 1
107 listener_pattern = "l\[\d\]"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200108 if is_active_open:
109 initial_pattern = "\[\d\](\.\d+:\d+\->\.\d+:\d+)\s+open:\s"
Florin Coras3417d082019-06-12 08:12:58 -0700110 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200111 initial_pattern = "\[\d\](\.\d+:\d+\->\.\d+:\d+)\s"
Florin Coras3417d082019-06-12 08:12:58 -0700112 idx = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200113 f = open(file_path, "r")
Florin Coras3417d082019-06-12 08:12:58 -0700114 for line in f:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200115 # skip listener lines (server)
116 if re.search(listener_pattern, line) != None:
117 continue
118 match = re.search(initial_pattern, line)
119 if match == None:
120 continue
121 if idx < session_idx:
122 idx += 1
123 continue
124 filter_pattern = str(match.group(1)) + "\s+(.+)"
125 print("pattern is %s" % filter_pattern)
126 f.close()
127 return filter_pattern
128 raise Exception("Could not find initial pattern")
129
Florin Coras3417d082019-06-12 08:12:58 -0700130
131def compute_time(min, sec, msec):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200132 return int(min) * 60 + int(sec) + int(msec) / 1000.0
133
Florin Coras3417d082019-06-12 08:12:58 -0700134
135def run(file_path, session_idx):
136 filter_sessions = 1
137 filter_pattern = ""
138
139 patterns = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200140 "time": "^\d+:(\d+):(\d+):(\d+):\d+",
141 "listener": "l\[\d\]",
142 "cc": "cwnd (\d+) flight (\d+) space (\d+) ssthresh (\d+) snd_wnd (\d+)",
143 "cc-snd": "cc_space (\d+) sacked (\d+) lost (\d+)",
144 "rtt": "rto (\d+) srtt (\d+) mrtt-us (\d+) rttvar (\d+)",
145 "rxtt": "rxt-timeout",
146 "congestion": "congestion",
147 "recovered": "recovered",
Florin Coras3417d082019-06-12 08:12:58 -0700148 }
149 d = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200150 "cwnd": [],
151 "space": [],
152 "flight": [],
153 "ssthresh": [],
154 "snd_wnd": [],
155 "cc-space": [],
156 "lost": [],
157 "sacked": [],
158 "rto": [],
159 "srtt": [],
160 "mrtt-us": [],
161 "rttvar": [],
162 "rxtTimeout": [],
163 "congestion": [],
164 "recovered": [],
Florin Coras3417d082019-06-12 08:12:58 -0700165 }
166
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 if filter_sessions:
Florin Coras3417d082019-06-12 08:12:58 -0700168 filter_pattern = find_pattern(file_path, session_idx)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200169 f = open(file_path, "r")
Florin Coras3417d082019-06-12 08:12:58 -0700170
171 stats_index = 0
172 start_time = 0
173
174 for line in f:
175 # skip listener lines (server)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200176 if re.search(patterns["listener"], line) != None:
Florin Coras3417d082019-06-12 08:12:58 -0700177 continue
178 # filter sessions
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200179 if filter_sessions:
Florin Coras3417d082019-06-12 08:12:58 -0700180 match = re.search(filter_pattern, line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200181 if match == None:
Florin Coras3417d082019-06-12 08:12:58 -0700182 continue
183
184 original_line = line
185 line = match.group(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200186 match = re.search(patterns["time"], original_line)
187 if match == None:
188 print("something went wrong! no time!")
189 continue
190 time = compute_time(match.group(1), match.group(2), match.group(3))
191 if start_time == 0:
192 start_time = time
Florin Coras3417d082019-06-12 08:12:58 -0700193
194 time = time - start_time
195 match = re.search(patterns["cc"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200196 if match != None:
197 d["cwnd"].append(Point(time, int(match.group(1))))
198 d["flight"].append(int(match.group(2)))
199 d["space"].append(int(match.group(3)))
200 d["ssthresh"].append(int(match.group(4)))
201 d["snd_wnd"].append(int(match.group(5)))
202 stats_index += 1
203 continue
Florin Coras3417d082019-06-12 08:12:58 -0700204 match = re.search(patterns["cc-snd"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200205 if match != None:
206 d["cc-space"].append(int(match.group(1)))
207 d["sacked"].append(int(match.group(2)))
208 d["lost"].append(int(match.group(3)))
Florin Coras3417d082019-06-12 08:12:58 -0700209 match = re.search(patterns["rtt"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200210 if match != None:
211 d["rto"].append(int(match.group(1)))
212 d["srtt"].append(int(match.group(2)))
213 d["mrtt-us"].append(int(match.group(3)))
214 d["rttvar"].append(int(match.group(4)))
215 if stats_index == 0:
216 continue
Florin Coras3417d082019-06-12 08:12:58 -0700217 match = re.search(patterns["rxtt"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200218 if match != None:
219 d["rxtTimeout"].append(Point(time, d["cwnd"][stats_index - 1].y + 1e4))
220 continue
Florin Coras3417d082019-06-12 08:12:58 -0700221 match = re.search(patterns["congestion"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 if match != None:
223 d["congestion"].append(Point(time, d["cwnd"][stats_index - 1].y - 1e4))
224 continue
Florin Coras3417d082019-06-12 08:12:58 -0700225 match = re.search(patterns["recovered"], line)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226 if match != None:
227 d["recovered"].append(Point(time, d["cwnd"][stats_index - 1].y))
228 continue
Florin Coras3417d082019-06-12 08:12:58 -0700229
230 plot_data(d)
231
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200232
Florin Coras3417d082019-06-12 08:12:58 -0700233if __name__ == "__main__":
234 parser = argparse.ArgumentParser(description="Plot tcp cc logs")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200235 parser.add_argument(
236 "-f", action="store", dest="file", required=True, help="elog file in txt format"
237 )
238 parser.add_argument(
239 "-s",
240 action="store",
241 dest="session_index",
242 default=0,
243 help="session index for which to plot cc logs",
244 )
Florin Coras3417d082019-06-12 08:12:58 -0700245 results = parser.parse_args()
246 run(results.file, int(results.session_index))