Commit ef442aa7 authored by rch@chromium.org's avatar rch@chromium.org

Adding transmission times for every QUIC packet received in the AckFrame.

Making the scheduler a strict mock for quic connection test.

Merge internal change: 39116450
Merge internal change: 38802607


Review URL: https://chromiumcodereview.appspot.com/11416155

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171096 0039d316-1c4b-4281-b951-d872f2087c98
parent e490611e
......@@ -97,8 +97,7 @@ void QuicSendScheduler::OnIncomingAckFrame(const QuicAckFrame& ack_frame) {
while (it != it_upper) {
QuicPacketSequenceNumber sequence_number = it->first;
if (ack_frame.received_info.missing_packets.find(sequence_number) ==
ack_frame.received_info.missing_packets.end()) {
if (ack_frame.received_info.ContainsAck(sequence_number)) {
// Not missing, hence implicitly acked.
scoped_ptr<PendingPacket> pending_packet_cleaner(it->second);
acked_packets[sequence_number] = pending_packet_cleaner->BytesSent();
......
......@@ -59,7 +59,7 @@ TEST_F(QuicSendSchedulerTest, FixedRatePacing) {
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packet we sent.
ack.received_info.largest_received = i;
ack.received_info.RecordAck(i, acc_advance_time);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(QuicTime::FromMilliseconds(1200), acc_advance_time);
......@@ -78,8 +78,10 @@ TEST_F(QuicSendSchedulerTest, AvailableCongestionWindow) {
sender_->SentPacket(i, 100, false);
EXPECT_EQ(kMaxPacketSize - (i * 100), sender_->AvailableCongestionWindow());
}
// Ack the packet we sent.
ack.received_info.largest_received = 12;
// Ack the packets we sent.
for (int i = 1; i <= 12; i++) {
ack.received_info.RecordAck(i, QuicTime::FromMilliseconds(100));
}
sender_->OnIncomingAckFrame(ack);
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
}
......@@ -97,7 +99,7 @@ TEST_F(QuicSendSchedulerTest, FixedRateBandwidth) {
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i, 1000, false);
// Ack the packet we sent.
ack.received_info.largest_received = i;
ack.received_info.RecordAck(i, clock_.Now());
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
......@@ -117,7 +119,7 @@ TEST_F(QuicSendSchedulerTest, BandwidthWith3SecondGap) {
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i, 1000, false);
// Ack the packet we sent.
ack.received_info.largest_received = i;
ack.received_info.RecordAck(i, clock_.Now());
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
......@@ -135,7 +137,7 @@ TEST_F(QuicSendSchedulerTest, BandwidthWith3SecondGap) {
sender_->SentPacket(i + 100, 1000, false);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
// Ack the packet we sent.
ack.received_info.largest_received = i + 100;
ack.received_info.RecordAck(i + 100, clock_.Now());
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
......@@ -162,9 +164,9 @@ TEST_F(QuicSendSchedulerTest, Pacing) {
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packets we sent.
ack.received_info.largest_received = i - 2;
ack.received_info.RecordAck(i - 2, clock_.Now());
sender_->OnIncomingAckFrame(ack);
ack.received_info.largest_received = i - 1;
ack.received_info.RecordAck(i - 1, clock_.Now());
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(QuicTime::FromMilliseconds(120), acc_advance_time);
......
......@@ -24,14 +24,14 @@ using std::set;
namespace net {
// An arbitrary number we'll probably want to tune.
const QuicPacketSequenceNumber kMaxUnackedPackets = 5000u;
const QuicPacketSequenceNumber kMaxAckedPackets = 5000u;
// The amount of time we wait before resending a packet.
const int64 kDefaultResendTimeMs = 500;
bool Near(QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) {
QuicPacketSequenceNumber delta = (a > b) ? a - b : b - a;
return delta <= kMaxUnackedPackets;
return delta <= kMaxAckedPackets;
}
QuicConnection::QuicConnection(QuicGuid guid,
......@@ -105,8 +105,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
ReceivedPacketInfo info = outgoing_ack_.received_info;
// If this packet has already been seen, or that the sender
// has told us will not be resent, then stop processing the packet.
if (header.packet_sequence_number <= info.largest_received &&
info.missing_packets.count(header.packet_sequence_number) != 1) {
if (info.ContainsAck(header.packet_sequence_number)) {
return false;
}
......@@ -168,12 +167,10 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
return false;
}
// We can't have too many missing or retransmitting packets, or our ack
// frames go over kMaxPacketSize.
DCHECK_LT(incoming_ack.received_info.missing_packets.size(),
kMaxUnackedPackets);
DCHECK_LT(incoming_ack.sent_info.non_retransmiting.size(),
kMaxUnackedPackets);
// We can't have too many acked packets, or our ack frames go over
// kMaxPacketSize.
DCHECK_LT(incoming_ack.received_info.received_packet_times.size(),
kMaxAckedPackets);
if (incoming_ack.sent_info.least_unacked != 0 &&
incoming_ack.sent_info.least_unacked < least_packet_awaiting_ack_) {
......@@ -199,9 +196,7 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
// incoming_ack shows they've been seen by the peer.
UnackedPacketMap::iterator it = unacked_packets_.begin();
while (it != unacked_packets_.end()) {
if ((it->first < incoming_ack.received_info.largest_received &&
!ContainsKey(incoming_ack.received_info.missing_packets, it->first)) ||
it->first == incoming_ack.received_info.largest_received) {
if (incoming_ack.received_info.ContainsAck(it->first)) {
// Packet was acked, so remove it from our unacked packet list.
DVLOG(1) << "Got an ack for " << it->first;
// TODO(rch): This is inefficient and should be sped up.
......@@ -236,17 +231,9 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
// If we've gotten an ack for the lowest packet we were waiting on,
// update that and the list of packets we advertise we will not resend.
if (lowest_unacked > outgoing_ack_.sent_info.least_unacked) {
SequenceSet* non_retrans = &outgoing_ack_.sent_info.non_retransmiting;
// We don't need to advertise not-resending packets between the old
// and new values.
for (QuicPacketSequenceNumber i = outgoing_ack_.sent_info.least_unacked;
i < lowest_unacked; ++i) {
non_retrans->erase(i);
}
// If all packets we sent have been acked, use the special value of 0
if (lowest_unacked > packet_creator_.sequence_number()) {
lowest_unacked = 0;
DCHECK_EQ(0u, non_retrans->size());
}
outgoing_ack_.sent_info.least_unacked = lowest_unacked;
}
......@@ -254,22 +241,11 @@ void QuicConnection::UpdatePacketInformationReceivedByPeer(
void QuicConnection::UpdatePacketInformationSentByPeer(
const QuicAckFrame& incoming_ack) {
// Iteratate through the packets which will the peer will not resend and
// remove them from our missing list.
for (SequenceSet::const_iterator it =
incoming_ack.sent_info.non_retransmiting.begin();
it != incoming_ack.sent_info.non_retransmiting.end(); ++it) {
DVLOG(1) << "no longer expecting " << *it;
outgoing_ack_.received_info.missing_packets.erase(*it);
}
// Make sure we also don't expect any packets lower than the peer's
// Make sure we also don't ack any packets lower than the peer's
// last-packet-awaiting-ack.
if (incoming_ack.sent_info.least_unacked > least_packet_awaiting_ack_) {
for (QuicPacketSequenceNumber i = least_packet_awaiting_ack_;
i < incoming_ack.sent_info.least_unacked; ++i) {
outgoing_ack_.received_info.missing_packets.erase(i);
}
outgoing_ack_.received_info.ClearAcksBefore(
incoming_ack.sent_info.least_unacked);
least_packet_awaiting_ack_ = incoming_ack.sent_info.least_unacked;
}
......@@ -394,23 +370,7 @@ bool QuicConnection::OnCanWrite() {
void QuicConnection::AckPacket(const QuicPacketHeader& header) {
QuicPacketSequenceNumber sequence_number = header.packet_sequence_number;
if (sequence_number > outgoing_ack_.received_info.largest_received) {
// We've got a new high sequence number. Note any new intermediate missing
// packets, and update the last_ack data.
for (QuicPacketSequenceNumber i =
outgoing_ack_.received_info.largest_received + 1;
i < sequence_number; ++i) {
DVLOG(1) << "missing " << i;
outgoing_ack_.received_info.missing_packets.insert(i);
}
outgoing_ack_.received_info.largest_received = sequence_number;
outgoing_ack_.received_info.time_received = clock_->Now();
} else {
// We've gotten one of the out of order packets - remove it from our
// "missing packets" list.
DVLOG(1) << "Removing " << sequence_number << " from missing list";
outgoing_ack_.received_info.missing_packets.erase(sequence_number);
}
outgoing_ack_.received_info.RecordAck(sequence_number, clock_->Now());
// TODO(alyssar) delay sending until we have data, or enough time has elapsed.
if (frames_.size() > 0) {
SendAck();
......@@ -471,11 +431,6 @@ bool QuicConnection::SendPacket(QuicPacketSequenceNumber sequence_number,
sequence_number < outgoing_ack_.sent_info.least_unacked) {
outgoing_ack_.sent_info.least_unacked = sequence_number;
}
} else {
if (outgoing_ack_.sent_info.least_unacked != 0 &&
sequence_number > outgoing_ack_.sent_info.least_unacked) {
outgoing_ack_.sent_info.non_retransmiting.insert(sequence_number);
}
}
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(*packet));
......
......@@ -132,9 +132,9 @@ class QuicConnectionHelperTest : public ::testing::Test {
InitializeHeader(sequence_number);
QuicAckFrame ack(0, QuicTime(), 0);
ack.congestion_info.type = kFixRate;
ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
return ConstructPacket(header_, QuicFrame(&ack));
}
......
This diff is collapsed.
......@@ -12,6 +12,7 @@
#include "net/quic/quic_utils.h"
using base::StringPiece;
using std::map;
namespace net {
......@@ -353,31 +354,46 @@ bool QuicFramer::ProcessPDUFrame() {
}
bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
if (!reader_->ReadUInt48(&frame->received_info.largest_received)) {
set_detailed_error("Unable to read largest received.");
uint8 num_acked_packets;
if (!reader_->ReadBytes(&num_acked_packets, 1)) {
set_detailed_error("Unable to read num acked packets.");
return false;
}
uint64 time_received;
if (!reader_->ReadUInt64(&time_received)) {
set_detailed_error("Unable to read time received.");
return false;
}
frame->received_info.time_received =
QuicTime::FromMicroseconds(time_received);
uint8 num_unacked_packets;
if (!reader_->ReadBytes(&num_unacked_packets, 1)) {
set_detailed_error("Unable to read num unacked packets.");
uint64 smallest_received;
if (!reader_->ReadUInt48(&smallest_received)) {
set_detailed_error("Unable to read smallest received.");
return false;
}
for (int i = 0; i < num_unacked_packets; ++i) {
QuicPacketSequenceNumber sequence_number;
if (!reader_->ReadUInt48(&sequence_number)) {
set_detailed_error("Unable to read sequence number in unacked packets.");
if (num_acked_packets == 0u) {
// Ensures largest_received is set when no actual acks are transmitted.
frame->received_info.largest_received = smallest_received;
} else {
uint64 time_received_us;
if (!reader_->ReadUInt64(&time_received_us)) {
set_detailed_error("Unable to read time received.");
return false;
}
frame->received_info.missing_packets.insert(sequence_number);
frame->received_info.RecordAck(
smallest_received, QuicTime::FromMicroseconds(time_received_us));
for (int i = 0; i < num_acked_packets - 1; ++i) {
uint8 sequence_delta;
if (!reader_->ReadBytes(&sequence_delta, 1)) {
set_detailed_error("Unable to read sequence delta in acked packets.");
return false;
}
int32 time_delta_us;
if (!reader_->ReadBytes(&time_delta_us, sizeof(time_delta_us))) {
set_detailed_error("Unable to read time delta in acked packets.");
return false;
}
frame->received_info.RecordAck(
smallest_received + sequence_delta,
QuicTime::FromMicroseconds(time_received_us + time_delta_us));
}
}
if (!reader_->ReadUInt48(&frame->sent_info.least_unacked)) {
......@@ -385,21 +401,6 @@ bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
return false;
}
uint8 num_non_retransmiting_packets;
if (!reader_->ReadBytes(&num_non_retransmiting_packets, 1)) {
set_detailed_error("Unable to read num non-retransmitting.");
return false;
}
for (uint8 i = 0; i < num_non_retransmiting_packets; ++i) {
QuicPacketSequenceNumber sequence_number;
if (!reader_->ReadUInt48(&sequence_number)) {
set_detailed_error(
"Unable to read sequence number in non-retransmitting.");
return false;
}
frame->sent_info.non_retransmiting.insert(sequence_number);
}
uint8 congestion_info_type;
if (!reader_->ReadBytes(&congestion_info_type, 1)) {
set_detailed_error("Unable to read congestion info type.");
......@@ -582,13 +583,13 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) {
break; // Need to support this eventually :>
case ACK_FRAME: {
const QuicAckFrame& ack = *frame.ack_frame;
len += 1; // num acked packets
len += 6; // largest received packet sequence number
len += 8; // time delta
len += 1; // num missing packets
len += 6 * ack.received_info.missing_packets.size();
if (ack.received_info.received_packet_times.size() > 0) {
len += 8; // time
len += 5 * (ack.received_info.received_packet_times.size() - 1);
}
len += 6; // least packet sequence number awaiting an ack
len += 1; // num non retransmitting packets
len += 6 * ack.sent_info.non_retransmiting.size();
len += 1; // congestion control type
switch (ack.congestion_info.type) {
case kNone:
......@@ -656,43 +657,46 @@ bool QuicFramer::AppendStreamFramePayload(
bool QuicFramer::AppendAckFramePayload(
const QuicAckFrame& frame,
QuicDataWriter* writer) {
if (!writer->WriteUInt48(frame.received_info.largest_received)) {
return false;
}
if (!writer->WriteUInt64(
frame.received_info.time_received.ToMicroseconds())) {
uint8 num_acked_packets = frame.received_info.received_packet_times.size();
if (!writer->WriteBytes(&num_acked_packets, 1)) {
return false;
}
if (num_acked_packets == 0) {
// Special case when no packets are acked, just transmit the largest.
if (!writer->WriteUInt48(frame.received_info.largest_received)) {
return false;
}
} else {
map<QuicPacketSequenceNumber, QuicTime>::const_iterator it =
frame.received_info.received_packet_times.begin();
size_t num_unacked_packets = frame.received_info.missing_packets.size();
if (!writer->WriteBytes(&num_unacked_packets, 1)) {
return false;
}
QuicPacketSequenceNumber lowest_sequence = it->first;
if (!writer->WriteUInt48(lowest_sequence)) {
return false;
}
SequenceSet::const_iterator it = frame.received_info.missing_packets.begin();
for (; it != frame.received_info.missing_packets.end(); ++it) {
if (!writer->WriteUInt48(*it)) {
QuicTime lowest_time = it->second;
// TODO(ianswett): Use time deltas from the connection's first received
// packet.
if (!writer->WriteUInt64(lowest_time.ToMicroseconds())) {
return false;
}
}
if (!writer->WriteUInt48(frame.sent_info.least_unacked)) {
return false;
}
for (++it; it != frame.received_info.received_packet_times.end(); ++it) {
QuicPacketSequenceNumber sequence_delta = it->first - lowest_sequence;
if (!writer->WriteBytes(&sequence_delta, 1)) {
return false;
}
size_t num_non_retransmiting_packets =
frame.sent_info.non_retransmiting.size();
if (!writer->WriteBytes(&num_non_retransmiting_packets, 1)) {
return false;
int32 time_delta_us = it->second.Subtract(lowest_time).ToMicroseconds();
if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) {
return false;
}
}
}
it = frame.sent_info.non_retransmiting.begin();
while (it != frame.sent_info.non_retransmiting.end()) {
if (!writer->WriteUInt48(*it)) {
return false;
}
++it;
if (!writer->WriteUInt48(frame.sent_info.least_unacked)) {
return false;
}
if (!writer->WriteBytes(&frame.congestion_info.type, 1)) {
......
This diff is collapsed.
......@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "net/quic/quic_protocol.h"
#include "base/stl_util.h"
using base::StringPiece;
using std::map;
using std::ostream;
namespace net {
......@@ -21,30 +23,87 @@ QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
data(data) {
}
ReceivedPacketInfo::ReceivedPacketInfo() {}
// TODO(ianswett): Initializing largest_received to 0 should not be necessary.
ReceivedPacketInfo::ReceivedPacketInfo() : largest_received(0) {}
ReceivedPacketInfo::~ReceivedPacketInfo() {}
void ReceivedPacketInfo::RecordAck(QuicPacketSequenceNumber sequence_number,
QuicTime time) {
DCHECK(!ContainsAck(sequence_number));
received_packet_times[sequence_number] = time;
if (largest_received < sequence_number) {
largest_received = sequence_number;
}
}
bool ReceivedPacketInfo::ContainsAck(
QuicPacketSequenceNumber sequence_number) const {
return ContainsKey(received_packet_times, sequence_number);
}
void ReceivedPacketInfo::ClearAcksBefore(
QuicPacketSequenceNumber least_unacked) {
for (QuicPacketSequenceNumber i = received_packet_times.begin()->first;
i < least_unacked; ++i) {
received_packet_times.erase(i);
}
}
SentPacketInfo::SentPacketInfo() {}
SentPacketInfo::~SentPacketInfo() {}
QuicAckFrame::QuicAckFrame(QuicPacketSequenceNumber largest_received,
QuicTime time_received,
QuicPacketSequenceNumber least_unacked) {
received_info.largest_received = largest_received;
for (QuicPacketSequenceNumber seq_num = 1;
seq_num <= largest_received; ++seq_num) {
received_info.RecordAck(seq_num, time_received);
}
sent_info.least_unacked = least_unacked;
congestion_info.type = kNone;
}
ostream& operator<<(ostream& os, const QuicAckFrame& s) {
os << "largest_received: " << s.received_info.largest_received
<< " time: " << s.received_info.time_received.ToMicroseconds()
<< " missing: ";
for (SequenceSet::const_iterator it = s.received_info.missing_packets.begin();
it != s.received_info.missing_packets.end(); ++it) {
os << *it << " ";
os << "sent info { least_waiting: " << s.sent_info.least_unacked << " } "
<< "received info { largest_received: "
<< s.received_info.largest_received
<< " received packets: [ ";
for (map<QuicPacketSequenceNumber, QuicTime>::const_iterator it =
s.received_info.received_packet_times.begin();
it != s.received_info.received_packet_times.end(); ++it) {
os << it->first << "@" << it->second.ToMilliseconds() << " ";
}
os << " least_waiting: " << s.sent_info.least_unacked
<< " no_retransmit: ";
for (SequenceSet::const_iterator it = s.sent_info.non_retransmiting.begin();
it != s.sent_info.non_retransmiting.end(); ++it) {
os << *it << " ";
os << "] } congestion info { type: " << s.congestion_info.type;
switch (s.congestion_info.type) {
case kNone:
break;
case kInterArrival: {
const CongestionFeedbackMessageInterArrival& inter_arrival =
s.congestion_info.inter_arrival;
os << " accumulated_number_of_lost_packets: "
<< inter_arrival.accumulated_number_of_lost_packets;
os << " offset_time: " << inter_arrival.offset_time;
os << " delta_time: " << inter_arrival.delta_time;
break;
}
case kFixRate: {
os << " bitrate_in_bytes_per_second: "
<< s.congestion_info.fix_rate.bitrate_in_bytes_per_second;
break;
}
case kTCP: {
const CongestionFeedbackMessageTCP& tcp = s.congestion_info.tcp;
os << " accumulated_number_of_lost_packets: "
<< tcp.accumulated_number_of_lost_packets;
os << " receive_window: " << tcp.receive_window;
break;
}
}
os << "\n";
os << " }\n";
return os;
}
......
......@@ -6,6 +6,7 @@
#define NET_QUIC_QUIC_PROTOCOL_H_
#include <limits>
#include <map>
#include <ostream>
#include <utility>
#include <vector>
......@@ -168,14 +169,16 @@ typedef base::hash_set<QuicPacketSequenceNumber> SequenceSet;
struct NET_EXPORT_PRIVATE ReceivedPacketInfo {
ReceivedPacketInfo();
~ReceivedPacketInfo();
void RecordAck(QuicPacketSequenceNumber sequence_number, QuicTime time);
bool ContainsAck(QuicPacketSequenceNumber sequence_number) const;
void ClearAcksBefore(QuicPacketSequenceNumber least_unacked);
// The highest packet sequence number we've received from the peer.
QuicPacketSequenceNumber largest_received;
// The time at which we received the above packet.
QuicTime time_received;
// The set of packets which we're expecting and have not received.
// This includes any packets between the lowest and largest_received
// which we have neither seen nor been informed are non-retransmitting.
SequenceSet missing_packets;
// The set of all received packets and their arrival times.
std::map<QuicPacketSequenceNumber, QuicTime> received_packet_times;
};
struct NET_EXPORT_PRIVATE SentPacketInfo {
......@@ -183,9 +186,6 @@ struct NET_EXPORT_PRIVATE SentPacketInfo {
~SentPacketInfo();
// The lowest packet we've sent which is unacked, and we expect an ack for.
QuicPacketSequenceNumber least_unacked;
// The set of packets between least_unacked and the last packet we have sent
// which we will not resend.
SequenceSet non_retransmiting;
};
// Defines for all types of congestion feedback that will be negotiated in QUIC,
......@@ -241,14 +241,11 @@ struct NET_EXPORT_PRIVATE CongestionInfo {
struct NET_EXPORT_PRIVATE QuicAckFrame {
QuicAckFrame() {}
// Testing convenience method to construct a QuicAckFrame with all packets
// from least_unacked to largest_received acked at time_received.
QuicAckFrame(QuicPacketSequenceNumber largest_received,
QuicTime time_received,
QuicPacketSequenceNumber least_unacked) {
received_info.largest_received = largest_received;
received_info.time_received = time_received;
sent_info.least_unacked = least_unacked;
congestion_info.type = kNone;
}
QuicPacketSequenceNumber least_unacked);
NET_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
const QuicAckFrame& s);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment