xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_network_blackhole_detector.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2020 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_network_blackhole_detector.h"
6 
7 #include "quiche/quic/core/quic_constants.h"
8 
9 namespace quic {
10 
11 namespace {
12 
13 class AlarmDelegate : public QuicAlarm::DelegateWithContext {
14  public:
AlarmDelegate(QuicNetworkBlackholeDetector * detector,QuicConnectionContext * context)15   explicit AlarmDelegate(QuicNetworkBlackholeDetector* detector,
16                          QuicConnectionContext* context)
17       : QuicAlarm::DelegateWithContext(context), detector_(detector) {}
18   AlarmDelegate(const AlarmDelegate&) = delete;
19   AlarmDelegate& operator=(const AlarmDelegate&) = delete;
20 
OnAlarm()21   void OnAlarm() override { detector_->OnAlarm(); }
22 
23  private:
24   QuicNetworkBlackholeDetector* detector_;
25 };
26 
27 }  // namespace
28 
QuicNetworkBlackholeDetector(Delegate * delegate,QuicConnectionArena * arena,QuicAlarmFactory * alarm_factory,QuicConnectionContext * context)29 QuicNetworkBlackholeDetector::QuicNetworkBlackholeDetector(
30     Delegate* delegate, QuicConnectionArena* arena,
31     QuicAlarmFactory* alarm_factory, QuicConnectionContext* context)
32     : delegate_(delegate),
33       alarm_(alarm_factory->CreateAlarm(
34           arena->New<AlarmDelegate>(this, context), arena)) {}
35 
OnAlarm()36 void QuicNetworkBlackholeDetector::OnAlarm() {
37   QuicTime next_deadline = GetEarliestDeadline();
38   if (!next_deadline.IsInitialized()) {
39     QUIC_BUG(quic_bug_10328_1) << "BlackholeDetector alarm fired unexpectedly";
40     return;
41   }
42 
43   QUIC_DVLOG(1) << "BlackholeDetector alarm firing. next_deadline:"
44                 << next_deadline
45                 << ", path_degrading_deadline_:" << path_degrading_deadline_
46                 << ", path_mtu_reduction_deadline_:"
47                 << path_mtu_reduction_deadline_
48                 << ", blackhole_deadline_:" << blackhole_deadline_;
49   if (path_degrading_deadline_ == next_deadline) {
50     path_degrading_deadline_ = QuicTime::Zero();
51     delegate_->OnPathDegradingDetected();
52   }
53 
54   if (path_mtu_reduction_deadline_ == next_deadline) {
55     path_mtu_reduction_deadline_ = QuicTime::Zero();
56     delegate_->OnPathMtuReductionDetected();
57   }
58 
59   if (blackhole_deadline_ == next_deadline) {
60     blackhole_deadline_ = QuicTime::Zero();
61     delegate_->OnBlackholeDetected();
62   }
63 
64   UpdateAlarm();
65 }
66 
StopDetection(bool permanent)67 void QuicNetworkBlackholeDetector::StopDetection(bool permanent) {
68   if (permanent) {
69     alarm_->PermanentCancel();
70   } else {
71     alarm_->Cancel();
72   }
73   path_degrading_deadline_ = QuicTime::Zero();
74   blackhole_deadline_ = QuicTime::Zero();
75   path_mtu_reduction_deadline_ = QuicTime::Zero();
76 }
77 
RestartDetection(QuicTime path_degrading_deadline,QuicTime blackhole_deadline,QuicTime path_mtu_reduction_deadline)78 void QuicNetworkBlackholeDetector::RestartDetection(
79     QuicTime path_degrading_deadline, QuicTime blackhole_deadline,
80     QuicTime path_mtu_reduction_deadline) {
81   path_degrading_deadline_ = path_degrading_deadline;
82   blackhole_deadline_ = blackhole_deadline;
83   path_mtu_reduction_deadline_ = path_mtu_reduction_deadline;
84 
85   QUIC_BUG_IF(quic_bug_12708_1, blackhole_deadline_.IsInitialized() &&
86                                     blackhole_deadline_ != GetLastDeadline())
87       << "Blackhole detection deadline should be the last deadline.";
88 
89   UpdateAlarm();
90 }
91 
GetEarliestDeadline() const92 QuicTime QuicNetworkBlackholeDetector::GetEarliestDeadline() const {
93   QuicTime result = QuicTime::Zero();
94   for (QuicTime t : {path_degrading_deadline_, blackhole_deadline_,
95                      path_mtu_reduction_deadline_}) {
96     if (!t.IsInitialized()) {
97       continue;
98     }
99 
100     if (!result.IsInitialized() || t < result) {
101       result = t;
102     }
103   }
104 
105   return result;
106 }
107 
GetLastDeadline() const108 QuicTime QuicNetworkBlackholeDetector::GetLastDeadline() const {
109   return std::max({path_degrading_deadline_, blackhole_deadline_,
110                    path_mtu_reduction_deadline_});
111 }
112 
UpdateAlarm() const113 void QuicNetworkBlackholeDetector::UpdateAlarm() const {
114   // If called after OnBlackholeDetected(), the alarm may have been permanently
115   // cancelled and is not safe to be armed again.
116   if (alarm_->IsPermanentlyCancelled()) {
117     return;
118   }
119 
120   QuicTime next_deadline = GetEarliestDeadline();
121 
122   QUIC_DVLOG(1) << "Updating alarm. next_deadline:" << next_deadline
123                 << ", path_degrading_deadline_:" << path_degrading_deadline_
124                 << ", path_mtu_reduction_deadline_:"
125                 << path_mtu_reduction_deadline_
126                 << ", blackhole_deadline_:" << blackhole_deadline_;
127 
128   alarm_->Update(next_deadline, kAlarmGranularity);
129 }
130 
IsDetectionInProgress() const131 bool QuicNetworkBlackholeDetector::IsDetectionInProgress() const {
132   return alarm_->IsSet();
133 }
134 
135 }  // namespace quic
136