OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/strings/stringprintf.h" |
| 6 #include "net/quic/core/congestion_control/simulation/link.h" |
| 7 #include "net/quic/core/congestion_control/simulation/simulator.h" |
| 8 |
| 9 using base::StringPrintf; |
| 10 |
| 11 namespace net { |
| 12 namespace simulation { |
| 13 |
| 14 // Parameters for random noise delay. |
| 15 const uint64_t kMaxRandomDelayUs = 10; |
| 16 |
| 17 OneWayLink::OneWayLink(Simulator* simulator, |
| 18 std::string name, |
| 19 UnconstrainedPortInterface* sink, |
| 20 QuicBandwidth bandwidth, |
| 21 QuicTime::Delta propagation_delay) |
| 22 : Actor(simulator, name), |
| 23 sink_(sink), |
| 24 bandwidth_(bandwidth), |
| 25 propagation_delay_(propagation_delay), |
| 26 next_write_at_(QuicTime::Zero()) {} |
| 27 |
| 28 OneWayLink::~OneWayLink() {} |
| 29 |
| 30 OneWayLink::QueuedPacket::QueuedPacket(std::unique_ptr<Packet> packet, |
| 31 QuicTime dequeue_time) |
| 32 : packet(std::move(packet)), dequeue_time(dequeue_time) {} |
| 33 |
| 34 OneWayLink::QueuedPacket::~QueuedPacket() {} |
| 35 |
| 36 void OneWayLink::AcceptPacket(std::unique_ptr<Packet> packet) { |
| 37 DCHECK(TimeUntilAvailable().IsZero()); |
| 38 QuicTime::Delta transfer_time = bandwidth_.TransferTime(packet->size); |
| 39 next_write_at_ = clock_->Now() + transfer_time; |
| 40 |
| 41 packets_in_transit_.emplace( |
| 42 std::move(packet), |
| 43 next_write_at_ + propagation_delay_ + GetRandomDelay(transfer_time)); |
| 44 ScheduleNextPacketDeparture(); |
| 45 } |
| 46 |
| 47 QuicTime::Delta OneWayLink::TimeUntilAvailable() { |
| 48 const QuicTime now = clock_->Now(); |
| 49 if (next_write_at_ <= now) { |
| 50 return QuicTime::Delta::Zero(); |
| 51 } |
| 52 |
| 53 return next_write_at_ - now; |
| 54 } |
| 55 |
| 56 void OneWayLink::Act() { |
| 57 DCHECK(!packets_in_transit_.empty()); |
| 58 DCHECK(packets_in_transit_.front().dequeue_time >= clock_->Now()); |
| 59 |
| 60 sink_->AcceptPacket(std::move(packets_in_transit_.front().packet)); |
| 61 packets_in_transit_.pop(); |
| 62 |
| 63 ScheduleNextPacketDeparture(); |
| 64 } |
| 65 |
| 66 void OneWayLink::ScheduleNextPacketDeparture() { |
| 67 if (packets_in_transit_.empty()) { |
| 68 return; |
| 69 } |
| 70 |
| 71 Schedule(packets_in_transit_.front().dequeue_time); |
| 72 } |
| 73 |
| 74 QuicTime::Delta OneWayLink::GetRandomDelay(QuicTime::Delta transfer_time) { |
| 75 QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds( |
| 76 simulator_->GetRandomGenerator()->RandUint64() % (kMaxRandomDelayUs + 1)); |
| 77 // Have an upper bound on the delay to ensure packets do not go out of order. |
| 78 delta = std::min(delta, transfer_time * 0.5); |
| 79 return delta; |
| 80 } |
| 81 |
| 82 SymmetricLink::SymmetricLink(Simulator* simulator, |
| 83 std::string name, |
| 84 UnconstrainedPortInterface* sink_a, |
| 85 UnconstrainedPortInterface* sink_b, |
| 86 QuicBandwidth bandwidth, |
| 87 QuicTime::Delta propagation_delay) |
| 88 : a_to_b_link_(simulator, |
| 89 StringPrintf("%s (A-to-B)", name.c_str()), |
| 90 sink_b, |
| 91 bandwidth, |
| 92 propagation_delay), |
| 93 b_to_a_link_(simulator, |
| 94 StringPrintf("%s (B-to-A)", name.c_str()), |
| 95 sink_a, |
| 96 bandwidth, |
| 97 propagation_delay) {} |
| 98 |
| 99 SymmetricLink::SymmetricLink(Endpoint* endpoint_a, |
| 100 Endpoint* endpoint_b, |
| 101 QuicBandwidth bandwidth, |
| 102 QuicTime::Delta propagation_delay) |
| 103 : SymmetricLink(endpoint_a->simulator(), |
| 104 StringPrintf("Link [%s]<->[%s]", |
| 105 endpoint_a->name().c_str(), |
| 106 endpoint_b->name().c_str()), |
| 107 endpoint_a->GetRxPort(), |
| 108 endpoint_b->GetRxPort(), |
| 109 bandwidth, |
| 110 propagation_delay) { |
| 111 endpoint_a->SetTxPort(&a_to_b_link_); |
| 112 endpoint_b->SetTxPort(&b_to_a_link_); |
| 113 } |
| 114 |
| 115 } // namespace simulation |
| 116 } // namespace net |
OLD | NEW |