1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "test/network/cross_traffic.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <math.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
18*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
19*d9f75844SAndroid Build Coastguard Worker #include "cross_traffic.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_minmax.h"
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
24*d9f75844SAndroid Build Coastguard Worker namespace test {
25*d9f75844SAndroid Build Coastguard Worker
RandomWalkCrossTraffic(RandomWalkConfig config,CrossTrafficRoute * traffic_route)26*d9f75844SAndroid Build Coastguard Worker RandomWalkCrossTraffic::RandomWalkCrossTraffic(RandomWalkConfig config,
27*d9f75844SAndroid Build Coastguard Worker CrossTrafficRoute* traffic_route)
28*d9f75844SAndroid Build Coastguard Worker : config_(config),
29*d9f75844SAndroid Build Coastguard Worker traffic_route_(traffic_route),
30*d9f75844SAndroid Build Coastguard Worker random_(config_.random_seed) {
31*d9f75844SAndroid Build Coastguard Worker sequence_checker_.Detach();
32*d9f75844SAndroid Build Coastguard Worker }
33*d9f75844SAndroid Build Coastguard Worker RandomWalkCrossTraffic::~RandomWalkCrossTraffic() = default;
34*d9f75844SAndroid Build Coastguard Worker
Process(Timestamp at_time)35*d9f75844SAndroid Build Coastguard Worker void RandomWalkCrossTraffic::Process(Timestamp at_time) {
36*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_);
37*d9f75844SAndroid Build Coastguard Worker if (last_process_time_.IsMinusInfinity()) {
38*d9f75844SAndroid Build Coastguard Worker last_process_time_ = at_time;
39*d9f75844SAndroid Build Coastguard Worker }
40*d9f75844SAndroid Build Coastguard Worker TimeDelta delta = at_time - last_process_time_;
41*d9f75844SAndroid Build Coastguard Worker last_process_time_ = at_time;
42*d9f75844SAndroid Build Coastguard Worker
43*d9f75844SAndroid Build Coastguard Worker if (at_time - last_update_time_ >= config_.update_interval) {
44*d9f75844SAndroid Build Coastguard Worker intensity_ += random_.Gaussian(config_.bias, config_.variance) *
45*d9f75844SAndroid Build Coastguard Worker sqrt((at_time - last_update_time_).seconds<double>());
46*d9f75844SAndroid Build Coastguard Worker intensity_ = rtc::SafeClamp(intensity_, 0.0, 1.0);
47*d9f75844SAndroid Build Coastguard Worker last_update_time_ = at_time;
48*d9f75844SAndroid Build Coastguard Worker }
49*d9f75844SAndroid Build Coastguard Worker pending_size_ += TrafficRate() * delta;
50*d9f75844SAndroid Build Coastguard Worker
51*d9f75844SAndroid Build Coastguard Worker if (pending_size_ >= config_.min_packet_size &&
52*d9f75844SAndroid Build Coastguard Worker at_time >= last_send_time_ + config_.min_packet_interval) {
53*d9f75844SAndroid Build Coastguard Worker traffic_route_->SendPacket(pending_size_.bytes());
54*d9f75844SAndroid Build Coastguard Worker pending_size_ = DataSize::Zero();
55*d9f75844SAndroid Build Coastguard Worker last_send_time_ = at_time;
56*d9f75844SAndroid Build Coastguard Worker }
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker
GetProcessInterval() const59*d9f75844SAndroid Build Coastguard Worker TimeDelta RandomWalkCrossTraffic::GetProcessInterval() const {
60*d9f75844SAndroid Build Coastguard Worker return config_.min_packet_interval;
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker
TrafficRate() const63*d9f75844SAndroid Build Coastguard Worker DataRate RandomWalkCrossTraffic::TrafficRate() const {
64*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_);
65*d9f75844SAndroid Build Coastguard Worker return config_.peak_rate * intensity_;
66*d9f75844SAndroid Build Coastguard Worker }
67*d9f75844SAndroid Build Coastguard Worker
StatsPrinter()68*d9f75844SAndroid Build Coastguard Worker ColumnPrinter RandomWalkCrossTraffic::StatsPrinter() {
69*d9f75844SAndroid Build Coastguard Worker return ColumnPrinter::Lambda(
70*d9f75844SAndroid Build Coastguard Worker "random_walk_cross_traffic_rate",
71*d9f75844SAndroid Build Coastguard Worker [this](rtc::SimpleStringBuilder& sb) {
72*d9f75844SAndroid Build Coastguard Worker sb.AppendFormat("%.0lf", TrafficRate().bps() / 8.0);
73*d9f75844SAndroid Build Coastguard Worker },
74*d9f75844SAndroid Build Coastguard Worker 32);
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker
PulsedPeaksCrossTraffic(PulsedPeaksConfig config,CrossTrafficRoute * traffic_route)77*d9f75844SAndroid Build Coastguard Worker PulsedPeaksCrossTraffic::PulsedPeaksCrossTraffic(
78*d9f75844SAndroid Build Coastguard Worker PulsedPeaksConfig config,
79*d9f75844SAndroid Build Coastguard Worker CrossTrafficRoute* traffic_route)
80*d9f75844SAndroid Build Coastguard Worker : config_(config), traffic_route_(traffic_route) {
81*d9f75844SAndroid Build Coastguard Worker sequence_checker_.Detach();
82*d9f75844SAndroid Build Coastguard Worker }
83*d9f75844SAndroid Build Coastguard Worker PulsedPeaksCrossTraffic::~PulsedPeaksCrossTraffic() = default;
84*d9f75844SAndroid Build Coastguard Worker
Process(Timestamp at_time)85*d9f75844SAndroid Build Coastguard Worker void PulsedPeaksCrossTraffic::Process(Timestamp at_time) {
86*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_);
87*d9f75844SAndroid Build Coastguard Worker TimeDelta time_since_toggle = at_time - last_update_time_;
88*d9f75844SAndroid Build Coastguard Worker if (time_since_toggle.IsInfinite() ||
89*d9f75844SAndroid Build Coastguard Worker (sending_ && time_since_toggle >= config_.send_duration)) {
90*d9f75844SAndroid Build Coastguard Worker sending_ = false;
91*d9f75844SAndroid Build Coastguard Worker last_update_time_ = at_time;
92*d9f75844SAndroid Build Coastguard Worker } else if (!sending_ && time_since_toggle >= config_.hold_duration) {
93*d9f75844SAndroid Build Coastguard Worker sending_ = true;
94*d9f75844SAndroid Build Coastguard Worker last_update_time_ = at_time;
95*d9f75844SAndroid Build Coastguard Worker // Start sending period.
96*d9f75844SAndroid Build Coastguard Worker last_send_time_ = at_time;
97*d9f75844SAndroid Build Coastguard Worker }
98*d9f75844SAndroid Build Coastguard Worker
99*d9f75844SAndroid Build Coastguard Worker if (sending_) {
100*d9f75844SAndroid Build Coastguard Worker DataSize pending_size = config_.peak_rate * (at_time - last_send_time_);
101*d9f75844SAndroid Build Coastguard Worker
102*d9f75844SAndroid Build Coastguard Worker if (pending_size >= config_.min_packet_size &&
103*d9f75844SAndroid Build Coastguard Worker at_time >= last_send_time_ + config_.min_packet_interval) {
104*d9f75844SAndroid Build Coastguard Worker traffic_route_->SendPacket(pending_size.bytes());
105*d9f75844SAndroid Build Coastguard Worker last_send_time_ = at_time;
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker }
109*d9f75844SAndroid Build Coastguard Worker
GetProcessInterval() const110*d9f75844SAndroid Build Coastguard Worker TimeDelta PulsedPeaksCrossTraffic::GetProcessInterval() const {
111*d9f75844SAndroid Build Coastguard Worker return config_.min_packet_interval;
112*d9f75844SAndroid Build Coastguard Worker }
113*d9f75844SAndroid Build Coastguard Worker
TrafficRate() const114*d9f75844SAndroid Build Coastguard Worker DataRate PulsedPeaksCrossTraffic::TrafficRate() const {
115*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_RUN_ON(&sequence_checker_);
116*d9f75844SAndroid Build Coastguard Worker return sending_ ? config_.peak_rate : DataRate::Zero();
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker
StatsPrinter()119*d9f75844SAndroid Build Coastguard Worker ColumnPrinter PulsedPeaksCrossTraffic::StatsPrinter() {
120*d9f75844SAndroid Build Coastguard Worker return ColumnPrinter::Lambda(
121*d9f75844SAndroid Build Coastguard Worker "pulsed_peaks_cross_traffic_rate",
122*d9f75844SAndroid Build Coastguard Worker [this](rtc::SimpleStringBuilder& sb) {
123*d9f75844SAndroid Build Coastguard Worker sb.AppendFormat("%.0lf", TrafficRate().bps() / 8.0);
124*d9f75844SAndroid Build Coastguard Worker },
125*d9f75844SAndroid Build Coastguard Worker 32);
126*d9f75844SAndroid Build Coastguard Worker }
127*d9f75844SAndroid Build Coastguard Worker
TcpMessageRouteImpl(Clock * clock,TaskQueueBase * task_queue,EmulatedRoute * send_route,EmulatedRoute * ret_route)128*d9f75844SAndroid Build Coastguard Worker TcpMessageRouteImpl::TcpMessageRouteImpl(Clock* clock,
129*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* task_queue,
130*d9f75844SAndroid Build Coastguard Worker EmulatedRoute* send_route,
131*d9f75844SAndroid Build Coastguard Worker EmulatedRoute* ret_route)
132*d9f75844SAndroid Build Coastguard Worker : clock_(clock),
133*d9f75844SAndroid Build Coastguard Worker task_queue_(task_queue),
134*d9f75844SAndroid Build Coastguard Worker request_route_(send_route,
135*d9f75844SAndroid Build Coastguard Worker [this](TcpPacket packet, Timestamp) {
136*d9f75844SAndroid Build Coastguard Worker OnRequest(std::move(packet));
137*d9f75844SAndroid Build Coastguard Worker }),
138*d9f75844SAndroid Build Coastguard Worker response_route_(ret_route,
__anon0369fb610402(TcpPacket packet, Timestamp arrival_time) 139*d9f75844SAndroid Build Coastguard Worker [this](TcpPacket packet, Timestamp arrival_time) {
140*d9f75844SAndroid Build Coastguard Worker OnResponse(std::move(packet), arrival_time);
141*d9f75844SAndroid Build Coastguard Worker }) {}
142*d9f75844SAndroid Build Coastguard Worker
SendMessage(size_t size,std::function<void ()> on_received)143*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::SendMessage(size_t size,
144*d9f75844SAndroid Build Coastguard Worker std::function<void()> on_received) {
145*d9f75844SAndroid Build Coastguard Worker task_queue_->PostTask(
146*d9f75844SAndroid Build Coastguard Worker [this, size, handler = std::move(on_received)] {
147*d9f75844SAndroid Build Coastguard Worker // If we are currently sending a message we won't reset the connection,
148*d9f75844SAndroid Build Coastguard Worker // we'll act as if the messages are sent in the same TCP stream. This is
149*d9f75844SAndroid Build Coastguard Worker // intended to simulate recreation of a TCP session for each message
150*d9f75844SAndroid Build Coastguard Worker // in the typical case while avoiding the complexity overhead of
151*d9f75844SAndroid Build Coastguard Worker // maintaining multiple virtual TCP sessions in parallel.
152*d9f75844SAndroid Build Coastguard Worker if (pending_.empty() && in_flight_.empty()) {
153*d9f75844SAndroid Build Coastguard Worker cwnd_ = 10;
154*d9f75844SAndroid Build Coastguard Worker ssthresh_ = INFINITY;
155*d9f75844SAndroid Build Coastguard Worker }
156*d9f75844SAndroid Build Coastguard Worker int64_t data_left = static_cast<int64_t>(size);
157*d9f75844SAndroid Build Coastguard Worker int64_t kMaxPacketSize = 1200;
158*d9f75844SAndroid Build Coastguard Worker int64_t kMinPacketSize = 4;
159*d9f75844SAndroid Build Coastguard Worker Message message{std::move(handler)};
160*d9f75844SAndroid Build Coastguard Worker while (data_left > 0) {
161*d9f75844SAndroid Build Coastguard Worker int64_t packet_size = std::min(data_left, kMaxPacketSize);
162*d9f75844SAndroid Build Coastguard Worker int fragment_id = next_fragment_id_++;
163*d9f75844SAndroid Build Coastguard Worker pending_.push_back(MessageFragment{
164*d9f75844SAndroid Build Coastguard Worker fragment_id,
165*d9f75844SAndroid Build Coastguard Worker static_cast<size_t>(std::max(kMinPacketSize, packet_size))});
166*d9f75844SAndroid Build Coastguard Worker message.pending_fragment_ids.insert(fragment_id);
167*d9f75844SAndroid Build Coastguard Worker data_left -= packet_size;
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker messages_.emplace_back(message);
170*d9f75844SAndroid Build Coastguard Worker SendPackets(clock_->CurrentTime());
171*d9f75844SAndroid Build Coastguard Worker });
172*d9f75844SAndroid Build Coastguard Worker }
173*d9f75844SAndroid Build Coastguard Worker
OnRequest(TcpPacket packet_info)174*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::OnRequest(TcpPacket packet_info) {
175*d9f75844SAndroid Build Coastguard Worker for (auto it = messages_.begin(); it != messages_.end(); ++it) {
176*d9f75844SAndroid Build Coastguard Worker if (it->pending_fragment_ids.count(packet_info.fragment.fragment_id) != 0) {
177*d9f75844SAndroid Build Coastguard Worker it->pending_fragment_ids.erase(packet_info.fragment.fragment_id);
178*d9f75844SAndroid Build Coastguard Worker if (it->pending_fragment_ids.empty()) {
179*d9f75844SAndroid Build Coastguard Worker it->handler();
180*d9f75844SAndroid Build Coastguard Worker messages_.erase(it);
181*d9f75844SAndroid Build Coastguard Worker }
182*d9f75844SAndroid Build Coastguard Worker break;
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker const size_t kAckPacketSize = 20;
186*d9f75844SAndroid Build Coastguard Worker response_route_.SendPacket(kAckPacketSize, packet_info);
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker
OnResponse(TcpPacket packet_info,Timestamp at_time)189*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::OnResponse(TcpPacket packet_info, Timestamp at_time) {
190*d9f75844SAndroid Build Coastguard Worker auto it = in_flight_.find(packet_info.sequence_number);
191*d9f75844SAndroid Build Coastguard Worker if (it != in_flight_.end()) {
192*d9f75844SAndroid Build Coastguard Worker last_rtt_ = at_time - packet_info.send_time;
193*d9f75844SAndroid Build Coastguard Worker in_flight_.erase(it);
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker auto lost_end = in_flight_.lower_bound(packet_info.sequence_number);
196*d9f75844SAndroid Build Coastguard Worker for (auto lost_it = in_flight_.begin(); lost_it != lost_end;
197*d9f75844SAndroid Build Coastguard Worker lost_it = in_flight_.erase(lost_it)) {
198*d9f75844SAndroid Build Coastguard Worker pending_.push_front(lost_it->second.fragment);
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker
201*d9f75844SAndroid Build Coastguard Worker if (packet_info.sequence_number - last_acked_seq_num_ > 1) {
202*d9f75844SAndroid Build Coastguard Worker HandleLoss(at_time);
203*d9f75844SAndroid Build Coastguard Worker } else if (cwnd_ <= ssthresh_) {
204*d9f75844SAndroid Build Coastguard Worker cwnd_ += 1;
205*d9f75844SAndroid Build Coastguard Worker } else {
206*d9f75844SAndroid Build Coastguard Worker cwnd_ += 1.0f / cwnd_;
207*d9f75844SAndroid Build Coastguard Worker }
208*d9f75844SAndroid Build Coastguard Worker last_acked_seq_num_ =
209*d9f75844SAndroid Build Coastguard Worker std::max(packet_info.sequence_number, last_acked_seq_num_);
210*d9f75844SAndroid Build Coastguard Worker SendPackets(at_time);
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker
HandleLoss(Timestamp at_time)213*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::HandleLoss(Timestamp at_time) {
214*d9f75844SAndroid Build Coastguard Worker if (at_time - last_reduction_time_ < last_rtt_)
215*d9f75844SAndroid Build Coastguard Worker return;
216*d9f75844SAndroid Build Coastguard Worker last_reduction_time_ = at_time;
217*d9f75844SAndroid Build Coastguard Worker ssthresh_ = std::max(static_cast<int>(in_flight_.size() / 2), 2);
218*d9f75844SAndroid Build Coastguard Worker cwnd_ = ssthresh_;
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker
SendPackets(Timestamp at_time)221*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::SendPackets(Timestamp at_time) {
222*d9f75844SAndroid Build Coastguard Worker const TimeDelta kPacketTimeout = TimeDelta::Seconds(1);
223*d9f75844SAndroid Build Coastguard Worker int cwnd = std::ceil(cwnd_);
224*d9f75844SAndroid Build Coastguard Worker int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0);
225*d9f75844SAndroid Build Coastguard Worker while (packets_to_send-- > 0 && !pending_.empty()) {
226*d9f75844SAndroid Build Coastguard Worker auto seq_num = next_sequence_number_++;
227*d9f75844SAndroid Build Coastguard Worker TcpPacket send;
228*d9f75844SAndroid Build Coastguard Worker send.sequence_number = seq_num;
229*d9f75844SAndroid Build Coastguard Worker send.send_time = at_time;
230*d9f75844SAndroid Build Coastguard Worker send.fragment = pending_.front();
231*d9f75844SAndroid Build Coastguard Worker pending_.pop_front();
232*d9f75844SAndroid Build Coastguard Worker request_route_.SendPacket(send.fragment.size, send);
233*d9f75844SAndroid Build Coastguard Worker in_flight_.insert({seq_num, send});
234*d9f75844SAndroid Build Coastguard Worker task_queue_->PostDelayedTask(
235*d9f75844SAndroid Build Coastguard Worker [this, seq_num] {
236*d9f75844SAndroid Build Coastguard Worker HandlePacketTimeout(seq_num, clock_->CurrentTime());
237*d9f75844SAndroid Build Coastguard Worker },
238*d9f75844SAndroid Build Coastguard Worker kPacketTimeout);
239*d9f75844SAndroid Build Coastguard Worker }
240*d9f75844SAndroid Build Coastguard Worker }
241*d9f75844SAndroid Build Coastguard Worker
HandlePacketTimeout(int seq_num,Timestamp at_time)242*d9f75844SAndroid Build Coastguard Worker void TcpMessageRouteImpl::HandlePacketTimeout(int seq_num, Timestamp at_time) {
243*d9f75844SAndroid Build Coastguard Worker auto lost = in_flight_.find(seq_num);
244*d9f75844SAndroid Build Coastguard Worker if (lost != in_flight_.end()) {
245*d9f75844SAndroid Build Coastguard Worker pending_.push_front(lost->second.fragment);
246*d9f75844SAndroid Build Coastguard Worker in_flight_.erase(lost);
247*d9f75844SAndroid Build Coastguard Worker HandleLoss(at_time);
248*d9f75844SAndroid Build Coastguard Worker SendPackets(at_time);
249*d9f75844SAndroid Build Coastguard Worker }
250*d9f75844SAndroid Build Coastguard Worker }
251*d9f75844SAndroid Build Coastguard Worker
FakeTcpCrossTraffic(FakeTcpConfig config,EmulatedRoute * send_route,EmulatedRoute * ret_route)252*d9f75844SAndroid Build Coastguard Worker FakeTcpCrossTraffic::FakeTcpCrossTraffic(FakeTcpConfig config,
253*d9f75844SAndroid Build Coastguard Worker EmulatedRoute* send_route,
254*d9f75844SAndroid Build Coastguard Worker EmulatedRoute* ret_route)
255*d9f75844SAndroid Build Coastguard Worker : conf_(config), route_(this, send_route, ret_route) {}
256*d9f75844SAndroid Build Coastguard Worker
GetProcessInterval() const257*d9f75844SAndroid Build Coastguard Worker TimeDelta FakeTcpCrossTraffic::GetProcessInterval() const {
258*d9f75844SAndroid Build Coastguard Worker return conf_.process_interval;
259*d9f75844SAndroid Build Coastguard Worker }
260*d9f75844SAndroid Build Coastguard Worker
Process(Timestamp at_time)261*d9f75844SAndroid Build Coastguard Worker void FakeTcpCrossTraffic::Process(Timestamp at_time) {
262*d9f75844SAndroid Build Coastguard Worker SendPackets(at_time);
263*d9f75844SAndroid Build Coastguard Worker }
264*d9f75844SAndroid Build Coastguard Worker
OnRequest(int sequence_number,Timestamp at_time)265*d9f75844SAndroid Build Coastguard Worker void FakeTcpCrossTraffic::OnRequest(int sequence_number, Timestamp at_time) {
266*d9f75844SAndroid Build Coastguard Worker const size_t kAckPacketSize = 20;
267*d9f75844SAndroid Build Coastguard Worker route_.SendResponse(kAckPacketSize, sequence_number);
268*d9f75844SAndroid Build Coastguard Worker }
269*d9f75844SAndroid Build Coastguard Worker
OnResponse(int sequence_number,Timestamp at_time)270*d9f75844SAndroid Build Coastguard Worker void FakeTcpCrossTraffic::OnResponse(int sequence_number, Timestamp at_time) {
271*d9f75844SAndroid Build Coastguard Worker ack_received_ = true;
272*d9f75844SAndroid Build Coastguard Worker auto it = in_flight_.find(sequence_number);
273*d9f75844SAndroid Build Coastguard Worker if (it != in_flight_.end()) {
274*d9f75844SAndroid Build Coastguard Worker last_rtt_ = at_time - in_flight_.at(sequence_number);
275*d9f75844SAndroid Build Coastguard Worker in_flight_.erase(sequence_number);
276*d9f75844SAndroid Build Coastguard Worker }
277*d9f75844SAndroid Build Coastguard Worker if (sequence_number - last_acked_seq_num_ > 1) {
278*d9f75844SAndroid Build Coastguard Worker HandleLoss(at_time);
279*d9f75844SAndroid Build Coastguard Worker } else if (cwnd_ <= ssthresh_) {
280*d9f75844SAndroid Build Coastguard Worker cwnd_ += 1;
281*d9f75844SAndroid Build Coastguard Worker } else {
282*d9f75844SAndroid Build Coastguard Worker cwnd_ += 1.0f / cwnd_;
283*d9f75844SAndroid Build Coastguard Worker }
284*d9f75844SAndroid Build Coastguard Worker last_acked_seq_num_ = std::max(sequence_number, last_acked_seq_num_);
285*d9f75844SAndroid Build Coastguard Worker SendPackets(at_time);
286*d9f75844SAndroid Build Coastguard Worker }
287*d9f75844SAndroid Build Coastguard Worker
HandleLoss(Timestamp at_time)288*d9f75844SAndroid Build Coastguard Worker void FakeTcpCrossTraffic::HandleLoss(Timestamp at_time) {
289*d9f75844SAndroid Build Coastguard Worker if (at_time - last_reduction_time_ < last_rtt_)
290*d9f75844SAndroid Build Coastguard Worker return;
291*d9f75844SAndroid Build Coastguard Worker last_reduction_time_ = at_time;
292*d9f75844SAndroid Build Coastguard Worker ssthresh_ = std::max(static_cast<int>(in_flight_.size() / 2), 2);
293*d9f75844SAndroid Build Coastguard Worker cwnd_ = ssthresh_;
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker
SendPackets(Timestamp at_time)296*d9f75844SAndroid Build Coastguard Worker void FakeTcpCrossTraffic::SendPackets(Timestamp at_time) {
297*d9f75844SAndroid Build Coastguard Worker int cwnd = std::ceil(cwnd_);
298*d9f75844SAndroid Build Coastguard Worker int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0);
299*d9f75844SAndroid Build Coastguard Worker bool timeouts = false;
300*d9f75844SAndroid Build Coastguard Worker for (auto it = in_flight_.begin(); it != in_flight_.end();) {
301*d9f75844SAndroid Build Coastguard Worker if (it->second < at_time - conf_.packet_timeout) {
302*d9f75844SAndroid Build Coastguard Worker it = in_flight_.erase(it);
303*d9f75844SAndroid Build Coastguard Worker timeouts = true;
304*d9f75844SAndroid Build Coastguard Worker } else {
305*d9f75844SAndroid Build Coastguard Worker ++it;
306*d9f75844SAndroid Build Coastguard Worker }
307*d9f75844SAndroid Build Coastguard Worker }
308*d9f75844SAndroid Build Coastguard Worker if (timeouts)
309*d9f75844SAndroid Build Coastguard Worker HandleLoss(at_time);
310*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < packets_to_send; ++i) {
311*d9f75844SAndroid Build Coastguard Worker if ((total_sent_ + conf_.packet_size) > conf_.send_limit) {
312*d9f75844SAndroid Build Coastguard Worker break;
313*d9f75844SAndroid Build Coastguard Worker }
314*d9f75844SAndroid Build Coastguard Worker in_flight_.insert({next_sequence_number_, at_time});
315*d9f75844SAndroid Build Coastguard Worker route_.SendRequest(conf_.packet_size.bytes<size_t>(),
316*d9f75844SAndroid Build Coastguard Worker next_sequence_number_++);
317*d9f75844SAndroid Build Coastguard Worker total_sent_ += conf_.packet_size;
318*d9f75844SAndroid Build Coastguard Worker }
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker
321*d9f75844SAndroid Build Coastguard Worker } // namespace test
322*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
323