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 #ifndef QUICHE_QUIC_CORE_QUIC_MTU_DISCOVERY_H_
6 #define QUICHE_QUIC_CORE_QUIC_MTU_DISCOVERY_H_
7 
8 #include <iostream>
9 
10 #include "net/third_party/quiche/src/quic/core/quic_constants.h"
11 #include "net/third_party/quiche/src/quic/core/quic_types.h"
12 
13 namespace quic {
14 
15 // The initial number of packets between MTU probes.  After each attempt the
16 // number is doubled.
17 const QuicPacketCount kPacketsBetweenMtuProbesBase = 100;
18 
19 // The number of MTU probes that get sent before giving up.
20 const size_t kMtuDiscoveryAttempts = 3;
21 
22 // Ensure that exponential back-off does not result in an integer overflow.
23 // The number of packets can be potentially capped, but that is not useful at
24 // current kMtuDiscoveryAttempts value, and hence is not implemented at present.
25 static_assert(kMtuDiscoveryAttempts + 8 < 8 * sizeof(QuicPacketNumber),
26               "The number of MTU discovery attempts is too high");
27 static_assert(kPacketsBetweenMtuProbesBase < (1 << 8),
28               "The initial number of packets between MTU probes is too high");
29 
30 // The incresed packet size targeted when doing path MTU discovery.
31 const QuicByteCount kMtuDiscoveryTargetPacketSizeHigh = 1450;
32 const QuicByteCount kMtuDiscoveryTargetPacketSizeLow = 1430;
33 
34 static_assert(kMtuDiscoveryTargetPacketSizeLow <= kMaxOutgoingPacketSize,
35               "MTU discovery target is too large");
36 static_assert(kMtuDiscoveryTargetPacketSizeHigh <= kMaxOutgoingPacketSize,
37               "MTU discovery target is too large");
38 
39 static_assert(kMtuDiscoveryTargetPacketSizeLow > kDefaultMaxPacketSize,
40               "MTU discovery target does not exceed the default packet size");
41 static_assert(kMtuDiscoveryTargetPacketSizeHigh > kDefaultMaxPacketSize,
42               "MTU discovery target does not exceed the default packet size");
43 
44 // QuicConnectionMtuDiscoverer is a MTU discovery controller, it answers two
45 // questions:
46 // 1) Probe scheduling: Whether a connection should send a MTU probe packet
47 //    right now.
48 // 2) MTU search stradegy: When it is time to send, what should be the size of
49 //    the probing packet.
50 // Note the discoverer does not actually send or process probing packets.
51 //
52 // Unit tests are in QuicConnectionTest.MtuDiscovery*.
53 class QUIC_EXPORT_PRIVATE QuicConnectionMtuDiscoverer {
54  public:
55   // Construct a discoverer in the disabled state.
56   QuicConnectionMtuDiscoverer() = default;
57 
58   // Construct a discoverer in the disabled state, with the given parameters.
59   QuicConnectionMtuDiscoverer(QuicPacketCount packets_between_probes_base,
60                               QuicPacketNumber next_probe_at);
61 
62   // Enable the discoverer by setting the probe target.
63   // max_packet_length: The max packet length currently used.
64   // target_max_packet_length: The target max packet length to probe.
65   void Enable(QuicByteCount max_packet_length,
66               QuicByteCount target_max_packet_length);
67 
68   // Disable the discoverer by unsetting the probe target.
69   void Disable();
70 
71   // Whether a MTU probe packet should be sent right now.
72   // Always return false if disabled.
73   bool ShouldProbeMtu(QuicPacketNumber largest_sent_packet) const;
74 
75   // Called immediately before a probing packet is sent, to get the size of the
76   // packet.
77   // REQUIRES: ShouldProbeMtu(largest_sent_packet) == true.
78   QuicPacketLength GetUpdatedMtuProbeSize(QuicPacketNumber largest_sent_packet);
79 
80   // Called after the max packet length is updated, which is triggered by a ack
81   // of a probing packet.
82   void OnMaxPacketLengthUpdated(QuicByteCount old_value,
83                                 QuicByteCount new_value);
84 
packets_between_probes()85   QuicPacketCount packets_between_probes() const {
86     return packets_between_probes_;
87   }
88 
next_probe_at()89   QuicPacketNumber next_probe_at() const { return next_probe_at_; }
90 
91   QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
92       std::ostream& os,
93       const QuicConnectionMtuDiscoverer& d);
94 
95  private:
96   bool IsEnabled() const;
97   QuicPacketLength next_probe_packet_length() const;
98 
99   QuicPacketLength min_probe_length_ = 0;
100   QuicPacketLength max_probe_length_ = 0;
101 
102   QuicPacketLength last_probe_length_ = 0;
103 
104   uint16_t remaining_probe_count_ = kMtuDiscoveryAttempts;
105 
106   // The number of packets between MTU probes.
107   QuicPacketCount packets_between_probes_ = kPacketsBetweenMtuProbesBase;
108 
109   // The packet number of the packet after which the next MTU probe will be
110   // sent.
111   QuicPacketNumber next_probe_at_ =
112       QuicPacketNumber(kPacketsBetweenMtuProbesBase);
113 };
114 
115 }  // namespace quic
116 
117 #endif  // QUICHE_QUIC_CORE_QUIC_MTU_DISCOVERY_H_
118