OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // The tests in this file attempt to verify the following through simulation: | 5 // The tests in this file attempt to verify the following through simulation: |
6 // a) That a server experiencing overload will actually benefit from the | 6 // a) That a server experiencing overload will actually benefit from the |
7 // anti-DDoS throttling logic, i.e. that its traffic spike will subside | 7 // anti-DDoS throttling logic, i.e. that its traffic spike will subside |
8 // and be distributed over a longer period of time; | 8 // and be distributed over a longer period of time; |
9 // b) That "well-behaved" clients of a server under DDoS attack actually | 9 // b) That "well-behaved" clients of a server under DDoS attack actually |
10 // benefit from the anti-DDoS throttling logic; and | 10 // benefit from the anti-DDoS throttling logic; and |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 requests_per_tick_.push_back(num_current_tick_queries_); | 152 requests_per_tick_.push_back(num_current_tick_queries_); |
153 num_current_tick_queries_ = 0; | 153 num_current_tick_queries_ = 0; |
154 } | 154 } |
155 | 155 |
156 // This is called by Requester. It returns the response code from | 156 // This is called by Requester. It returns the response code from |
157 // the server. | 157 // the server. |
158 int HandleRequest() { | 158 int HandleRequest() { |
159 ++num_current_tick_queries_; | 159 ++num_current_tick_queries_; |
160 if (!start_downtime_.is_null() && | 160 if (!start_downtime_.is_null() && |
161 start_downtime_ < now_ && now_ < end_downtime_) { | 161 start_downtime_ < now_ && now_ < end_downtime_) { |
162 // TODO(joi): For the simulation measuring the increase in perceived | 162 // For the simulation measuring the increase in perceived |
163 // downtime, it might be interesting to count separately the | 163 // downtime, it might be interesting to count separately the |
164 // queries seen by the server (assuming a front-end reverse proxy | 164 // queries seen by the server (assuming a front-end reverse proxy |
165 // is what actually serves up the 503s in this case) so that we could | 165 // is what actually serves up the 503s in this case) so that we could |
166 // visualize the traffic spike seen by the server when it comes up, | 166 // visualize the traffic spike seen by the server when it comes up, |
167 // which would in many situations be ameliorated by the anti-DDoS | 167 // which would in many situations be ameliorated by the anti-DDoS |
168 // throttling. | 168 // throttling. |
169 return 503; | 169 return 503; |
170 } | 170 } |
171 | 171 |
172 if ((num_overloaded_ticks_remaining_ > 0 || | 172 if ((num_overloaded_ticks_remaining_ > 0 || |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 const double request_drop_ratio_; // Ratio of requests to 503 when failing. | 278 const double request_drop_ratio_; // Ratio of requests to 503 when failing. |
279 int num_overloaded_ticks_remaining_; | 279 int num_overloaded_ticks_remaining_; |
280 int num_current_tick_queries_; | 280 int num_current_tick_queries_; |
281 int num_overloaded_ticks_; | 281 int num_overloaded_ticks_; |
282 int max_experienced_queries_per_tick_; | 282 int max_experienced_queries_per_tick_; |
283 std::vector<int> requests_per_tick_; | 283 std::vector<int> requests_per_tick_; |
284 | 284 |
285 DISALLOW_COPY_AND_ASSIGN(Server); | 285 DISALLOW_COPY_AND_ASSIGN(Server); |
286 }; | 286 }; |
287 | 287 |
288 class TestingURLRequestThrottlerManager : public URLRequestThrottlerManager { | |
289 public: | |
290 TestingURLRequestThrottlerManager() : URLRequestThrottlerManager() { | |
291 } | |
292 }; | |
293 | |
294 // Mock throttler entry used by Requester class. | 288 // Mock throttler entry used by Requester class. |
295 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { | 289 class MockURLRequestThrottlerEntry : public URLRequestThrottlerEntry { |
296 public: | 290 public: |
297 explicit MockURLRequestThrottlerEntry( | 291 explicit MockURLRequestThrottlerEntry( |
298 URLRequestThrottlerManager* manager) | 292 URLRequestThrottlerManager* manager) |
299 : URLRequestThrottlerEntry(manager, ""), | 293 : URLRequestThrottlerEntry(manager, ""), |
300 mock_backoff_entry_(&backoff_policy_) { | 294 mock_backoff_entry_(&backoff_policy_) { |
301 } | 295 } |
302 | 296 |
303 virtual const BackoffEntry* GetBackoffEntry() const OVERRIDE { | 297 virtual const BackoffEntry* GetBackoffEntry() const OVERRIDE { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 TimeDelta current_jitter = TimeDelta::FromMilliseconds( | 414 TimeDelta current_jitter = TimeDelta::FromMilliseconds( |
421 request_jitter_.InMilliseconds() * base::RandDouble()); | 415 request_jitter_.InMilliseconds() * base::RandDouble()); |
422 if (base::RandInt(0, 1)) { | 416 if (base::RandInt(0, 1)) { |
423 effective_delay -= current_jitter; | 417 effective_delay -= current_jitter; |
424 } else { | 418 } else { |
425 effective_delay += current_jitter; | 419 effective_delay += current_jitter; |
426 } | 420 } |
427 | 421 |
428 if (throttler_entry_->fake_now() - time_of_last_attempt_ > | 422 if (throttler_entry_->fake_now() - time_of_last_attempt_ > |
429 effective_delay) { | 423 effective_delay) { |
430 if (!throttler_entry_->ShouldRejectRequest(0)) { | 424 if (!throttler_entry_->ShouldRejectRequest(NULL, 0)) { |
431 int status_code = server_->HandleRequest(); | 425 int status_code = server_->HandleRequest(); |
432 MockURLRequestThrottlerHeaderAdapter response_headers(status_code); | 426 MockURLRequestThrottlerHeaderAdapter response_headers(status_code); |
433 throttler_entry_->UpdateWithResponse("", &response_headers); | 427 throttler_entry_->UpdateWithResponse("", &response_headers); |
434 | 428 |
435 if (status_code == 200) { | 429 if (status_code == 200) { |
436 if (results_) | 430 if (results_) |
437 results_->AddSuccess(); | 431 results_->AddSuccess(); |
438 | 432 |
439 if (last_attempt_was_failure_) { | 433 if (last_attempt_was_failure_) { |
440 last_downtime_duration_ = | 434 last_downtime_duration_ = |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 DISALLOW_COPY_AND_ASSIGN(Requester); | 480 DISALLOW_COPY_AND_ASSIGN(Requester); |
487 }; | 481 }; |
488 | 482 |
489 void SimulateAttack(Server* server, | 483 void SimulateAttack(Server* server, |
490 RequesterResults* attacker_results, | 484 RequesterResults* attacker_results, |
491 RequesterResults* client_results, | 485 RequesterResults* client_results, |
492 bool enable_throttling) { | 486 bool enable_throttling) { |
493 const size_t kNumAttackers = 50; | 487 const size_t kNumAttackers = 50; |
494 const size_t kNumClients = 50; | 488 const size_t kNumClients = 50; |
495 DiscreteTimeSimulation simulation; | 489 DiscreteTimeSimulation simulation; |
496 TestingURLRequestThrottlerManager manager; | 490 URLRequestThrottlerManager manager; |
497 ScopedVector<Requester> requesters; | 491 ScopedVector<Requester> requesters; |
498 for (size_t i = 0; i < kNumAttackers; ++i) { | 492 for (size_t i = 0; i < kNumAttackers; ++i) { |
499 // Use a tiny time_between_requests so the attackers will ping the | 493 // Use a tiny time_between_requests so the attackers will ping the |
500 // server at every tick of the simulation. | 494 // server at every tick of the simulation. |
501 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( | 495 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( |
502 new MockURLRequestThrottlerEntry(&manager)); | 496 new MockURLRequestThrottlerEntry(&manager)); |
503 if (!enable_throttling) | 497 if (!enable_throttling) |
504 throttler_entry->DisableBackoffThrottling(); | 498 throttler_entry->DisableBackoffThrottling(); |
505 | 499 |
506 Requester* attacker = new Requester(throttler_entry.get(), | 500 Requester* attacker = new Requester(throttler_entry.get(), |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 double SimulateDowntime(const TimeDelta& duration, | 583 double SimulateDowntime(const TimeDelta& duration, |
590 const TimeDelta& average_client_interval, | 584 const TimeDelta& average_client_interval, |
591 bool enable_throttling) { | 585 bool enable_throttling) { |
592 TimeDelta time_between_ticks = duration / 200; | 586 TimeDelta time_between_ticks = duration / 200; |
593 TimeTicks start_downtime = TimeTicks() + (duration / 2); | 587 TimeTicks start_downtime = TimeTicks() + (duration / 2); |
594 | 588 |
595 // A server that never rejects requests, but will go down for maintenance. | 589 // A server that never rejects requests, but will go down for maintenance. |
596 Server server(std::numeric_limits<int>::max(), 1.0); | 590 Server server(std::numeric_limits<int>::max(), 1.0); |
597 server.SetDowntime(start_downtime, duration); | 591 server.SetDowntime(start_downtime, duration); |
598 | 592 |
599 TestingURLRequestThrottlerManager manager; | 593 URLRequestThrottlerManager manager; |
600 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( | 594 scoped_refptr<MockURLRequestThrottlerEntry> throttler_entry( |
601 new MockURLRequestThrottlerEntry(&manager)); | 595 new MockURLRequestThrottlerEntry(&manager)); |
602 if (!enable_throttling) | 596 if (!enable_throttling) |
603 throttler_entry->DisableBackoffThrottling(); | 597 throttler_entry->DisableBackoffThrottling(); |
604 | 598 |
605 Requester requester( | 599 Requester requester( |
606 throttler_entry.get(), average_client_interval, &server, NULL); | 600 throttler_entry.get(), average_client_interval, &server, NULL); |
607 requester.SetStartupJitter(duration / 3); | 601 requester.SetStartupJitter(duration / 3); |
608 requester.SetRequestJitter(average_client_interval); | 602 requester.SetRequestJitter(average_client_interval); |
609 | 603 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 trials[i].PrintTrialDescription(); | 739 trials[i].PrintTrialDescription(); |
746 trials[i].stats.ReportTrialResult(increase_ratio); | 740 trials[i].stats.ReportTrialResult(increase_ratio); |
747 } | 741 } |
748 | 742 |
749 VerboseOut("Average increase ratio was %.4f\n", average_increase_ratio); | 743 VerboseOut("Average increase ratio was %.4f\n", average_increase_ratio); |
750 VerboseOut("Maximum increase ratio was %.4f\n", max_increase_ratio); | 744 VerboseOut("Maximum increase ratio was %.4f\n", max_increase_ratio); |
751 } | 745 } |
752 | 746 |
753 } // namespace | 747 } // namespace |
754 } // namespace net | 748 } // namespace net |
OLD | NEW |