| Index: net/quic/quic_packet_generator.cc
|
| diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
|
| index a7f0af08ade11a8577f4d79ce4ca5ddd1f1f281e..9ee0c3231540edf7112bee7b222e986d4a9f71f5 100644
|
| --- a/net/quic/quic_packet_generator.cc
|
| +++ b/net/quic/quic_packet_generator.cc
|
| @@ -18,15 +18,19 @@ namespace net {
|
| namespace {
|
|
|
| // We want to put some space between a protected packet and the FEC packet to
|
| -// avoid losing them both within the same loss episode. On the other hand,
|
| -// we expect to be able to recover from any loss in about an RTT.
|
| -// We resolve this tradeoff by sending an FEC packet atmost half an RTT,
|
| -// or equivalently, half the max number of in-flight packets, the first
|
| -// protected packet. Since we don't want to delay an FEC packet past half an
|
| -// RTT, we set the max FEC group size to be half the current congestion window.
|
| +// avoid losing them both within the same loss episode. On the other hand, we
|
| +// expect to be able to recover from any loss in about an RTT. We resolve this
|
| +// tradeoff by sending an FEC packet atmost half an RTT, or equivalently, half
|
| +// the max number of in-flight packets, the first protected packet. Since we
|
| +// don't want to delay an FEC packet past half an RTT, we set the max FEC group
|
| +// size to be half the current congestion window.
|
| const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5;
|
| const float kRttMultiplierForFecTimeout = 0.5;
|
|
|
| +// Minimum timeout for FEC alarm, set to half the minimum Tail Loss Probe
|
| +// timeout of 10ms.
|
| +const int64 kMinFecTimeoutMs = 5u;
|
| +
|
| } // namespace
|
|
|
| class QuicAckNotifier;
|
| @@ -235,10 +239,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(
|
|
|
| // Try to close FEC group since we've either run out of data to send or we're
|
| // blocked. If not in batch mode, force close the group.
|
| - // TODO(jri): This method should be called with flush=false here
|
| - // once the timer-based FEC sending is done, to separate FEC sending from
|
| - // the end of batch operations.
|
| - MaybeSendFecPacketAndCloseGroup(!InBatchMode());
|
| + MaybeSendFecPacketAndCloseGroup(/*flush=*/false);
|
|
|
| DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames());
|
| return QuicConsumedData(total_bytes_consumed, fin_consumed);
|
| @@ -265,15 +266,10 @@ void QuicPacketGenerator::SendQueuedFrames(bool flush) {
|
| SerializeAndSendPacket();
|
| }
|
| }
|
| -
|
| - if (!InBatchMode() || flush) {
|
| - if (packet_creator_.HasPendingFrames()) {
|
| - SerializeAndSendPacket();
|
| - }
|
| - // Ensure the FEC group is closed at the end of this method unless other
|
| - // writes are pending.
|
| - MaybeSendFecPacketAndCloseGroup(true);
|
| + if (packet_creator_.HasPendingFrames() && (flush || !InBatchMode())) {
|
| + SerializeAndSendPacket();
|
| }
|
| + MaybeSendFecPacketAndCloseGroup(flush);
|
| }
|
|
|
| void QuicPacketGenerator::MaybeStartFecProtection() {
|
| @@ -299,9 +295,7 @@ void QuicPacketGenerator::MaybeStartFecProtection() {
|
| }
|
|
|
| void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) {
|
| - if (!packet_creator_.IsFecProtected() ||
|
| - packet_creator_.HasPendingFrames() ||
|
| - !packet_creator_.ShouldSendFec(force)) {
|
| + if (!ShouldSendFecPacket(force)) {
|
| return;
|
| }
|
| // TODO(jri): SerializeFec can return a NULL packet, and this should
|
| @@ -319,6 +313,36 @@ void QuicPacketGenerator::MaybeSendFecPacketAndCloseGroup(bool force) {
|
| }
|
| }
|
|
|
| +bool QuicPacketGenerator::ShouldSendFecPacket(bool force) {
|
| + return packet_creator_.IsFecProtected() &&
|
| + !packet_creator_.HasPendingFrames() &&
|
| + packet_creator_.ShouldSendFec(force);
|
| +}
|
| +
|
| +void QuicPacketGenerator::OnFecTimeout() {
|
| + DCHECK(!InBatchMode());
|
| + if (!ShouldSendFecPacket(true)) {
|
| + LOG(DFATAL) << "No FEC packet to send on FEC timeout.";
|
| + return;
|
| + }
|
| + // Flush out any pending frames in the generator and the creator, and then
|
| + // send out FEC packet.
|
| + SendQueuedFrames(true);
|
| + MaybeSendFecPacketAndCloseGroup(/*flush=*/true);
|
| +}
|
| +
|
| +QuicTime::Delta QuicPacketGenerator::GetFecTimeout(
|
| + QuicPacketSequenceNumber sequence_number) {
|
| + // Do not set up FEC alarm for |sequence_number| it is not the first packet in
|
| + // the current group.
|
| + if (packet_creator_.IsFecGroupOpen() &&
|
| + (sequence_number == packet_creator_.fec_group_number())) {
|
| + return QuicTime::Delta::Max(
|
| + fec_timeout_, QuicTime::Delta::FromMilliseconds(kMinFecTimeoutMs));
|
| + }
|
| + return QuicTime::Delta::Infinite();
|
| +}
|
| +
|
| bool QuicPacketGenerator::InBatchMode() {
|
| return batch_mode_;
|
| }
|
| @@ -403,7 +427,7 @@ void QuicPacketGenerator::SerializeAndSendPacket() {
|
| }
|
|
|
| delegate_->OnSerializedPacket(serialized_packet);
|
| - MaybeSendFecPacketAndCloseGroup(false);
|
| + MaybeSendFecPacketAndCloseGroup(/*flush=*/false);
|
|
|
| // The packet has now been serialized, safe to delete pending frames.
|
| if (FLAGS_quic_disallow_multiple_pending_ack_frames) {
|
|
|