aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs427
1 files changed, 427 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
new file mode 100644
index 0000000..3c82a78
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
@@ -0,0 +1,427 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Tests.Common;
35
36namespace OpenSim.Region.ClientStack.LindenUDP.Tests
37{
38 [TestFixture]
39 public class ThrottleTests : OpenSimTestCase
40 {
41 [TestFixtureSetUp]
42 public void FixtureInit()
43 {
44 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
45 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
46 }
47
48 [TestFixtureTearDown]
49 public void TearDown()
50 {
51 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
52 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
53 // tests really shouldn't).
54 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
55 }
56
57 [Test]
58 public void TestSetRequestDripRate()
59 {
60 TestHelpers.InMethod();
61
62 TokenBucket tb = new TokenBucket("tb", null, 5000, 0);
63 AssertRates(tb, 5000, 0, 5000, 0);
64
65 tb.RequestedDripRate = 4000;
66 AssertRates(tb, 4000, 0, 4000, 0);
67
68 tb.RequestedDripRate = 6000;
69 AssertRates(tb, 6000, 0, 6000, 0);
70 }
71
72 [Test]
73 public void TestSetRequestDripRateWithMax()
74 {
75 TestHelpers.InMethod();
76
77 TokenBucket tb = new TokenBucket("tb", null, 5000, 10000);
78 AssertRates(tb, 5000, 0, 5000, 10000);
79
80 tb.RequestedDripRate = 4000;
81 AssertRates(tb, 4000, 0, 4000, 10000);
82
83 tb.RequestedDripRate = 6000;
84 AssertRates(tb, 6000, 0, 6000, 10000);
85
86 tb.RequestedDripRate = 12000;
87 AssertRates(tb, 10000, 0, 10000, 10000);
88 }
89
90 [Test]
91 public void TestSetRequestDripRateWithChildren()
92 {
93 TestHelpers.InMethod();
94
95 TokenBucket tbParent = new TokenBucket("tbParent", null, 0, 0);
96 TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000, 0);
97 TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000, 0);
98
99 AssertRates(tbParent, 8000, 8000, 8000, 0);
100 AssertRates(tbChild1, 3000, 0, 3000, 0);
101 AssertRates(tbChild2, 5000, 0, 5000, 0);
102
103 // Test: Setting a parent request greater than total children requests.
104 tbParent.RequestedDripRate = 10000;
105
106 AssertRates(tbParent, 10000, 8000, 8000, 0);
107 AssertRates(tbChild1, 3000, 0, 3000, 0);
108 AssertRates(tbChild2, 5000, 0, 5000, 0);
109
110 // Test: Setting a parent request lower than total children requests.
111 tbParent.RequestedDripRate = 6000;
112
113 AssertRates(tbParent, 6000, 8000, 6000, 0);
114 AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0);
115 AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0);
116 }
117
118 private void AssertRates(
119 TokenBucket tb, double requestedDripRate, double totalDripRequest, double dripRate, double maxDripRate)
120 {
121 Assert.AreEqual((int)requestedDripRate, tb.RequestedDripRate, "Requested drip rate");
122 Assert.AreEqual((int)totalDripRequest, tb.TotalDripRequest, "Total drip request");
123 Assert.AreEqual((int)dripRate, tb.DripRate, "Drip rate");
124 Assert.AreEqual((int)maxDripRate, tb.MaxDripRate, "Max drip rate");
125 }
126
127 [Test]
128 public void TestClientThrottleSetNoLimit()
129 {
130 TestHelpers.InMethod();
131// TestHelpers.EnableLogging();
132
133 Scene scene = new SceneHelpers().SetupScene();
134 TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
135
136 ScenePresence sp
137 = ClientStackHelpers.AddChildClient(
138 scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
139
140 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
141
142 udpServer.Throttle.DebugLevel = 1;
143 udpClient.ThrottleDebugLevel = 1;
144
145 int resendBytes = 1000;
146 int landBytes = 2000;
147 int windBytes = 3000;
148 int cloudBytes = 4000;
149 int taskBytes = 5000;
150 int textureBytes = 6000;
151 int assetBytes = 7000;
152
153 SetThrottles(
154 udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
155
156 // We expect this to be lower because of the minimum bound set by MTU
157 int totalBytes = LLUDPServer.MTU + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
158
159 AssertThrottles(
160 udpClient,
161 LLUDPServer.MTU, landBytes, windBytes, cloudBytes, taskBytes,
162 textureBytes, assetBytes, totalBytes, 0, 0);
163 }
164
165 [Test]
166 public void TestClientThrottleAdaptiveNoLimit()
167 {
168 TestHelpers.InMethod();
169// TestHelpers.EnableLogging();
170
171 Scene scene = new SceneHelpers().SetupScene();
172
173 IniConfigSource ics = new IniConfigSource();
174 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
175 config.Set("enable_adaptive_throttles", true);
176 config.Set("adaptive_throttle_min_bps", 32000);
177
178 TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene, ics);
179
180 ScenePresence sp
181 = ClientStackHelpers.AddChildClient(
182 scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
183
184 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
185
186 udpServer.Throttle.DebugLevel = 1;
187 udpClient.ThrottleDebugLevel = 1;
188
189 // Total is 275000
190 int resendBytes = 5000; // this is set low to test the minimum throttle override
191 int landBytes = 20000;
192 int windBytes = 30000;
193 int cloudBytes = 40000;
194 int taskBytes = 50000;
195 int textureBytes = 60000;
196 int assetBytes = 70000;
197 int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
198
199 SetThrottles(
200 udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
201
202 // Ratio of current adaptive drip rate to requested bytes, minimum rate is 32000
203 double commitRatio = 32000.0 / totalBytes;
204
205 AssertThrottles(
206 udpClient,
207 LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
208 textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
209
210 // Test an increase in target throttle, ack of 20 packets adds 20 * LLUDPServer.MTU bytes
211 // to the throttle, recompute commitratio from those numbers
212 udpClient.FlowThrottle.AcknowledgePackets(20);
213 commitRatio = (32000.0 + 20.0 * LLUDPServer.MTU) / totalBytes;
214
215 AssertThrottles(
216 udpClient,
217 LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
218 textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
219
220 // Test a decrease in target throttle, adaptive throttle should cut the rate by 50% with a floor
221 // set by the minimum adaptive rate
222 udpClient.FlowThrottle.ExpirePackets(1);
223 commitRatio = (32000.0 + (20.0 * LLUDPServer.MTU)/Math.Pow(2,1)) / totalBytes;
224
225 AssertThrottles(
226 udpClient,
227 LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
228 textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
229 }
230
231 /// <summary>
232 /// Test throttle setttings where max client throttle has been limited server side.
233 /// </summary>
234 [Test]
235 public void TestSingleClientThrottleRegionLimited()
236 {
237 TestHelpers.InMethod();
238 // TestHelpers.EnableLogging();
239
240 int resendBytes = 6000;
241 int landBytes = 8000;
242 int windBytes = 10000;
243 int cloudBytes = 12000;
244 int taskBytes = 14000;
245 int textureBytes = 16000;
246 int assetBytes = 18000;
247 int totalBytes
248 = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2);
249
250 Scene scene = new SceneHelpers().SetupScene();
251 TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
252 udpServer.Throttle.RequestedDripRate = totalBytes;
253
254 ScenePresence sp1
255 = ClientStackHelpers.AddChildClient(
256 scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
257
258 LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient;
259
260 SetThrottles(
261 udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
262
263 AssertThrottles(
264 udpClient1,
265 resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2,
266 textureBytes / 2, assetBytes / 2, totalBytes, 0, 0);
267
268 // Test: Now add another client
269 ScenePresence sp2
270 = ClientStackHelpers.AddChildClient(
271 scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457);
272
273 LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient;
274 // udpClient.ThrottleDebugLevel = 1;
275
276 SetThrottles(
277 udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
278
279 AssertThrottles(
280 udpClient1,
281 resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4,
282 textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0);
283
284 AssertThrottles(
285 udpClient2,
286 resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4,
287 textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0);
288 }
289
290 /// <summary>
291 /// Test throttle setttings where max client throttle has been limited server side.
292 /// </summary>
293 [Test]
294 public void TestClientThrottlePerClientLimited()
295 {
296 TestHelpers.InMethod();
297 // TestHelpers.EnableLogging();
298
299 int resendBytes = 4000;
300 int landBytes = 6000;
301 int windBytes = 8000;
302 int cloudBytes = 10000;
303 int taskBytes = 12000;
304 int textureBytes = 14000;
305 int assetBytes = 16000;
306 int totalBytes
307 = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2);
308
309 Scene scene = new SceneHelpers().SetupScene();
310 TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
311 udpServer.ThrottleRates.Total = totalBytes;
312
313 ScenePresence sp
314 = ClientStackHelpers.AddChildClient(
315 scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
316
317 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
318 // udpClient.ThrottleDebugLevel = 1;
319
320 SetThrottles(
321 udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
322
323 AssertThrottles(
324 udpClient,
325 resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2,
326 textureBytes / 2, assetBytes / 2, totalBytes, 0, totalBytes);
327 }
328
329 [Test]
330 public void TestClientThrottlePerClientAndRegionLimited()
331 {
332 TestHelpers.InMethod();
333 //TestHelpers.EnableLogging();
334
335 int resendBytes = 4000;
336 int landBytes = 6000;
337 int windBytes = 8000;
338 int cloudBytes = 10000;
339 int taskBytes = 12000;
340 int textureBytes = 14000;
341 int assetBytes = 16000;
342
343 // current total 70000
344 int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
345
346 Scene scene = new SceneHelpers().SetupScene();
347 TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
348 udpServer.ThrottleRates.Total = (int)(totalBytes * 1.1);
349 udpServer.Throttle.RequestedDripRate = (int)(totalBytes * 1.5);
350
351 ScenePresence sp1
352 = ClientStackHelpers.AddChildClient(
353 scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
354
355 LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient;
356 udpClient1.ThrottleDebugLevel = 1;
357
358 SetThrottles(
359 udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
360
361 AssertThrottles(
362 udpClient1,
363 resendBytes, landBytes, windBytes, cloudBytes, taskBytes,
364 textureBytes, assetBytes, totalBytes, 0, totalBytes * 1.1);
365
366 // Now add another client
367 ScenePresence sp2
368 = ClientStackHelpers.AddChildClient(
369 scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457);
370
371 LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient;
372 udpClient2.ThrottleDebugLevel = 1;
373
374 SetThrottles(
375 udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
376
377 AssertThrottles(
378 udpClient1,
379 resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75,
380 textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1);
381
382 AssertThrottles(
383 udpClient2,
384 resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75,
385 textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1);
386 }
387
388 private void AssertThrottles(
389 LLUDPClient udpClient,
390 double resendBytes, double landBytes, double windBytes, double cloudBytes, double taskBytes, double textureBytes, double assetBytes,
391 double totalBytes, double targetBytes, double maxBytes)
392 {
393 ClientInfo ci = udpClient.GetClientInfo();
394
395// Console.WriteLine(
396// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}",
397// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle);
398
399 Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend");
400 Assert.AreEqual((int)landBytes, ci.landThrottle, "Land");
401 Assert.AreEqual((int)windBytes, ci.windThrottle, "Wind");
402 Assert.AreEqual((int)cloudBytes, ci.cloudThrottle, "Cloud");
403 Assert.AreEqual((int)taskBytes, ci.taskThrottle, "Task");
404 Assert.AreEqual((int)textureBytes, ci.textureThrottle, "Texture");
405 Assert.AreEqual((int)assetBytes, ci.assetThrottle, "Asset");
406 Assert.AreEqual((int)totalBytes, ci.totalThrottle, "Total");
407 Assert.AreEqual((int)targetBytes, ci.targetThrottle, "Target");
408 Assert.AreEqual((int)maxBytes, ci.maxThrottle, "Max");
409 }
410
411 private void SetThrottles(
412 LLUDPClient udpClient, int resendBytes, int landBytes, int windBytes, int cloudBytes, int taskBytes, int textureBytes, int assetBytes)
413 {
414 byte[] throttles = new byte[28];
415
416 Array.Copy(BitConverter.GetBytes((float)resendBytes * 8), 0, throttles, 0, 4);
417 Array.Copy(BitConverter.GetBytes((float)landBytes * 8), 0, throttles, 4, 4);
418 Array.Copy(BitConverter.GetBytes((float)windBytes * 8), 0, throttles, 8, 4);
419 Array.Copy(BitConverter.GetBytes((float)cloudBytes * 8), 0, throttles, 12, 4);
420 Array.Copy(BitConverter.GetBytes((float)taskBytes * 8), 0, throttles, 16, 4);
421 Array.Copy(BitConverter.GetBytes((float)textureBytes * 8), 0, throttles, 20, 4);
422 Array.Copy(BitConverter.GetBytes((float)assetBytes * 8), 0, throttles, 24, 4);
423
424 udpClient.SetThrottles(throttles);
425 }
426 }
427} \ No newline at end of file