dcsctp: Add burst limiter for sent packets
Some deployments, e.g. Chromium, has a limited send buffer. It's reasonable that it's quite small, as it avoids queuing too much, which typically results in increased latency for real-time communication. To avoid SCTP to fill up the entire buffer at once - especially when doing fast retransmissions - limit the amount of packets that are sent in one go. In a typical scenario, SCTP will not send more than three packets for each incoming packet, which is is the case when a SACK is received which has acknowledged two large packets, and which also adds the MTU to the congestion window (due to in slow-start mode), which then may result in sending three packets. So setting this value to four makes any retransmission not use that much more of the send buffer. This is analogous to usrsctp_sysctl_set_sctp_fr_max_burst_default in usrsctp, which also has the default value of four (4). Bug: webrtc:12943 Change-Id: Iff76a1668beadc8776fab10312ef9ee26f24e442 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/228480 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Victor Boivie <boivie@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34744}
This commit is contained in:
parent
a9e7f719a9
commit
e0fb45c6d4
@ -132,6 +132,14 @@ struct DcSctpOptions {
|
||||
// See https://tools.ietf.org/html/rfc4960#section-7.2.3.
|
||||
size_t cwnd_mtus_min = 4;
|
||||
|
||||
// The number of packets that may be sent at once. This is limited to avoid
|
||||
// bursts that too quickly fill the send buffer. Typically in a a socket in
|
||||
// its "slow start" phase (when it sends as much as it can), it will send
|
||||
// up to three packets for every SACK received, so the default limit is set
|
||||
// just above that, and then mostly applicable for (but not limited to) fast
|
||||
// retransmission scenarios.
|
||||
int max_burst = 4;
|
||||
|
||||
// Maximum Data Retransmit Attempts (per DATA chunk).
|
||||
int max_retransmissions = 10;
|
||||
|
||||
|
||||
@ -62,7 +62,8 @@ using ::testing::SizeIs;
|
||||
|
||||
constexpr SendOptions kSendOptions;
|
||||
constexpr size_t kLargeMessageSize = DcSctpOptions::kMaxSafeMTUSize * 20;
|
||||
static constexpr size_t kSmallMessageSize = 10;
|
||||
constexpr size_t kSmallMessageSize = 10;
|
||||
constexpr int kMaxBurstPackets = 4;
|
||||
|
||||
MATCHER_P(HasDataChunkWithStreamId, stream_id, "") {
|
||||
absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
|
||||
@ -235,6 +236,7 @@ DcSctpOptions MakeOptionsForTest(bool enable_message_interleaving) {
|
||||
// To make the interval more predictable in tests.
|
||||
options.heartbeat_interval_include_rtt = false;
|
||||
options.enable_message_interleaving = enable_message_interleaving;
|
||||
options.max_burst = kMaxBurstPackets;
|
||||
return options;
|
||||
}
|
||||
|
||||
@ -1713,5 +1715,21 @@ TEST_F(DcSctpSocketTest, UnackDataAlsoIncludesSendQueue) {
|
||||
expected_sent_packets + expected_queued_packets + 2);
|
||||
}
|
||||
|
||||
TEST_F(DcSctpSocketTest, DoesntSendMoreThanMaxBurstPackets) {
|
||||
ConnectSockets();
|
||||
|
||||
sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
|
||||
std::vector<uint8_t>(kLargeMessageSize)),
|
||||
kSendOptions);
|
||||
|
||||
for (int i = 0; i < kMaxBurstPackets; ++i) {
|
||||
std::vector<uint8_t> packet = cb_a_.ConsumeSentPacket();
|
||||
EXPECT_THAT(packet, Not(IsEmpty()));
|
||||
sock_z_.ReceivePacket(std::move(packet)); // DATA
|
||||
}
|
||||
|
||||
EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace dcsctp
|
||||
|
||||
@ -84,7 +84,7 @@ void TransmissionControlBlock::MaybeSendSack() {
|
||||
|
||||
void TransmissionControlBlock::SendBufferedPackets(SctpPacket::Builder& builder,
|
||||
TimeMs now) {
|
||||
for (int packet_idx = 0;; ++packet_idx) {
|
||||
for (int packet_idx = 0; packet_idx < options_.max_burst; ++packet_idx) {
|
||||
// Only add control chunks to the first packet that is sent, if sending
|
||||
// multiple packets in one go (as allowed by the congestion window).
|
||||
if (packet_idx == 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user