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