scriptroute 0.4.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,145 @@
1
+ module Scriptroute
2
+ module Tulip
3
+
4
+ class LossTrain
5
+ attr_reader :train;
6
+
7
+ def initialize(destination, intra_train, type, ttl)
8
+ @destination, @intra_train, @type, @ttl = destination, intra_train, type, ttl;
9
+ #(dsts, numpackets, intratrain, types, ttls, psizes, numtrains, intertrain)
10
+ @train = Train2.new([destination], 3, @intra_train, [type], [ttl], [-1, 1000, -1], 1, 0);
11
+ end
12
+
13
+ def isLossy?
14
+ return (@train.num_losses[0] > 0);
15
+ end
16
+
17
+ ##todo: principled treatment of pcapping
18
+ def wasPcapped?
19
+ @train.packets.each_index { |j|
20
+ @train.packets[0].each_index { |k|
21
+ pr = @train.packets[j][k];
22
+ return true if (!pr or !pr.probe or !pr.probe.time);
23
+ }
24
+ }
25
+ return false;
26
+ end
27
+
28
+ def to_s
29
+ str = "";
30
+ str += "losstrain #{@destination} #{@intra_train} #{@type} #{@ttl}\n";
31
+ @train.packets.each_index { |j|
32
+ @train.packets[0].each_index { |k|
33
+ pr = @train.packets[j][k];
34
+ if (pr and pr.probe and pr.probe.time) then
35
+ stime, sid = pr.probe.time.to_f * 1000, pr.probe.packet.ip_id;
36
+ rtime = (pr.response) ? pr.response.time.to_f * 1000 : -1;
37
+ rid = (pr.response) ? pr.response.packet.ip_id : -1;
38
+ src = (pr.response)? pr.response.packet.ip_src : -1;
39
+ str += "#{src} %.3f +%.3fms %d %d\n" %[stime, rtime-stime, rid, sid];
40
+ else
41
+ str += "pcap overload\n";
42
+ end
43
+ }
44
+ }
45
+ return str;
46
+ end
47
+
48
+ end
49
+
50
+ class LossDoctor
51
+
52
+ def analyze (hopDetails)
53
+
54
+ hopDetails.each_index { |hop|
55
+ next if (!hopDetails[hop]);
56
+ details = hopDetails[hop];
57
+
58
+ valid = @total[hop] - @undesiredLosses[hop];
59
+ # printf("%d. %s ", $global_tpath.path[hop].hop, details[4]);
60
+ printf("%s ", $global_tpath.path[hop]);
61
+ printf("(ejected) ") if (@ejected.has_key?(hop));
62
+ rt = @total[hop] - @undesiredLosses[hop] - @noLosses[hop];
63
+ printf("rt=%.3f (%d/%d) ",(valid==0)? 0 : rt.to_f/valid, rt, valid);
64
+ if (details[3]) then
65
+ printf("fw=%.3f (%d/%d) ", @forwardLosses[hop].to_f/valid, @forwardLosses[hop], valid);
66
+ consec = @noLosses[hop] - @reorderedResponses[hop];
67
+ consecR = (consec==0)? 0 : @consecutiveIPIDs[hop].to_f/consec;
68
+ printf("co=%.3f (%d/%d) ", consecR, @consecutiveIPIDs[hop], consec);
69
+ printf("ro=%.3f (%d/%d)", @reorderedResponses[hop].to_f/@noLosses[hop], @reorderedResponses[hop], @noLosses[hop]);
70
+ end
71
+ puts "";
72
+ }
73
+ end
74
+
75
+ def initialize (hopDetails)
76
+ @total = Hash.new(0);
77
+ @noLosses = Hash.new(0);
78
+ @undesiredLosses = Hash.new(0);
79
+ @forwardLosses = Hash.new(0);
80
+ @reorderedResponses = Hash.new(0);
81
+ @consecutiveIPIDs = Hash.new(0);
82
+ @ejected = Hash.new(0);
83
+
84
+
85
+ (0..$count-1).each { |num|
86
+ startTime = Time.now;
87
+ hopDetails.each_index { |i|
88
+
89
+ next if (!hopDetails[i] or @ejected.has_key?(i));
90
+ details = hopDetails[i];
91
+
92
+ #(destination, intra_train, type, ttl)
93
+ train = LossTrain.new(details[0], $spread/1000.0, details[2], details[1]);
94
+ puts "#{train}\n" if ($verbose>=10);
95
+
96
+ @total[i] += 1;
97
+ pkts = train.train.packets[0];
98
+
99
+ next if (train.wasPcapped?);
100
+
101
+ if (!train.isLossy?) then
102
+ @noLosses[i] += 1;
103
+ if (details[3]) then
104
+ ids = pkts.map { |p| p.response.packet.ip_id };
105
+ if (ids[1] < ids[0] or ids[2] < ids[1]) then
106
+ @reorderedResponses[i] += 1 if (ids[1] != 0); #don't count routers that return 0 for big probes
107
+ end
108
+ if (ids[0] + 1 == ids[1] and ids[1] + 1 == ids[2]) then
109
+ @consecutiveIPIDs[i] += 1;
110
+ end
111
+ end
112
+ else
113
+ if (!pkts[0].response or !pkts[2].response) then
114
+ @undesiredLosses[i] += 1;
115
+ else
116
+ id0 = pkts[0].response.packet.ip_id;
117
+ id2 = pkts[2].response.packet.ip_id;
118
+ if (id0 == id2 - 1) then
119
+ @forwardLosses[i] += 1;
120
+ end
121
+ end
122
+ if (@noLosses[i] <= 0.25*@total[i] and @total[i] >= 10) then
123
+ @ejected[i] = 1;
124
+ end
125
+ end
126
+ }
127
+
128
+ if ($printFrequency > 0 and (num+1) % $printFrequency == 0 and num != $count-1 ) then
129
+ puts " ---- after #{num+1} measurements ----";
130
+ analyze(hopDetails);
131
+ end
132
+
133
+ sleepTime = startTime + $lag/1000.0 - Time.now;
134
+ if (sleepTime > 0) then Kernel.sleep(sleepTime); end
135
+ }
136
+
137
+ puts " ---- after #{$count} measurements ----";
138
+ analyze(hopDetails);
139
+
140
+ end
141
+ end
142
+
143
+
144
+ end
145
+ end
@@ -0,0 +1,248 @@
1
+ module Scriptroute
2
+ module Tulip
3
+
4
+
5
+ class QueueTrain
6
+ attr_reader :train;
7
+
8
+ def initialize(dst, type, ttl)
9
+ #(dsts, numpackets, resolution, types, ttls, shuffle=false)
10
+ #@train = Train.new([dst], 2, 0, [type], [ttl]);
11
+ @train = Train.new([dst], 1, 0, [type], [ttl]);
12
+ end
13
+
14
+ def isLossy?
15
+ ##losing one of the two timestamps all the time is ok.
16
+ return (@train.num_losses[0] > 1);
17
+ end
18
+
19
+ # def to_s
20
+ # return @train.to_s;
21
+ # end
22
+
23
+ def to_s
24
+ str = "queuetrain: #{@train.dsts} (#{@train.types})\n";
25
+ @train.packets[0].each_index { |i|
26
+ (@train.dsts).each_index { |j|
27
+ pr = @train.packets[j][i];
28
+ stime = pr.probe.time.to_f * 1000;
29
+ rtt = (pr.probe and pr.response) ? (pr.response.time - pr.probe.time) * 1000 : -1;
30
+ str += "#{@train.dsts[j]} %.3fms %.3f " %[rtt, stime];
31
+ if (@train.types[j] == "tstamp") then
32
+ rem_time = (pr.response)? pr.response.packet.icmp_ttime : 0;
33
+ str += "#{rem_time}";
34
+ end
35
+ }
36
+ str += "\n";
37
+ }
38
+ return str;
39
+ end
40
+
41
+ end
42
+
43
+ def convertByteOrder(wrong)
44
+ right = Array.new();
45
+ right[0], right[1], right[2], right[3] = wrong & 255,
46
+ (wrong & (255 << 8)) >> 8,
47
+ (wrong & (255 << 16)) >> 16,
48
+ (wrong & (255 << 24)) >> 24;
49
+ out = ( (right[0] << 24) + (right[1] << 16) + (right[2] << 8) + right[3]);
50
+ #puts "#{wrong} #{out} #{right.join(" ")}\n";
51
+ return out;
52
+ end
53
+
54
+ def fixByteOrder (stamps)
55
+ if (stamps.length > 4 and
56
+ (stamps[0][1] > stamps[1][1] or
57
+ stamps[1][1] > stamps[2][1] or
58
+ stamps[2][1] > stamps[3][1] or
59
+ stamps[3][1] > stamps[4][1]
60
+ )
61
+ ) then
62
+ triplets = Array.new();
63
+ stamps.each_index { |i|
64
+ triplets[i] = Array.new();
65
+ triplets[i][0] = stamps[i][0];
66
+ triplets[i][1] = convertByteOrder(stamps[i][1]);
67
+ triplets[i][2] = stamps[i][2]; ## a better way to do this would be to insert in converted byte order
68
+ }
69
+ return triplets;
70
+ end
71
+ return stamps;
72
+ end
73
+
74
+ def computeRTMed (stamps)
75
+ rtts = Array.new();
76
+ stamps.each { |stamp|
77
+ rtts.push(stamp[2] - stamp[0]);
78
+ }
79
+ rtts.sort!;
80
+ if (rtts.length > 0)
81
+ medianDiff = rtts[rtts.length/2] - rtts[0];
82
+ return [medianDiff, rtts.first, rtts.last];
83
+ else
84
+ return -100;
85
+ end
86
+ end
87
+
88
+ def computeFWMedCing (triplets)
89
+ # triplets = Array.new();
90
+ oldsend, oldrcv = 0,0;
91
+ # stamps.each { |stamp|
92
+ # triplets.push(stamp);
93
+ # }
94
+
95
+ ENV['datalinepattern'] ="newexp";
96
+ ENV['fieldseparator'] = ":";
97
+ ENV['hostfieldnum'] = "3";
98
+ ENV['sentfieldnum'] = "6";
99
+ ENV['receivedfieldnum'] = "7";
100
+ ENV['bouncedfieldnum'] = "9";
101
+ ENV['segmentsecs'] = "12";
102
+ ENV['writefixeddir'] = "./";
103
+ ENV['sourceskew'] = "-";
104
+ ENV['target'] = "1.1.1.1";
105
+ ENV['showquality'] = "1";
106
+
107
+ pid = Process.pid;
108
+ tmp = File.new("/tmp/fixLC.#{pid}", "w");
109
+
110
+ if (triplets.length == 0) then
111
+ return -100;
112
+ end
113
+
114
+ base = triplets[0][0];
115
+ triplets.each_index { |j|
116
+ tup = triplets[j];
117
+ tmp.puts "0.000:newexp:1.1.1.1:%u:0:%u:%u:0:%u" %[j, tup[0] - base, tup[1], tup[2] - base];
118
+ }
119
+ tmp.close();
120
+ cmd = sprintf("#{FIXCLOCK} /tmp/fixLC.#{pid}");
121
+ output = `#{cmd}`.split("\n");
122
+ match = nil;
123
+ quality = [nil, nil];
124
+ output.each { |o|
125
+ if ( o =~ "inferred stdroundtrip" ) then
126
+ words = o.split;
127
+ quality = [words[4], words[6]];
128
+ end
129
+ }
130
+
131
+ otts = Array.new();
132
+ rejected = 0;
133
+ tmp = File.new("./fixLC.#{pid}.fix");
134
+ tmp.each { |line|
135
+ words = line.split(":");
136
+ snd,rem,zero,rcv = words[5..8].map { |i| i.to_i; }
137
+ # if (snd <= rem and rem <= rcv) then
138
+ otts.push(rem - snd);
139
+ # else
140
+ # rejected += 1;
141
+ # end
142
+ }
143
+ tmp.close();
144
+ File.delete("/tmp/fixLC.#{pid}", "./fixLC.#{pid}.fix", "./fixLC.#{pid}.rej");
145
+
146
+ #puts "conglib-warning: rejected #{rejected} cing corrections\n" if (rejected > 0);
147
+
148
+ otts.sort!;
149
+ #STDERR.puts "WARNING: too few ott samples: #{otts.length}" if (otts.length < 5);
150
+
151
+ medianDiff = (otts.length > 0)? (otts[otts.length/2] - otts[0]) : -100;
152
+ #puts "otts (#{otts.length}, #{medianDiff}): #{otts.join(" ")}";
153
+ return [[medianDiff, otts.last], quality];
154
+ end
155
+
156
+
157
+ class QueuingDoctor
158
+
159
+ def validOTT (ott, rtt)
160
+ return false if (ott < 0);
161
+ #return false if (ott > 3 and rtt < 1);
162
+ #return false if (ott > rtt/2);
163
+ return true;
164
+ end
165
+
166
+ def analyze (hopDetails)
167
+
168
+ hopDetails.each_index { |hop|
169
+ next if (!hopDetails[hop]);
170
+ details = hopDetails[hop];
171
+
172
+ valid = @total[hop] - @ratelimited[hop];
173
+ # printf("%d. %s ", $global_tpath.path[hop].hop, details[4]);
174
+ printf("%s ", $global_tpath.path[hop]);
175
+ printf("(ejected) ") if (@ejected.has_key?(hop));
176
+ round = computeRTMed(@stamps[hop]);
177
+ printf("rt: median=%.3f min=%.3f max=%.3f ", round[0]+round[1], round[1], round[2]);
178
+ if (details[3]) then
179
+ triplets = fixByteOrder(@stamps[hop]);
180
+ cing = computeFWMedCing(triplets);
181
+ q = (cing[1][1].to_f==0)? 1 : cing[1][0].to_f/cing[1][1].to_f;
182
+ if (validOTT(cing[0][0], round[0])) then
183
+ printf("fw: median=%.3f max=%s quality=%.3f (%s/%s)", cing[0][0], cing[0][1], q, cing[1][0], cing[1][1]);
184
+ else
185
+ printf("fw: median=-1 max=-1 quality=-1");
186
+ end
187
+ end
188
+ puts "";
189
+ }
190
+ end
191
+
192
+ def initialize (hopDetails)
193
+
194
+ @total = Hash.new(0);
195
+ @ratelimited = Hash.new(0)
196
+ @stamps = Hash.new();
197
+ hopDetails.each_index { |i| @stamps[i] = Array.new() if (hopDetails[i]);}
198
+ @ejected = Hash.new();
199
+
200
+ ##todo: implement the correlation thingy
201
+ @pairs = Hash.new();
202
+
203
+ (0..$count-1).each { |num|
204
+ startTime = Time.now;
205
+ hopDetails.each_index { |i|
206
+
207
+ next if (!hopDetails[i] or @ejected.has_key?(i));
208
+ details = hopDetails[i];
209
+
210
+ #(dst, types, ttl)
211
+
212
+ #puts "before train = %.3f" % [Time.now.to_f*1000];
213
+ train = QueueTrain.new(details[0], details[2], details[1]);
214
+ #puts "after train = %.3f" % [Time.now.to_f*1000];
215
+
216
+ puts "#{train}\n" if ($verbose>=10);
217
+
218
+ @total[i] += 1;
219
+ if (train.isLossy?) then
220
+ @ratelimited[i] += 1;
221
+ @ejected[i] = 1 if (@ratelimited[i] >= 0.5*@total[i] and @total[i] >= 10);
222
+ else
223
+ p = train.train.packets[0][0];
224
+ if (p and p.probe and p.response and p.probe.time and p.response.time) then
225
+ @stamps[i].push([p.probe.time.to_f * 1000.0, p.response.packet.icmp_ttime, p.response.time.to_f*1000.0]);
226
+ else
227
+ @total[i] -= 1;
228
+ end
229
+ end
230
+ }
231
+
232
+ if ($printFrequency > 0 and (num+1) % $printFrequency == 0 and num != $count-1) then
233
+ puts " ---- after #{num+1} measurements ----";
234
+ analyze(hopDetails);
235
+ end
236
+
237
+ sleepTime = startTime + $lag/1000.0 - Time.now;
238
+ #puts "sleep = #{sleepTime} %.3f" % [Time.now.to_f*1000];
239
+ if (sleepTime > 0 and num != $count-1) then Kernel.sleep(sleepTime); end
240
+ }
241
+
242
+ puts " ---- after #{$count} measurements ----";
243
+ analyze(hopDetails);
244
+ end
245
+ end
246
+
247
+ end
248
+ end
@@ -0,0 +1,129 @@
1
+ module Scriptroute
2
+ module Tulip
3
+
4
+
5
+ class ReordTrain
6
+ attr_reader :destination,:intra_train, :type, :ttl, :train;
7
+
8
+ def initialize(destination, intra_train, type, ttl)
9
+ @destination, @intra_train, @type, @ttl =
10
+ destination, intra_train, type, ttl;
11
+
12
+ #(dsts, numpackets, resolution, types, ttls, shuffle=false)
13
+ @train = Train.new([@destination], 2, @intra_train, [@type], [@ttl]);
14
+ end
15
+
16
+ def isLossy?
17
+ return (@train.num_losses[0] > 0);
18
+ end
19
+
20
+ def isRTro?
21
+ return false if (isLossy?);
22
+ rt1, rt2 = [0,1].map { |v| @train.packets[0][v].response.time; }
23
+ (rt1 > rt2)? true : false;
24
+ end
25
+
26
+ def isFWro?
27
+ return false if (isLossy?);
28
+ id1, id2 = [0,1].map { |v| @train.packets[0][v].response.packet.ip_id; }
29
+ (id1 > id2)? true : false;
30
+ end
31
+
32
+ def wasPcapped?
33
+ @train.packets[0].each_index { |k|
34
+ pr = @train.packets[0][k];
35
+ return true if (!pr or !pr.probe or !pr.probe.time)
36
+ }
37
+ return false;
38
+ end
39
+
40
+ def to_s
41
+ str = "";
42
+ str += "reordtrain %s %s %s %s\n" % [@destination, @ttl, @type, @intra_train];
43
+ @train.packets[0].each_index { |k|
44
+ pr = @train.packets[0][k];
45
+ stime, sid = pr.probe.time.to_f * 1000, pr.probe.packet.ip_id;
46
+ rtime = (pr.response) ? pr.response.time.to_f * 1000 : -1;
47
+ sid = pr.probe.packet.ip_id;
48
+ rid = (pr.response) ? pr.response.packet.ip_id : -1;
49
+ src = (pr.response)? pr.response.packet.ip_src : -1;
50
+ str += "#{src} %.3f +%.3fms %d %d" %[stime, rtime-stime, rid, sid];
51
+ str += "\n";
52
+ }
53
+ return str;
54
+ end
55
+ end
56
+
57
+
58
+ class ReorderingDoctor
59
+
60
+ def analyze (hopDetails)
61
+
62
+ hopDetails.each_index { |hop|
63
+ next if (!hopDetails[hop]);
64
+ details = hopDetails[hop];
65
+
66
+ valid = 1.0*@total[hop] - @ratelimited[hop];
67
+ # printf("%d. %s ", $global_tpath.path[hop].hop, details[4]);
68
+ printf("%s ", $global_tpath.path[hop]);
69
+ # printf("%d. %s %s ", $global_tpath.path[hop].hop, IPSocket.getname($global_tpath.path[hop].hop), details[4]);
70
+ printf("(ejected) ") if (@ejected.has_key?(hop));
71
+ printf("rt=%.3f (%d/%d) ", @rtreord[hop].to_f/valid, @rtreord[hop], valid);
72
+ if (details[3]) then
73
+ printf("fw=%.3f (%d/%d)\n", @fwreord[hop].to_f/valid, @fwreord[hop], valid)
74
+ else
75
+ printf("\n")
76
+ end
77
+ }
78
+ end
79
+
80
+ def initialize (hopDetails)
81
+
82
+ @total = Hash.new(0);
83
+ @fwreord = Hash.new(0);
84
+ @rtreord = Hash.new(0);
85
+ @ratelimited = Hash.new(0)
86
+ @ejected = Hash.new(0);
87
+
88
+ (0..$count-1).each { |num|
89
+ startTime = Time.now;
90
+ hopDetails.each_index { |i|
91
+
92
+ next if (!hopDetails[i] or @ejected.has_key?(i));
93
+ details = hopDetails[i];
94
+
95
+ #(destination, intra_train, type, ttl)
96
+ train = ReordTrain.new(details[0], $spread/1000.0, details[2], details[1]);
97
+ puts "#{train}\n" if ($verbose>=10);
98
+
99
+ next if (train.wasPcapped?);
100
+
101
+ @total[i] += 1;
102
+ if (train.isLossy?) then
103
+ @ratelimited[i] += 1;
104
+ if ($skipRTrtrs and @ratelimited[i] >= 0.5*@total[i] and @total[i] >= 10) then
105
+ @ejected[i] = 1;
106
+ end
107
+ else
108
+ @fwreord[i] += (train.isFWro?)? 1 : 0
109
+ @rtreord[i] += (train.isRTro?)? 1 : 0
110
+ end
111
+ }
112
+
113
+ if ($printFrequency > 0 and (num+1) % $printFrequency == 0 and num != $count-1) then
114
+ puts " ---- after #{num+1} measurements ----";
115
+ analyze(hopDetails);
116
+ end
117
+
118
+ sleepTime = startTime + $lag/1000.0 - Time.now;
119
+ if (sleepTime > 0) then Kernel.sleep(sleepTime); end
120
+ }
121
+
122
+ puts " ---- after #{$count} measurements ----";
123
+ analyze(hopDetails);
124
+
125
+ end
126
+ end
127
+
128
+ end
129
+ end