Skip to content

Commit 956a5ea

Browse files
Matt Jorasfacebook-github-bot
authored andcommitted
Remove throws from addition and subtraction CC utilities
Summary: Throwing here causes the connection to close. Rather than trying to preserve that behavior, we instead cap the addition/subtraction, log the error, and allow the connection to continue. This kind of problem shouldn't happen in practice and represents a bug that should be fixed if it does. Reviewed By: jbeshay Differential Revision: D75009366 fbshipit-source-id: 8d000f1965191504f2a5be70ddd5141087efaf26
1 parent 2e401b1 commit 956a5ea

File tree

7 files changed

+72
-28
lines changed

7 files changed

+72
-28
lines changed

quic/congestion_control/Bbr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ void BbrCongestionController::onPacketSent(
128128
exitingQuiescene_ = true;
129129
}
130130
addAndCheckOverflow(
131-
conn_.lossState.inflightBytes, packet.metadata.encodedSize);
131+
conn_.lossState.inflightBytes,
132+
packet.metadata.encodedSize,
133+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
132134
if (!ackAggregationStartTime_) {
133135
ackAggregationStartTime_ = packet.metadata.time;
134136
}

quic/congestion_control/Bbr2.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ void Bbr2CongestionController::onPacketSent(
9090
}
9191

9292
addAndCheckOverflow(
93-
conn_.lossState.inflightBytes, packet.metadata.encodedSize);
93+
conn_.lossState.inflightBytes,
94+
packet.metadata.encodedSize,
95+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
9496

