blob: bbf18b6d7a6c5427d1230e1e5fb4f243dedb3257 [file] [log] [blame]
wubf76cf2a2019-10-11 18:49:07 -07001// Copyright (c) 2019 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 "net/third_party/quiche/src/quic/core/quic_mtu_discovery.h"
6#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
7#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
8
9namespace quic {
10
11QuicConnectionMtuDiscoverer::QuicConnectionMtuDiscoverer(
12 QuicPacketCount packets_between_probes_base,
13 QuicPacketNumber next_probe_at)
14 : packets_between_probes_(packets_between_probes_base),
15 next_probe_at_(next_probe_at) {}
16
17void QuicConnectionMtuDiscoverer::Enable(
18 QuicByteCount max_packet_length,
19 QuicByteCount target_max_packet_length) {
20 DCHECK(!IsEnabled());
21
22 if (target_max_packet_length <= max_packet_length) {
23 QUIC_DVLOG(1) << "MtuDiscoverer not enabled. target_max_packet_length:"
24 << target_max_packet_length
25 << " <= max_packet_length:" << max_packet_length;
26 return;
27 }
28
29 min_probe_length_ = max_packet_length;
30 max_probe_length_ = target_max_packet_length;
31 DCHECK(IsEnabled());
32
33 QUIC_DVLOG(1) << "MtuDiscoverer enabled. min:" << min_probe_length_
34 << ", max:" << max_probe_length_
35 << ", next:" << next_probe_packet_length();
36}
37
38void QuicConnectionMtuDiscoverer::Disable() {
39 *this = QuicConnectionMtuDiscoverer(packets_between_probes_, next_probe_at_);
40}
41
42bool QuicConnectionMtuDiscoverer::IsEnabled() const {
43 return min_probe_length_ < max_probe_length_;
44}
45
46bool QuicConnectionMtuDiscoverer::ShouldProbeMtu(
47 QuicPacketNumber largest_sent_packet) const {
48 if (!IsEnabled()) {
49 return false;
50 }
51
52 if (remaining_probe_count_ == 0) {
53 QUIC_DVLOG(1)
54 << "ShouldProbeMtu returns false because max probe count reached";
55 return false;
56 }
57
58 if (largest_sent_packet < next_probe_at_) {
59 QUIC_DVLOG(1) << "ShouldProbeMtu returns false because not enough packets "
60 "sent since last probe. largest_sent_packet:"
61 << largest_sent_packet
62 << ", next_probe_at_:" << next_probe_at_;
63 return false;
64 }
65
66 QUIC_DVLOG(1) << "ShouldProbeMtu returns true. largest_sent_packet:"
67 << largest_sent_packet;
68 return true;
69}
70
71QuicPacketLength QuicConnectionMtuDiscoverer::GetUpdatedMtuProbeSize(
72 QuicPacketNumber largest_sent_packet) {
73 DCHECK(ShouldProbeMtu(largest_sent_packet));
74
75 QuicPacketLength probe_packet_length = next_probe_packet_length();
76 if (probe_packet_length == last_probe_length_) {
77 // The next probe packet is as big as the previous one. Assuming the
78 // previous one exceeded MTU, we need to decrease the probe packet length.
79 max_probe_length_ = probe_packet_length;
wubf76cf2a2019-10-11 18:49:07 -070080 } else {
81 DCHECK_GT(probe_packet_length, last_probe_length_);
wubf76cf2a2019-10-11 18:49:07 -070082 }
83 last_probe_length_ = next_probe_packet_length();
84
85 packets_between_probes_ *= 2;
86 next_probe_at_ = largest_sent_packet + packets_between_probes_ + 1;
87 if (remaining_probe_count_ > 0) {
88 --remaining_probe_count_;
89 }
90
91 QUIC_DVLOG(1) << "GetUpdatedMtuProbeSize: probe_packet_length:"
92 << last_probe_length_
93 << ", New packets_between_probes_:" << packets_between_probes_
94 << ", next_probe_at_:" << next_probe_at_
95 << ", remaining_probe_count_:" << remaining_probe_count_;
96 DCHECK(!ShouldProbeMtu(largest_sent_packet));
97 return last_probe_length_;
98}
99
100QuicPacketLength QuicConnectionMtuDiscoverer::next_probe_packet_length() const {
101 DCHECK_NE(min_probe_length_, 0);
102 DCHECK_NE(max_probe_length_, 0);
103 DCHECK_GE(max_probe_length_, min_probe_length_);
104
105 const QuicPacketLength normal_next_probe_length =
106 (min_probe_length_ + max_probe_length_ + 1) / 2;
107
108 if (remaining_probe_count_ == 1 &&
109 normal_next_probe_length > last_probe_length_) {
110 // If the previous probe succeeded, and there is only one last probe to
111 // send, use |max_probe_length_| for the last probe.
112 return max_probe_length_;
113 }
114 return normal_next_probe_length;
115}
116
117void QuicConnectionMtuDiscoverer::OnMaxPacketLengthUpdated(
118 QuicByteCount old_value,
119 QuicByteCount new_value) {
120 if (!IsEnabled() || new_value <= old_value) {
121 return;
122 }
123
124 DCHECK_EQ(old_value, min_probe_length_);
125 min_probe_length_ = new_value;
wubf76cf2a2019-10-11 18:49:07 -0700126}
127
128std::ostream& operator<<(std::ostream& os,
129 const QuicConnectionMtuDiscoverer& d) {
130 os << "{ min_probe_length_:" << d.min_probe_length_
131 << " max_probe_length_:" << d.max_probe_length_
132 << " last_probe_length_:" << d.last_probe_length_
133 << " remaining_probe_count_:" << d.remaining_probe_count_
134 << " packets_between_probes_:" << d.packets_between_probes_
135 << " next_probe_at_:" << d.next_probe_at_ << " }";
136 return os;
137}
138
139} // namespace quic