| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "net/tools/quic/test_tools/packet_dropping_test_writer.h" | 5 #include "net/tools/quic/test_tools/packet_dropping_test_writer.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 10 #include "net/quic/platform/api/quic_logging.h" |
| 10 #include "net/tools/quic/platform/impl/quic_socket_utils.h" | 11 #include "net/tools/quic/platform/impl/quic_socket_utils.h" |
| 11 #include "net/tools/quic/quic_epoll_connection_helper.h" | 12 #include "net/tools/quic/quic_epoll_connection_helper.h" |
| 12 | 13 |
| 13 namespace net { | 14 namespace net { |
| 14 namespace test { | 15 namespace test { |
| 15 | 16 |
| 16 // An alarm that is scheduled if a blocked socket is simulated to indicate | 17 // An alarm that is scheduled if a blocked socket is simulated to indicate |
| 17 // it's writable again. | 18 // it's writable again. |
| 18 class WriteUnblockedAlarm : public QuicAlarm::Delegate { | 19 class WriteUnblockedAlarm : public QuicAlarm::Delegate { |
| 19 public: | 20 public: |
| 20 explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer) | 21 explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer) |
| 21 : writer_(writer) {} | 22 : writer_(writer) {} |
| 22 | 23 |
| 23 void OnAlarm() override { | 24 void OnAlarm() override { |
| 24 DVLOG(1) << "Unblocking socket."; | 25 QUIC_DLOG(INFO) << "Unblocking socket."; |
| 25 writer_->OnCanWrite(); | 26 writer_->OnCanWrite(); |
| 26 } | 27 } |
| 27 | 28 |
| 28 private: | 29 private: |
| 29 PacketDroppingTestWriter* writer_; | 30 PacketDroppingTestWriter* writer_; |
| 30 }; | 31 }; |
| 31 | 32 |
| 32 // An alarm that is scheduled every time a new packet is to be written at a | 33 // An alarm that is scheduled every time a new packet is to be written at a |
| 33 // later point. | 34 // later point. |
| 34 class DelayAlarm : public QuicAlarm::Delegate { | 35 class DelayAlarm : public QuicAlarm::Delegate { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 52 num_calls_to_write_(0), | 53 num_calls_to_write_(0), |
| 53 config_mutex_(), | 54 config_mutex_(), |
| 54 fake_packet_loss_percentage_(0), | 55 fake_packet_loss_percentage_(0), |
| 55 fake_drop_first_n_packets_(0), | 56 fake_drop_first_n_packets_(0), |
| 56 fake_blocked_socket_percentage_(0), | 57 fake_blocked_socket_percentage_(0), |
| 57 fake_packet_reorder_percentage_(0), | 58 fake_packet_reorder_percentage_(0), |
| 58 fake_packet_delay_(QuicTime::Delta::Zero()), | 59 fake_packet_delay_(QuicTime::Delta::Zero()), |
| 59 fake_bandwidth_(QuicBandwidth::Zero()), | 60 fake_bandwidth_(QuicBandwidth::Zero()), |
| 60 buffer_size_(0) { | 61 buffer_size_(0) { |
| 61 uint32_t seed = base::RandInt(0, std::numeric_limits<int32_t>::max()); | 62 uint32_t seed = base::RandInt(0, std::numeric_limits<int32_t>::max()); |
| 62 VLOG(1) << "Seeding packet loss with " << seed; | 63 QUIC_LOG(INFO) << "Seeding packet loss with " << seed; |
| 63 simple_random_.set_seed(seed); | 64 simple_random_.set_seed(seed); |
| 64 } | 65 } |
| 65 | 66 |
| 66 PacketDroppingTestWriter::~PacketDroppingTestWriter() {} | 67 PacketDroppingTestWriter::~PacketDroppingTestWriter() {} |
| 67 | 68 |
| 68 void PacketDroppingTestWriter::Initialize(QuicConnectionHelperInterface* helper, | 69 void PacketDroppingTestWriter::Initialize(QuicConnectionHelperInterface* helper, |
| 69 QuicAlarmFactory* alarm_factory, | 70 QuicAlarmFactory* alarm_factory, |
| 70 Delegate* on_can_write) { | 71 Delegate* on_can_write) { |
| 71 clock_ = helper->GetClock(); | 72 clock_ = helper->GetClock(); |
| 72 write_unblocked_alarm_.reset( | 73 write_unblocked_alarm_.reset( |
| 73 alarm_factory->CreateAlarm(new WriteUnblockedAlarm(this))); | 74 alarm_factory->CreateAlarm(new WriteUnblockedAlarm(this))); |
| 74 delay_alarm_.reset(alarm_factory->CreateAlarm(new DelayAlarm(this))); | 75 delay_alarm_.reset(alarm_factory->CreateAlarm(new DelayAlarm(this))); |
| 75 on_can_write_.reset(on_can_write); | 76 on_can_write_.reset(on_can_write); |
| 76 } | 77 } |
| 77 | 78 |
| 78 WriteResult PacketDroppingTestWriter::WritePacket( | 79 WriteResult PacketDroppingTestWriter::WritePacket( |
| 79 const char* buffer, | 80 const char* buffer, |
| 80 size_t buf_len, | 81 size_t buf_len, |
| 81 const QuicIpAddress& self_address, | 82 const QuicIpAddress& self_address, |
| 82 const QuicSocketAddress& peer_address, | 83 const QuicSocketAddress& peer_address, |
| 83 PerPacketOptions* options) { | 84 PerPacketOptions* options) { |
| 84 ++num_calls_to_write_; | 85 ++num_calls_to_write_; |
| 85 ReleaseOldPackets(); | 86 ReleaseOldPackets(); |
| 86 | 87 |
| 87 QuicReaderMutexLock lock(&config_mutex_); | 88 QuicReaderMutexLock lock(&config_mutex_); |
| 88 if (fake_drop_first_n_packets_ > 0 && | 89 if (fake_drop_first_n_packets_ > 0 && |
| 89 num_calls_to_write_ <= | 90 num_calls_to_write_ <= |
| 90 static_cast<uint64_t>(fake_drop_first_n_packets_)) { | 91 static_cast<uint64_t>(fake_drop_first_n_packets_)) { |
| 91 DVLOG(1) << "Dropping first " << fake_drop_first_n_packets_ | 92 QUIC_DVLOG(1) << "Dropping first " << fake_drop_first_n_packets_ |
| 92 << " packets (packet number " << num_calls_to_write_ << ")"; | 93 << " packets (packet number " << num_calls_to_write_ << ")"; |
| 93 return WriteResult(WRITE_STATUS_OK, buf_len); | 94 return WriteResult(WRITE_STATUS_OK, buf_len); |
| 94 } | 95 } |
| 95 if (fake_packet_loss_percentage_ > 0 && | 96 if (fake_packet_loss_percentage_ > 0 && |
| 96 simple_random_.RandUint64() % 100 < | 97 simple_random_.RandUint64() % 100 < |
| 97 static_cast<uint64_t>(fake_packet_loss_percentage_)) { | 98 static_cast<uint64_t>(fake_packet_loss_percentage_)) { |
| 98 DVLOG(1) << "Dropping packet."; | 99 QUIC_DVLOG(1) << "Dropping packet."; |
| 99 return WriteResult(WRITE_STATUS_OK, buf_len); | 100 return WriteResult(WRITE_STATUS_OK, buf_len); |
| 100 } | 101 } |
| 101 if (fake_blocked_socket_percentage_ > 0 && | 102 if (fake_blocked_socket_percentage_ > 0 && |
| 102 simple_random_.RandUint64() % 100 < | 103 simple_random_.RandUint64() % 100 < |
| 103 static_cast<uint64_t>(fake_blocked_socket_percentage_)) { | 104 static_cast<uint64_t>(fake_blocked_socket_percentage_)) { |
| 104 CHECK(on_can_write_.get() != nullptr); | 105 CHECK(on_can_write_.get() != nullptr); |
| 105 DVLOG(1) << "Blocking socket."; | 106 QUIC_DVLOG(1) << "Blocking socket."; |
| 106 if (!write_unblocked_alarm_->IsSet()) { | 107 if (!write_unblocked_alarm_->IsSet()) { |
| 107 // Set the alarm to fire immediately. | 108 // Set the alarm to fire immediately. |
| 108 write_unblocked_alarm_->Set(clock_->ApproximateNow()); | 109 write_unblocked_alarm_->Set(clock_->ApproximateNow()); |
| 109 } | 110 } |
| 110 return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN); | 111 return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN); |
| 111 } | 112 } |
| 112 | 113 |
| 113 if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) { | 114 if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) { |
| 114 if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) { | 115 if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) { |
| 115 // Drop packets which do not fit into the buffer. | 116 // Drop packets which do not fit into the buffer. |
| 116 DVLOG(1) << "Dropping packet because the buffer is full."; | 117 QUIC_DVLOG(1) << "Dropping packet because the buffer is full."; |
| 117 return WriteResult(WRITE_STATUS_OK, buf_len); | 118 return WriteResult(WRITE_STATUS_OK, buf_len); |
| 118 } | 119 } |
| 119 | 120 |
| 120 // Queue it to be sent. | 121 // Queue it to be sent. |
| 121 QuicTime send_time = clock_->ApproximateNow() + fake_packet_delay_; | 122 QuicTime send_time = clock_->ApproximateNow() + fake_packet_delay_; |
| 122 if (!fake_bandwidth_.IsZero()) { | 123 if (!fake_bandwidth_.IsZero()) { |
| 123 // Calculate a time the bandwidth limit would impose. | 124 // Calculate a time the bandwidth limit would impose. |
| 124 QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds( | 125 QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds( |
| 125 (buf_len * kNumMicrosPerSecond) / fake_bandwidth_.ToBytesPerSecond()); | 126 (buf_len * kNumMicrosPerSecond) / fake_bandwidth_.ToBytesPerSecond()); |
| 126 send_time = delayed_packets_.empty() | 127 send_time = delayed_packets_.empty() |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 QuicTime PacketDroppingTestWriter::ReleaseNextPacket() { | 168 QuicTime PacketDroppingTestWriter::ReleaseNextPacket() { |
| 168 if (delayed_packets_.empty()) { | 169 if (delayed_packets_.empty()) { |
| 169 return QuicTime::Zero(); | 170 return QuicTime::Zero(); |
| 170 } | 171 } |
| 171 QuicReaderMutexLock lock(&config_mutex_); | 172 QuicReaderMutexLock lock(&config_mutex_); |
| 172 DelayedPacketList::iterator iter = delayed_packets_.begin(); | 173 DelayedPacketList::iterator iter = delayed_packets_.begin(); |
| 173 // Determine if we should re-order. | 174 // Determine if we should re-order. |
| 174 if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 && | 175 if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 && |
| 175 simple_random_.RandUint64() % 100 < | 176 simple_random_.RandUint64() % 100 < |
| 176 static_cast<uint64_t>(fake_packet_reorder_percentage_)) { | 177 static_cast<uint64_t>(fake_packet_reorder_percentage_)) { |
| 177 DVLOG(1) << "Reordering packets."; | 178 QUIC_DLOG(INFO) << "Reordering packets."; |
| 178 ++iter; | 179 ++iter; |
| 179 // Swap the send times when re-ordering packets. | 180 // Swap the send times when re-ordering packets. |
| 180 delayed_packets_.begin()->send_time = iter->send_time; | 181 delayed_packets_.begin()->send_time = iter->send_time; |
| 181 } | 182 } |
| 182 | 183 |
| 183 DVLOG(1) << "Releasing packet. " << (delayed_packets_.size() - 1) | 184 QUIC_DLOG(INFO) << "Releasing packet. " << (delayed_packets_.size() - 1) |
| 184 << " remaining."; | 185 << " remaining."; |
| 185 // Grab the next one off the queue and send it. | 186 // Grab the next one off the queue and send it. |
| 186 QuicPacketWriterWrapper::WritePacket( | 187 QuicPacketWriterWrapper::WritePacket( |
| 187 iter->buffer.data(), iter->buffer.length(), iter->self_address, | 188 iter->buffer.data(), iter->buffer.length(), iter->self_address, |
| 188 iter->peer_address, iter->options.get()); | 189 iter->peer_address, iter->options.get()); |
| 189 DCHECK_GE(cur_buffer_size_, iter->buffer.length()); | 190 DCHECK_GE(cur_buffer_size_, iter->buffer.length()); |
| 190 cur_buffer_size_ -= iter->buffer.length(); | 191 cur_buffer_size_ -= iter->buffer.length(); |
| 191 delayed_packets_.erase(iter); | 192 delayed_packets_.erase(iter); |
| 192 | 193 |
| 193 // If there are others, find the time for the next to be sent. | 194 // If there are others, find the time for the next to be sent. |
| 194 if (delayed_packets_.empty()) { | 195 if (delayed_packets_.empty()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 // IPAddress has no move assignment operator. | 238 // IPAddress has no move assignment operator. |
| 238 // | 239 // |
| 239 // PacketDroppingTestWriter::DelayedWrite& | 240 // PacketDroppingTestWriter::DelayedWrite& |
| 240 // PacketDroppingTestWriter::DelayedWrite::operator=( | 241 // PacketDroppingTestWriter::DelayedWrite::operator=( |
| 241 // PacketDroppingTestWriter::DelayedWrite&& other) = default; | 242 // PacketDroppingTestWriter::DelayedWrite&& other) = default; |
| 242 | 243 |
| 243 PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() {} | 244 PacketDroppingTestWriter::DelayedWrite::~DelayedWrite() {} |
| 244 | 245 |
| 245 } // namespace test | 246 } // namespace test |
| 246 } // namespace net | 247 } // namespace net |
| OLD | NEW |