9597
// Maintain cwndLimited flag. We consider the transport being cwnd limited if
9698
// we are using > 90% of the cwnd.
@@ -771,7 +773,10 @@ void Bbr2CongestionController::probeInflightLongTermUpward() {
771773
if (probeUpAcks_ >= probeUpCount_) {
772774
auto delta = probeUpAcks_ / probeUpCount_;
773775
probeUpAcks_ -= delta * probeUpCount_;
774-
addAndCheckOverflow(*inflightLongTerm_, delta);
776+
addAndCheckOverflow(
777+
*inflightLongTerm_,
778+
delta,
779+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
775780
}
776781
if (roundStart_) {
777782
raiseInflightLongTermSlope();

quic/congestion_control/CongestionControlFunctions.h

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <quic/state/StateData.h>
1111

1212
#include <chrono>
13-
#include <utility>
1413

1514
namespace quic {
1615

@@ -26,24 +25,41 @@ PacingRate calculatePacingRate(
2625
uint64_t minCwndInMss,
2726
std::chrono::microseconds rtt);
2827

29-
template <class T1, class T2>
30-
void addAndCheckOverflow(T1& value, const T2& toAdd) {
31-
if (std::numeric_limits<T1>::max() - toAdd < value) {
32-
// TODO: the error code is CWND_OVERFLOW but this function can totally be
33-
// used for inflight bytes.
34-
throw quic::QuicInternalException(
35-
"Overflow bytes in flight", quic::LocalErrorCode::CWND_OVERFLOW);
28+
template <class T1, class T2, class T3 = T1>
29+
void addAndCheckOverflow(
30+
T1& value,
31+
const T2& toAdd,
32+
const T3& maxValue = std::numeric_limits<T1>::max()) {
33+
if (std::numeric_limits<T1>::max() - static_cast<T1>(toAdd) < value) {
34+
LOG(ERROR) << "Overflow prevented, capping at max value";
35+
value = static_cast<T1>(maxValue);
36+
} else {
37+
T1 newValue = value + static_cast<T1>(toAdd);
38+
if (newValue > static_cast<T1>(maxValue)) {
39+
LOG(ERROR) << "Value would exceed max limit, capping at max value";
40+
value = static_cast<T1>(maxValue);
41+
} else {
42+
value = newValue;
43+
}
3644
}
37-
value += folly::to<T1>(toAdd);
3845
}
3946

40-
template <class T1, class T2>
41-
void subtractAndCheckUnderflow(T1& value, const T2& toSub) {
42-
if (value < toSub) {
43-
// TODO: wrong error code
44-
throw quic::QuicInternalException(
45-
"Underflow bytes in flight", quic::LocalErrorCode::CWND_OVERFLOW);
47+
template <class T1, class T2, class T3 = T1>
48+
void subtractAndCheckUnderflow(
49+
T1& value,
50+
const T2& toSub,
51+
const T3& minValue = 0) {
52+
if (value < static_cast<T1>(toSub)) {
53+
LOG(ERROR) << "Underflow prevented, capping at min value";
54+
value = static_cast<T1>(minValue);
55+
} else {
56+
T1 newValue = value - static_cast<T1>(toSub);
57+
if (newValue < static_cast<T1>(minValue)) {
58+
LOG(ERROR) << "Value would be below min limit, capping at min value";
59+
value = static_cast<T1>(minValue);
60+
} else {
61+
value = newValue;
62+
}
4663
}
47-
value -= folly::to<T1>(toSub);
4864
}
4965
} // namespace quic

quic/congestion_control/Copa.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ void Copa::onRemoveBytesFromInflight(uint64_t bytes) {
4646

4747
void Copa::onPacketSent(const OutstandingPacketWrapper& packet) {
4848
addAndCheckOverflow(
49-
conn_.lossState.inflightBytes, packet.metadata.encodedSize);
49+
conn_.lossState.inflightBytes,
50+
packet.metadata.encodedSize,
51+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
5052

5153
VLOG(10) << __func__ << " writable=" << getWritableBytes()
5254
<< " cwnd=" << cwndBytes_
@@ -239,7 +241,10 @@ void Copa::onPacketAcked(const AckEvent& ack) {
239241
ack.ackTime - lastCwndDoubleTime_.value() > conn_.lossState.srtt) {
240242
VLOG(10) << __func__ << " doubling cwnd per RTT from=" << cwndBytes_
241243
<< " due to slow start" << " " << conn_;
242-
addAndCheckOverflow(cwndBytes_, cwndBytes_);
244+
addAndCheckOverflow(
245+
cwndBytes_,
246+
cwndBytes_,
247+
conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
243248
lastCwndDoubleTime_ = ack.ackTime;
244249
}
245250
} else {
@@ -256,7 +261,10 @@ void Copa::onPacketAcked(const AckEvent& ack) {
256261
(deltaParam_ * cwndBytes_);
257262
VLOG(10) << __func__ << " increasing cwnd from=" << cwndBytes_ << " by "
258263
<< addition << " " << conn_;
259-
addAndCheckOverflow(cwndBytes_, addition);
264+
addAndCheckOverflow(
265+
cwndBytes_,
266+
addition,
267+
conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
260268
}
261269
} else {
262270
if (velocityState_.direction != VelocityState::Direction::Down &&
@@ -278,7 +286,8 @@ void Copa::onPacketAcked(const AckEvent& ack) {
278286
std::min<uint64_t>(
279287
reduction,
280288
cwndBytes_ -
281-
conn_.transportSettings.minCwndInMss * conn_.udpSendPacketLen));
289+
conn_.transportSettings.minCwndInMss * conn_.udpSendPacketLen),
290+
conn_.transportSettings.minCwndInMss * conn_.udpSendPacketLen);
282291
}
283292
if (conn_.pacer) {
284293
conn_.pacer->refreshPacingRate(cwndBytes_ * 2, conn_.lossState.srtt);

quic/congestion_control/Copa2.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ void Copa2::onRemoveBytesFromInflight(uint64_t bytes) {
3636

3737
void Copa2::onPacketSent(const OutstandingPacketWrapper& packet) {
3838
addAndCheckOverflow(
39-
conn_.lossState.inflightBytes, packet.metadata.encodedSize);
39+
conn_.lossState.inflightBytes,
40+
packet.metadata.encodedSize,
41+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
4042

4143
VLOG(10) << __func__ << " writable=" << getWritableBytes()
4244
<< " cwnd=" << cwndBytes_

quic/congestion_control/NewReno.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ void NewReno::onRemoveBytesFromInflight(uint64_t bytes) {
3838

3939
void NewReno::onPacketSent(const OutstandingPacketWrapper& packet) {
4040
addAndCheckOverflow(
41-
conn_.lossState.inflightBytes, packet.metadata.encodedSize);
41+
conn_.lossState.inflightBytes,
42+
packet.metadata.encodedSize,
43+
2 * conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
4244
VLOG(10) << __func__ << " writable=" << getWritableBytes()
4345
<< " cwnd=" << cwndBytes_
4446
<< " inflight=" << conn_.lossState.inflightBytes
@@ -82,15 +84,20 @@ void NewReno::onPacketAcked(
8284
}
8385
if (cwndBytes_ < ssthresh_) {
8486
addAndCheckOverflow(
85-
cwndBytes_, packet.outstandingPacketMetadata.encodedSize);
87+
cwndBytes_,
88+
packet.outstandingPacketMetadata.encodedSize,
89+
conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
8690
} else {
8791
// TODO: I think this may be a bug in the specs. We should use
8892
// conn_.udpSendPacketLen for the cwnd calculation. But I need to
8993
// check how Linux handles this.
9094
uint64_t additionFactor = (kDefaultUDPSendPacketLen *
9195
packet.outstandingPacketMetadata.encodedSize) /
9296
cwndBytes_;
93-
addAndCheckOverflow(cwndBytes_, additionFactor);
97+
addAndCheckOverflow(
98+
cwndBytes_,
99+
additionFactor,
100+
conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
94101
}
95102
}
96103

quic/congestion_control/StaticCwndCongestionController.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ void StaticCwndCongestionController::onRemoveBytesFromInflight(
2626
void StaticCwndCongestionController::onPacketSent(
2727
const OutstandingPacketWrapper& packet) {
2828
isAppLimited_ = false;
29-
addAndCheckOverflow(inflightBytes_, packet.metadata.encodedSize);
29+
addAndCheckOverflow(
30+
inflightBytes_,
31+
packet.metadata.encodedSize,
32+
conn_.transportSettings.maxCwndInMss * conn_.udpSendPacketLen);
3033
}
3134

3235
void StaticCwndCongestionController::onPacketAckOrLoss(

0 commit comments

Comments
 (0)