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