misc: Fix python scripts shebang line
[vpp.git] / src / scripts / host-stack / cc_plots.py
1 #!/usr/bin/env python3
2
3 import sys
4 import re
5 import argparse
6 import matplotlib.pyplot as plt
7 from matplotlib.lines import Line2D
8
9 class Point():
10     "CC event"
11     def __init__(self, x, y):
12         self.x = x
13         self.y = y
14
15 def listx(points):
16   return list(map(lambda pt: pt.x, points))
17
18 def listy(points):
19   return list(map(lambda pt: pt.y, points))
20
21 def plot_data(d):
22
23   plt.figure(1)
24
25   cwndx = listx(d["cwnd"])
26   cwndy = listy(d["cwnd"])
27   congx = listx(d["congestion"])
28   congy = listy(d["congestion"])
29   rcvrdx = listx(d["recovered"])
30   rcvrdy = listy(d["recovered"])
31   rxttx = listx(d["rxtTimeout"])
32   rxtty = listy(d["rxtTimeout"])
33
34   # cwnd/ssthresh/cc events
35   plt.subplot(311)
36   plt.title("cwnd/ssthresh")
37   pcwnd = plt.plot(cwndx, cwndy, 'r')
38   psst = plt.plot(cwndx, d["ssthresh"], 'y-')
39   pcong = plt.plot(congx, congy,'yo')
40   precov = plt.plot(rcvrdx, rcvrdy,'co')
41   prxtt = plt.plot(rxttx, rxtty,'mo')
42
43   marker1 = Line2D(range(1), range(1), color="r")
44   marker2 = Line2D(range(1), range(1), color="y")
45   marker3 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="y")
46   marker4 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="c")
47   marker5 = Line2D(range(1), range(1), color="w", marker="o", markerfacecolor="m")
48   plt.legend((marker1, marker2, marker3, marker4, marker5),
49              ('cwnd', 'ssthresh', 'congestion', 'recovered', 'rxt-timeout'),
50              loc=4)
51   axes = plt.gca()
52   axes.set_ylim([-20e4, max(cwndy) + 20e4])
53
54   # snd variables
55   plt.subplot(312)
56   plt.title("cc variables")
57   plt.plot(cwndx, d["space"], 'g-', markersize=1)
58   plt.plot(cwndx, d["flight"], 'b-', markersize=1)
59   plt.plot(cwndx, d["sacked"], 'm:', markersize=1)
60   plt.plot(cwndx, d["lost"], 'y:', markersize=1)
61   plt.plot(cwndx, d["cc-space"], 'k:', markersize=1)
62   plt.plot(cwndx, cwndy, 'ro', markersize=2)
63
64   plt.plot(congx, congy, 'y^', markersize=10, markerfacecolor="y")
65   plt.plot(rcvrdx, rcvrdy, 'c^', markersize=10, markerfacecolor="c")
66   plt.plot(rxttx, rxtty, 'm^', markersize=10, markerfacecolor="m")
67
68   #plt.plot(cwndx, d["snd_wnd"], 'ko', markersize=1)
69   plt.legend(("snd-space", "flight", "sacked", "lost", "cc-space", "cwnd",
70               "congestion", "recovered", "rxt-timeout"),
71              loc=1)
72
73   # rto/srrt/rttvar
74   plt.subplot(313)
75   plt.title("rtt")
76   plt.plot(cwndx, d["srtt"], 'g-')
77   plt.plot(cwndx, [x/1000 for x in d["mrtt-us"]], 'r-')
78   plt.plot(cwndx, d["rttvar"], 'b-')
79   plt.legend(["srtt", "mrtt-us", "rttvar"])
80   axes = plt.gca()
81   #plt.plot(cwndx, rto, 'r-')
82   #axes.set_ylim([0, int(max(rto[2:len(rto)])) + 50])
83
84   # show
85   plt.show()
86
87 def find_pattern(file_path,session_idx):
88     is_active_open = 1
89     listener_pattern = "l\[\d\]"
90     if (is_active_open):
91       initial_pattern = "\[\d\](\.\d+:\d+\->\.\d+:\d+)\s+open:\s"
92     else:
93       initial_pattern = "\[\d\](\.\d+:\d+\->\.\d+:\d+)\s"
94     idx = 0
95     f = open(file_path, 'r')
96     for line in f:
97       # skip listener lines (server)
98       if (re.search(listener_pattern, line) != None):
99         continue
100       match = re.search(initial_pattern, line)
101       if (match == None):
102         continue
103       if (idx < session_idx):
104         idx += 1
105         continue
106       filter_pattern = str(match.group(1)) + "\s+(.+)"
107       print ("pattern is %s" % filter_pattern)
108       f.close()
109       return filter_pattern
110     raise Exception ("Could not find initial pattern")
111
112 def compute_time(min, sec, msec):
113   return int(min)*60 + int(sec) + int(msec)/1000.0
114
115 def run(file_path, session_idx):
116     filter_sessions = 1
117     filter_pattern = ""
118
119     patterns = {
120       "time"      : "^\d+:(\d+):(\d+):(\d+):\d+",
121       "listener"  : "l\[\d\]",
122       "cc"        : "cwnd (\d+) flight (\d+) space (\d+) ssthresh (\d+) snd_wnd (\d+)",
123       "cc-snd"    : "cc_space (\d+) sacked (\d+) lost (\d+)",
124       "rtt"       : "rto (\d+) srtt (\d+) mrtt-us (\d+) rttvar (\d+)",
125       "rxtt"      : "rxt-timeout",
126       "congestion": "congestion",
127       "recovered" : "recovered",
128     }
129     d = {
130       "cwnd"        : [],
131       "space"       : [],
132       "flight"      : [],
133       "ssthresh"    : [],
134       "snd_wnd"     : [],
135       "cc-space"    : [],
136       "lost"        : [],
137       "sacked"      : [],
138       "rto"         : [],
139       "srtt"        : [],
140       "mrtt-us"     : [],
141       "rttvar"      : [],
142       "rxtTimeout"  : [],
143       "congestion"  : [],
144       "recovered"   : [],
145     }
146
147     if (filter_sessions):
148         filter_pattern = find_pattern(file_path, session_idx)
149     f = open(file_path, 'r')
150
151     stats_index = 0
152     start_time = 0
153
154     for line in f:
155         # skip listener lines (server)
156         if (re.search(patterns["listener"], line) != None):
157             continue
158         # filter sessions
159         if (filter_sessions):
160             match = re.search(filter_pattern, line)
161             if (match == None):
162                 continue
163
164         original_line = line
165         line = match.group(1)
166         match = re.search (patterns["time"], original_line)
167         if (match == None):
168           print "something went wrong! no time!"
169           continue
170         time = compute_time (match.group(1), match.group(2), match.group(3))
171         if (start_time == 0):
172           start_time = time
173
174         time = time - start_time
175         match = re.search(patterns["cc"], line)
176         if (match != None):
177           d["cwnd"].append(Point(time, int(match.group(1))))
178           d["flight"].append(int(match.group(2)))
179           d["space"].append(int(match.group(3)))
180           d["ssthresh"].append(int(match.group(4)))
181           d["snd_wnd"].append(int(match.group(5)))
182           stats_index += 1
183           continue
184         match = re.search(patterns["cc-snd"], line)
185         if (match != None):
186           d["cc-space"].append(int(match.group(1)))
187           d["sacked"].append(int(match.group(2)))
188           d["lost"].append(int(match.group(3)))
189         match = re.search(patterns["rtt"], line)
190         if (match != None):
191            d["rto"].append(int(match.group(1)))
192            d["srtt"].append(int(match.group(2)))
193            d["mrtt-us"].append(int(match.group(3)))
194            d["rttvar"].append(int(match.group(4)))
195         if (stats_index == 0):
196            continue
197         match = re.search(patterns["rxtt"], line)
198         if (match != None):
199           d["rxtTimeout"].append(Point(time, d["cwnd"][stats_index - 1].y + 1e4))
200           continue
201         match = re.search(patterns["congestion"], line)
202         if (match != None):
203           d["congestion"].append(Point(time, d["cwnd"][stats_index - 1].y - 1e4))
204           continue
205         match = re.search(patterns["recovered"], line)
206         if (match != None):
207           d["recovered"].append(Point(time, d["cwnd"][stats_index - 1].y))
208           continue
209
210     plot_data(d)
211
212 if __name__ == "__main__":
213     parser = argparse.ArgumentParser(description="Plot tcp cc logs")
214     parser.add_argument('-f', action='store', dest='file', required=True,
215                         help="elog file in txt format")
216     parser.add_argument('-s', action='store', dest='session_index', default=0,
217                         help="session index for which to plot cc logs" )
218     results = parser.parse_args()
219     run(results.file, int(results.session_index))