| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" | |
| #include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h" | |
| namespace quic { | |
| namespace simulator { | |
| // Parameters for random noise delay. | |
| const uint64_t kMaxRandomDelayUs = 10; | |
| OneWayLink::OneWayLink(Simulator* simulator, | |
| std::string name, | |
| UnconstrainedPortInterface* sink, | |
| QuicBandwidth bandwidth, | |
| QuicTime::Delta propagation_delay) | |
| : Actor(simulator, name), | |
| sink_(sink), | |
| bandwidth_(bandwidth), | |
| propagation_delay_(propagation_delay), | |
| next_write_at_(QuicTime::Zero()) {} | |
| OneWayLink::~OneWayLink() {} | |
| OneWayLink::QueuedPacket::QueuedPacket(std::unique_ptr<Packet> packet, | |
| QuicTime dequeue_time) | |
| : packet(std::move(packet)), dequeue_time(dequeue_time) {} | |
| OneWayLink::QueuedPacket::QueuedPacket(QueuedPacket&& other) = default; | |
| OneWayLink::QueuedPacket::~QueuedPacket() {} | |
| void OneWayLink::AcceptPacket(std::unique_ptr<Packet> packet) { | |
| DCHECK(TimeUntilAvailable().IsZero()); | |
| QuicTime::Delta transfer_time = bandwidth_.TransferTime(packet->size); | |
| next_write_at_ = clock_->Now() + transfer_time; | |
| packets_in_transit_.emplace_back( | |
| std::move(packet), | |
| // Ensure that packets are delivered in order. | |
| std::max( | |
| next_write_at_ + propagation_delay_ + GetRandomDelay(transfer_time), | |
| packets_in_transit_.empty() | |
| ? QuicTime::Zero() | |
| : packets_in_transit_.back().dequeue_time)); | |
| ScheduleNextPacketDeparture(); | |
| } | |
| QuicTime::Delta OneWayLink::TimeUntilAvailable() { | |
| const QuicTime now = clock_->Now(); | |
| if (next_write_at_ <= now) { | |
| return QuicTime::Delta::Zero(); | |
| } | |
| return next_write_at_ - now; | |
| } | |
| void OneWayLink::Act() { | |
| DCHECK(!packets_in_transit_.empty()); | |
| DCHECK(packets_in_transit_.front().dequeue_time >= clock_->Now()); | |
| sink_->AcceptPacket(std::move(packets_in_transit_.front().packet)); | |
| packets_in_transit_.pop_front(); | |
| ScheduleNextPacketDeparture(); | |
| } | |
| void OneWayLink::ScheduleNextPacketDeparture() { | |
| if (packets_in_transit_.empty()) { | |
| return; | |
| } | |
| Schedule(packets_in_transit_.front().dequeue_time); | |
| } | |
| QuicTime::Delta OneWayLink::GetRandomDelay(QuicTime::Delta transfer_time) { | |
| if (!simulator_->enable_random_delays()) { | |
| return QuicTime::Delta::Zero(); | |
| } | |
| QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds( | |
| simulator_->GetRandomGenerator()->RandUint64() % (kMaxRandomDelayUs + 1)); | |
| // Have an upper bound on the delay to ensure packets do not go out of order. | |
| delta = std::min(delta, transfer_time * 0.5); | |
| return delta; | |
| } | |
| SymmetricLink::SymmetricLink(Simulator* simulator, | |
| std::string name, | |
| UnconstrainedPortInterface* sink_a, | |
| UnconstrainedPortInterface* sink_b, | |
| QuicBandwidth bandwidth, | |
| QuicTime::Delta propagation_delay) | |
| : a_to_b_link_(simulator, | |
| QuicStringPrintf("%s (A-to-B)", name.c_str()), | |
| sink_b, | |
| bandwidth, | |
| propagation_delay), | |
| b_to_a_link_(simulator, | |
| QuicStringPrintf("%s (B-to-A)", name.c_str()), | |
| sink_a, | |
| bandwidth, | |
| propagation_delay) {} | |
| SymmetricLink::SymmetricLink(Endpoint* endpoint_a, | |
| Endpoint* endpoint_b, | |
| QuicBandwidth bandwidth, | |
| QuicTime::Delta propagation_delay) | |
| : SymmetricLink(endpoint_a->simulator(), | |
| QuicStringPrintf("Link [%s]<->[%s]", | |
| endpoint_a->name().c_str(), | |
| endpoint_b->name().c_str()), | |
| endpoint_a->GetRxPort(), | |
| endpoint_b->GetRxPort(), | |
| bandwidth, | |
| propagation_delay) { | |
| endpoint_a->SetTxPort(&a_to_b_link_); | |
| endpoint_b->SetTxPort(&b_to_a_link_); | |
| } | |
| } // namespace simulator | |
| } // namespace quic |