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