Add QUIC congestion control classes.  (Just a basic fixed rate sender.)


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164486 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/net.gyp b/net/net.gyp
index f8ef0ea..b6697b7 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -633,6 +633,18 @@
         'proxy/sync_host_resolver.h',
         'proxy/sync_host_resolver_bridge.cc',
         'proxy/sync_host_resolver_bridge.h',
+        'quic/congestion_control/fix_rate_receiver.cc',
+        'quic/congestion_control/fix_rate_receiver.h',
+        'quic/congestion_control/fix_rate_sender.cc',
+        'quic/congestion_control/fix_rate_sender.h',
+        'quic/congestion_control/quic_receipt_metrics_collector.cc',
+        'quic/congestion_control/quic_receipt_metrics_collector.h',
+        'quic/congestion_control/quic_send_scheduler.cc',
+        'quic/congestion_control/quic_send_scheduler.h',
+        'quic/congestion_control/receive_algorithm_interface.cc',
+        'quic/congestion_control/receive_algorithm_interface.h',
+        'quic/congestion_control/send_algorithm_interface.cc',
+        'quic/congestion_control/send_algorithm_interface.h',
         'quic/crypto/crypto_framer.cc',
         'quic/crypto/crypto_framer.h',
         'quic/crypto/crypto_protocol.cc',
@@ -643,6 +655,8 @@
         'quic/crypto/quic_decrypter.cc',
         'quic/crypto/quic_encrypter.h',
         'quic/crypto/quic_encrypter.cc',
+        'quic/quic_clock.cc',
+        'quic/quic_clock.h',
         'quic/quic_data_reader.cc',
         'quic/quic_data_reader.h',
         'quic/quic_data_writer.cc',
@@ -1381,9 +1395,14 @@
         'proxy/proxy_server_unittest.cc',
         'proxy/proxy_service_unittest.cc',
         'proxy/sync_host_resolver_bridge_unittest.cc',
+        'quic/congestion_control/fix_rate_test.cc',
+        'quic/congestion_control/quic_receipt_metrics_collector_test.cc',
+        'quic/congestion_control/quic_send_scheduler_test.cc',
         'quic/crypto/crypto_framer_test.cc',
         'quic/crypto/null_decrypter_test.cc',
         'quic/crypto/null_encrypter_test.cc',
+        'quic/test_tools/mock_clock.cc',
+        'quic/test_tools/mock_clock.h',
         'quic/test_tools/quic_test_utils.cc',
         'quic/test_tools/quic_test_utils.h',
         'quic/quic_fec_group_test.cc',
diff --git a/net/quic/congestion_control/fix_rate_receiver.cc b/net/quic/congestion_control/fix_rate_receiver.cc
new file mode 100644
index 0000000..5adfc6ce
--- /dev/null
+++ b/net/quic/congestion_control/fix_rate_receiver.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/fix_rate_receiver.h"
+
+#include "base/basictypes.h"
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
+
+namespace {
+  static const int kInitialBitrate = 100000;  // In bytes per second.
+}
+
+namespace net {
+
+FixRateReceiver::FixRateReceiver()
+    : bitrate_in_bytes_per_second_(kInitialBitrate) {
+}
+
+bool FixRateReceiver::GenerateCongestionInfo(CongestionInfo* congestion_info) {
+  congestion_info->type = kFixRate;
+  congestion_info->fix_rate.bitrate_in_bytes_per_second =
+      bitrate_in_bytes_per_second_;
+  return true;
+}
+
+void FixRateReceiver::RecordIncomingPacket(
+    size_t bytes,
+    QuicPacketSequenceNumber sequence_number,
+    uint64 timestamp_us,
+    bool recovered) {
+  // Nothing to do for this simple implementation.
+}
+
+void FixRateReceiver::SetBitrate(int bytes_per_second) {
+  bitrate_in_bytes_per_second_ = bytes_per_second;
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/fix_rate_receiver.h b/net/quic/congestion_control/fix_rate_receiver.h
new file mode 100644
index 0000000..f212217
--- /dev/null
+++ b/net/quic/congestion_control/fix_rate_receiver.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Fix rate receive side congestion control, used for initial testing.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_FIX_RATE_RECEIVER_H_
+#define NET_QUIC_CONGESTION_CONTROL_FIX_RATE_RECEIVER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "net/base/net_export.h"
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE FixRateReceiver : public ReceiveAlgorithmInterface {
+ public:
+  FixRateReceiver();
+
+  // Implements ReceiveAlgorithmInterface.
+  virtual bool GenerateCongestionInfo(CongestionInfo* congestion_info) OVERRIDE;
+
+  // Implements ReceiveAlgorithmInterface.
+  virtual void RecordIncomingPacket(size_t bytes,
+                                    QuicPacketSequenceNumber sequence_number,
+                                    uint64 timestamp_us,
+                                    bool recovered) OVERRIDE;
+
+  void SetBitrate(int bytes_per_second);  // Used for testing only.
+
+ private:
+  int bitrate_in_bytes_per_second_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_FIX_RATE_RECEIVER_H_
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
new file mode 100644
index 0000000..e9af848
--- /dev/null
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/fix_rate_sender.h"
+
+#include <math.h>
+
+#include "base/logging.h"
+#include "net/quic/quic_protocol.h"
+
+namespace {
+  static const int kInitialBitrate = 100000;  // In bytes per second.
+  static const int kNoBytesSent = 0;
+}
+
+namespace net {
+
+FixRateSender::FixRateSender(QuicClock* clock)
+    : bitrate_in_bytes_per_second_(kInitialBitrate),
+      clock_(clock),
+      time_last_sent_us_(0),
+      bytes_last_sent_(kNoBytesSent),
+      bytes_in_flight_(0) {
+  DLOG(INFO) << "FixRateSender";
+}
+
+void FixRateSender::OnIncomingCongestionInfo(
+    const CongestionInfo& congestion_info) {
+  DCHECK(congestion_info.type == kFixRate) <<
+      "Invalid incoming CongestionFeedbackType:" << congestion_info.type;
+  if (congestion_info.type == kFixRate) {
+    bitrate_in_bytes_per_second_ =
+        congestion_info.fix_rate.bitrate_in_bytes_per_second;
+  }
+  // Silently ignore invalid messages in release mode.
+}
+
+void FixRateSender::OnIncomingAck(
+    QuicPacketSequenceNumber /*acked_sequence_number*/,
+    size_t bytes_acked, uint64 /*rtt_us*/) {
+  bytes_in_flight_ -= bytes_acked;
+}
+
+void FixRateSender::OnIncomingLoss(int /*number_of_lost_packets*/) {
+  // Ignore losses for fix rate sender.
+}
+
+void FixRateSender::SentPacket(QuicPacketSequenceNumber /*sequence_number*/,
+                               size_t bytes,
+                               bool retransmit) {
+  if (bytes > 0) {
+    time_last_sent_us_ = clock_->NowInUsec();
+    bytes_last_sent_ = bytes;
+  }
+  if (!retransmit) {
+    bytes_in_flight_ += bytes;
+  }
+}
+
+int FixRateSender::TimeUntilSend(bool /*retransmit*/) {
+  if (time_last_sent_us_ == 0 && bytes_last_sent_ == kNoBytesSent) {
+    // No sent packets.
+    return 0;  // We can send now.
+  }
+  uint64 elapsed_time_us = clock_->NowInUsec() - time_last_sent_us_;
+  uint64 time_to_transmit_us = (bytes_last_sent_ * 1000000) /
+      bitrate_in_bytes_per_second_;
+  if (elapsed_time_us > time_to_transmit_us) {
+    return 0;  // We can send now.
+  }
+  return time_to_transmit_us - elapsed_time_us;
+}
+
+size_t FixRateSender::AvailableCongestionWindow() {
+  if (TimeUntilSend(false) > 0) {
+    return 0;
+  }
+  // Note: Since this is for testing only we have the total window size equal to
+  // kMaxPacketSize.
+  return  kMaxPacketSize - bytes_in_flight_;
+}
+
+int FixRateSender::BandwidthEstimate() {
+  return bitrate_in_bytes_per_second_;
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/fix_rate_sender.h b/net/quic/congestion_control/fix_rate_sender.h
new file mode 100644
index 0000000..c60a1943
--- /dev/null
+++ b/net/quic/congestion_control/fix_rate_sender.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Fix rate send side congestion control, used for testing.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_FIX_RATE_SENDER_H_
+#define NET_QUIC_CONGESTION_CONTROL_FIX_RATE_SENDER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
+ public:
+  explicit FixRateSender(QuicClock* clock);
+
+  // Start implementation of SendAlgorithmInterface.
+  virtual void OnIncomingCongestionInfo(
+      const CongestionInfo& congestion_info) OVERRIDE;
+  virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+                             size_t acked_bytes,
+                             uint64 rtt_us) OVERRIDE;
+  virtual void OnIncomingLoss(int number_of_lost_packets) OVERRIDE;
+  virtual void SentPacket(QuicPacketSequenceNumber equence_number,
+                          size_t bytes, bool retransmit) OVERRIDE;
+  virtual int TimeUntilSend(bool retransmit) OVERRIDE;
+  virtual size_t AvailableCongestionWindow() OVERRIDE;
+  virtual int BandwidthEstimate() OVERRIDE;
+  // End implementation of SendAlgorithmInterface.
+
+ private:
+  uint32 bitrate_in_bytes_per_second_;
+  QuicClock* clock_;
+  uint64 time_last_sent_us_;
+  int bytes_last_sent_;
+  size_t bytes_in_flight_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_FIX_RATE_SENDER_H_
diff --git a/net/quic/congestion_control/fix_rate_test.cc b/net/quic/congestion_control/fix_rate_test.cc
new file mode 100644
index 0000000..3372c022
--- /dev/null
+++ b/net/quic/congestion_control/fix_rate_test.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/congestion_control/fix_rate_receiver.h"
+#include "net/quic/congestion_control/fix_rate_sender.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/quic_protocol.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class FixRateTest : public ::testing::Test {
+ protected:
+  void SetUp() {
+    sender_.reset(new FixRateSender(&clock_));
+    receiver_.reset(new FixRateReceiver());
+  }
+  MockClock clock_;
+  scoped_ptr<FixRateSender> sender_;
+  scoped_ptr<FixRateReceiver> receiver_;
+};
+
+TEST_F(FixRateTest, ReceiverAPI) {
+  CongestionInfo info;
+  receiver_->SetBitrate(300000);  // Bytes per second.
+  receiver_->RecordIncomingPacket(1, 1, 1, false);
+  ASSERT_TRUE(receiver_->GenerateCongestionInfo(&info));
+  EXPECT_EQ(kFixRate, info.type);
+  EXPECT_EQ(300000u, info.fix_rate.bitrate_in_bytes_per_second);
+}
+
+TEST_F(FixRateTest, SenderAPI) {
+  CongestionInfo info;
+  info.type = kFixRate;
+  info.fix_rate.bitrate_in_bytes_per_second = 300000;
+  sender_->OnIncomingCongestionInfo(info);
+  EXPECT_EQ(0, sender_->TimeUntilSend(false));
+  EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+  sender_->SentPacket(1, 1200, false);
+  EXPECT_EQ(0u, sender_->AvailableCongestionWindow());
+  EXPECT_EQ(300000, sender_->BandwidthEstimate());
+  EXPECT_EQ(4000, sender_->TimeUntilSend(false));
+  clock_.AdvanceTime(0.002);
+  EXPECT_EQ(2000, sender_->TimeUntilSend(false));
+  clock_.AdvanceTime(0.002);
+  EXPECT_EQ(0, sender_->TimeUntilSend(false));
+}
+
+TEST_F(FixRateTest, Pacing) {
+  const int packet_size = 1200;
+  const int rtt_us = 30000;
+  CongestionInfo info;
+  receiver_->SetBitrate(240000);  // Bytes per second.
+  ASSERT_TRUE(receiver_->GenerateCongestionInfo(&info));
+  sender_->OnIncomingCongestionInfo(info);
+  double acc_advance_time = 0.0;
+  for (int i = 0; i < 100; ++i) {
+    EXPECT_EQ(0, sender_->TimeUntilSend(false));
+    EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+    sender_->SentPacket(i, packet_size, false);
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    sender_->OnIncomingAck(i, packet_size, rtt_us);
+    acc_advance_time += advance_time;
+  }
+  EXPECT_EQ(500, floor((acc_advance_time * 1000) + 0.5));
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/quic_receipt_metrics_collector.cc b/net/quic/congestion_control/quic_receipt_metrics_collector.cc
new file mode 100644
index 0000000..db98e4d
--- /dev/null
+++ b/net/quic/congestion_control/quic_receipt_metrics_collector.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
+
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
+
+namespace net {
+
+QuicReceiptMetricsCollector::QuicReceiptMetricsCollector(
+    QuicClock* clock,
+    CongestionFeedbackType type)
+    : receive_algorithm_(ReceiveAlgorithmInterface::Create(clock, type)) {
+}
+
+QuicReceiptMetricsCollector::~QuicReceiptMetricsCollector() {
+}
+
+bool QuicReceiptMetricsCollector::GenerateCongestionInfo(
+    CongestionInfo* info) {
+  return receive_algorithm_->GenerateCongestionInfo(info);
+}
+
+void QuicReceiptMetricsCollector::RecordIncomingPacket(
+    size_t bytes,
+    QuicPacketSequenceNumber sequence_number,
+    uint64 timestamp_us,
+    bool revived) {
+  receive_algorithm_->RecordIncomingPacket(bytes, sequence_number, timestamp_us,
+                                           revived);
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/quic_receipt_metrics_collector.h b/net/quic/congestion_control/quic_receipt_metrics_collector.h
new file mode 100644
index 0000000..7ae77d2
--- /dev/null
+++ b/net/quic/congestion_control/quic_receipt_metrics_collector.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This is the base class for QUIC receive side congestion control.
+// This class will provide the CongestionInfo objects to outgoing ACKs if
+// needed.
+// The acctual receive side algorithm is implemented via the
+// ReceiveAlgorithmInterface.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_RECEIPT_METRICS_COLLECTOR_H_
+#define NET_QUIC_CONGESTION_CONTROL_QUIC_RECEIPT_METRICS_COLLECTOR_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE QuicReceiptMetricsCollector {
+ public:
+  QuicReceiptMetricsCollector(QuicClock* clock,
+                              CongestionFeedbackType congestion_type);
+
+  virtual ~QuicReceiptMetricsCollector();
+
+  // Should be called for each ACK packet to decide if we need to attach a
+  // CongestionInfo block.
+  // Returns false if no CongestionInfo block is needed otherwise fills in
+  // congestion_info and return true.
+  virtual bool GenerateCongestionInfo(CongestionInfo* congestion_info);
+
+  // Should be called for each incoming packet.
+  // bytes: is the packet size in bytes including IP headers.
+  // sequence_number: is the unique sequence number from the QUIC packet header.
+  // timestamp: is the sent timestamp from the QUIC packet header.
+  // TODO(pwestin) which type should we use for timestamp?
+  // revived: is set if the packet is lost and then recovered with help of a
+  // FEC packet.
+  virtual void RecordIncomingPacket(size_t bytes,
+                                    QuicPacketSequenceNumber sequence_number,
+                                    uint64 timestamp_us,
+                                    bool revived);
+
+  // TODO(pwestin) Keep track of the number of FEC recovered packets.
+  // Needed by all congestion control algorithms.
+
+ private:
+  scoped_ptr<ReceiveAlgorithmInterface> receive_algorithm_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_QUIC_RECEIPT_METRICS_COLLECTOR_H_
diff --git a/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc b/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc
new file mode 100644
index 0000000..1388130
--- /dev/null
+++ b/net/quic/congestion_control/quic_receipt_metrics_collector_test.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class QuicReceiptMetricsCollectorTest : public ::testing::Test {
+ protected:
+  void SetUpCongestionType(CongestionFeedbackType congestion_type) {
+    receiver_.reset(new QuicReceiptMetricsCollector(&clock_, congestion_type));
+  }
+
+  MockClock clock_;
+  scoped_ptr<QuicReceiptMetricsCollector> receiver_;
+};
+
+TEST_F(QuicReceiptMetricsCollectorTest, FixedRateReceiverAPI) {
+  SetUpCongestionType(kFixRate);
+  CongestionInfo info;
+  receiver_->RecordIncomingPacket(1, 1, 1, false);
+  ASSERT_TRUE(receiver_->GenerateCongestionInfo(&info));
+  EXPECT_EQ(kFixRate, info.type);
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/quic_send_scheduler.cc b/net/quic/congestion_control/quic_send_scheduler.cc
new file mode 100644
index 0000000..9df5db7
--- /dev/null
+++ b/net/quic/congestion_control/quic_send_scheduler.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "net/quic/congestion_control/quic_send_scheduler.h"
+
+#include <cmath>
+
+#include "base/stl_util.h"
+#include "base/time.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+//#include "util/gtl/map-util.h"
+
+namespace net {
+
+// To prevent too aggressive pacing we allow the following packet burst size.
+const int kMinPacketBurstSize = 2;
+const int64 kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;
+
+QuicSendScheduler::QuicSendScheduler(
+    QuicClock* clock,
+    CongestionFeedbackType type)
+    : clock_(clock),
+      current_estimated_bandwidth_(-1),
+      max_estimated_bandwidth_(-1),
+      last_sent_packet_us_(0),
+      current_packet_bucket_(-1),
+      first_packet_bucket_(-1),
+      send_algorithm_(SendAlgorithmInterface::Create(clock, type)) {
+  memset(packet_history_, 0, sizeof(packet_history_));
+}
+
+QuicSendScheduler::~QuicSendScheduler() {
+  STLDeleteContainerPairSecondPointers(pending_packets_.begin(),
+                                       pending_packets_.end());
+}
+
+int QuicSendScheduler::UpdatePacketHistory() {
+  uint64 now_us = clock_->NowInUsec();
+  int timestamp_scaled = now_us / kBitrateSmoothingPeriod;
+
+  int bucket = timestamp_scaled % kBitrateSmoothingBuckets;
+  if (!HasSentPacket()) {
+    // First packet.
+    current_packet_bucket_ = bucket;
+    first_packet_bucket_ = bucket;
+  }
+  if (current_packet_bucket_ != bucket) {
+    // We need to make sure to zero out any skipped buckets.
+    // Max loop count is kBitrateSmoothingBuckets.
+    do {
+      current_packet_bucket_ =
+          (1 + current_packet_bucket_) % kBitrateSmoothingBuckets;
+      packet_history_[current_packet_bucket_] = 0;
+      if (first_packet_bucket_ == current_packet_bucket_) {
+        // We have filled the whole window, no need to keep track of first
+        // bucket.
+        first_packet_bucket_ = -1;
+      }
+    }  while (current_packet_bucket_ != bucket);
+  }
+  return bucket;
+}
+
+void QuicSendScheduler::SentPacket(QuicPacketSequenceNumber sequence_number,
+                                   size_t bytes,
+                                   bool retransmit) {
+  int bucket = UpdatePacketHistory();
+  packet_history_[bucket] += bytes;
+  last_sent_packet_us_ = clock_->NowInUsec();
+  send_algorithm_->SentPacket(sequence_number, bytes, retransmit);
+  if (!retransmit) {
+    pending_packets_[sequence_number] = new PendingPacket(bytes,
+                                                          last_sent_packet_us_);
+  }
+  DLOG(INFO) << "Sent sequence number:" << sequence_number;
+}
+
+void QuicSendScheduler::OnIncomingAckFrame(const QuicAckFrame& ack_frame) {
+  if (ack_frame.congestion_info.type != kNone) {
+    send_algorithm_->OnIncomingCongestionInfo(ack_frame.congestion_info);
+  }
+  // We want to.
+  // * Get all packets lower(including) than largest_received
+  //   from pending_packets_.
+  // * Remove all missing packets.
+  // * Send each ACK in the list to send_algorithm_.
+  uint64 last_timestamp_us = 0;
+  std::map<QuicPacketSequenceNumber, size_t> acked_packets;
+
+  PendingPacketsMap::iterator it, it_upper;
+  it = pending_packets_.begin();
+  it_upper = pending_packets_.upper_bound(
+      ack_frame.received_info.largest_received);
+
+  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()) {
+      // Not missing, hence implicitly acked.
+      scoped_ptr<PendingPacket> pending_packet_cleaner(it->second);
+      acked_packets[sequence_number] = pending_packet_cleaner->BytesSent();
+      last_timestamp_us = pending_packet_cleaner->SendTimestamp();
+      pending_packets_.erase(it++);  // Must be incremented post to work.
+    } else {
+      ++it;
+    }
+  }
+  // We calculate the RTT based on the highest ACKed sequence number, the lower
+  // sequence numbers will include the ACK aggregation delay.
+  uint64 rtt_us = clock_->NowInUsec() - last_timestamp_us;
+
+  std::map<QuicPacketSequenceNumber, size_t>::iterator it_acked_packets;
+  for (it_acked_packets = acked_packets.begin();
+      it_acked_packets != acked_packets.end();
+      ++it_acked_packets) {
+    send_algorithm_->OnIncomingAck(it_acked_packets->first,
+                                   it_acked_packets->second,
+                                   rtt_us);
+    DLOG(INFO) << "ACKed sequence number:" << it_acked_packets->first;
+  }
+}
+
+int QuicSendScheduler::TimeUntilSend(bool retransmit) {
+  return send_algorithm_->TimeUntilSend(retransmit);
+}
+
+size_t QuicSendScheduler::AvailableCongestionWindow() {
+  size_t available_congestion_window =
+      send_algorithm_->AvailableCongestionWindow();
+  DLOG(INFO) << "Available congestion window:" << available_congestion_window;
+
+  // Should we limit the window to pace the data?
+  if (available_congestion_window > kMinPacketBurstSize * kMaxPacketSize) {
+    // TODO(pwestin): implement pacing.
+    // will depend on estimated bandwidth; higher bandwidth => larger burst
+    // we need to consider our timing accuracy here too.
+    // an accuracy of 1ms will allow us to send up to 19.2Mbit/s with 2 packets
+    // per burst.
+  }
+  return available_congestion_window;
+}
+
+int QuicSendScheduler::BandwidthEstimate() {
+  return send_algorithm_->BandwidthEstimate();
+}
+
+bool QuicSendScheduler::HasSentPacket() {
+  return (current_packet_bucket_ != -1);
+}
+
+// TODO(pwestin) add a timer to make this accurate even if not called.
+int QuicSendScheduler::SentBandwidth() {
+  UpdatePacketHistory();
+
+  if (first_packet_bucket_ != -1) {
+    // We don't have a full set of data.
+    int number_of_buckets = (current_packet_bucket_ - first_packet_bucket_) + 1;
+    if (number_of_buckets < 0) {
+      // We have a wrap in bucket index.
+      number_of_buckets = kBitrateSmoothingBuckets + number_of_buckets;
+    }
+    int64 sum = 0;
+    int bucket = first_packet_bucket_;
+    for (int n = 0; n < number_of_buckets; bucket++, n++) {
+      bucket = bucket % kBitrateSmoothingBuckets;
+      sum += packet_history_[bucket];
+    }
+    current_estimated_bandwidth_ = (sum *
+        (kNumMicrosPerSecond / kBitrateSmoothingPeriod)) / number_of_buckets;
+  } else {
+    int64 sum = 0;
+    for (uint32 bucket = 0; bucket < kBitrateSmoothingBuckets; ++bucket) {
+      sum += packet_history_[bucket];
+    }
+    current_estimated_bandwidth_ = (sum * (kNumMicrosPerSecond /
+        kBitrateSmoothingPeriod)) / kBitrateSmoothingBuckets;
+  }
+  max_estimated_bandwidth_ = std::max(max_estimated_bandwidth_,
+                                      current_estimated_bandwidth_);
+  return current_estimated_bandwidth_;
+}
+
+int QuicSendScheduler::PeakSustainedBandwidth() {
+  // To make sure that we get the latest estimate we call SentBandwidth.
+  if (HasSentPacket()) {
+    SentBandwidth();
+  }
+  return max_estimated_bandwidth_;
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/quic_send_scheduler.h b/net/quic/congestion_control/quic_send_scheduler.h
new file mode 100644
index 0000000..2d1379ac
--- /dev/null
+++ b/net/quic/congestion_control/quic_send_scheduler.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The is the base class for QUIC send side congestion control.
+// It decides when we can send a QUIC packet to the wire.
+// This class handles the basic bookkeeping of sent bitrate and packet loss.
+// The acctual send side algorithm is implemented via the
+// SendAlgorithmInterface.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_
+#define NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_clock.h"
+
+namespace net {
+
+const uint32 kBitrateSmoothingBuckets = 300;
+
+// 10 ms in micro seconds, must be less than 1 second for current
+// implementation due to overflow resulting in a potential divide by zero.
+const uint32 kBitrateSmoothingPeriod = 10000;
+
+// When kUnknownWaitTime is returned, there is no need to poll the function
+// again until we receive a new event.
+const int kUnknownWaitTime = -1;
+
+class NET_EXPORT_PRIVATE QuicSendScheduler {
+ public:
+  class PendingPacket {
+   public:
+    PendingPacket(size_t bytes, uint64 timestamp_us)
+        : bytes_sent_(bytes),
+          send_timestamp_us_(timestamp_us) {
+    }
+    size_t BytesSent() { return bytes_sent_; }
+    uint64 SendTimestamp() { return send_timestamp_us_; }
+
+   private:
+    size_t bytes_sent_;
+    uint64 send_timestamp_us_;
+  };
+  typedef std::map<QuicPacketSequenceNumber, PendingPacket*> PendingPacketsMap;
+
+  QuicSendScheduler(QuicClock* clock, CongestionFeedbackType congestion_type);
+  virtual ~QuicSendScheduler();
+
+  // Called when we have received an ack frame from remote peer.
+  virtual void OnIncomingAckFrame(const QuicAckFrame& ack_frame);
+
+  // Inform that we sent x bytest to the wire, and if that was a retransmission.
+  // Note: this function must be called for every packet sent to the wire.
+  virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
+                          size_t bytes,
+                          bool retransmit);
+
+  // Calculate the time until we can send the next packet to the wire.
+  // Note 1: When kUnknownWaitTime is returned, there is no need to poll
+  // TimeUntilSend again until we receive an OnIncomingAckFrame event.
+  // Note 2: Send algorithms may or may not use |retransmit| in their
+  // calculations.
+  virtual int TimeUntilSend(bool retransmit);
+
+  // Returns the current available congestion window in bytes, the number of
+  // bytes that can be sent now.
+  // Note: due to pacing this function might return a smaller value than the
+  // real available congestion window. This way we hold off the sender to avoid
+  // queuing in the lower layers in the stack.
+  size_t AvailableCongestionWindow();
+
+  int BandwidthEstimate();  // Current estimate, in bytes per second.
+
+  int SentBandwidth();  // Current smooth acctually sent, in bytes per second.
+
+  int PeakSustainedBandwidth();  // In bytes per second.
+
+ private:
+  // Have we sent any packets during this session?
+  bool HasSentPacket();
+  int UpdatePacketHistory();
+
+  QuicClock* clock_;
+  int current_estimated_bandwidth_;
+  int max_estimated_bandwidth_;
+  uint64 last_sent_packet_us_;
+  // To keep track of the real sent bitrate we keep track of the last sent bytes
+  // by keeping an array containing the number of bytes sent in a short timespan
+  // kBitrateSmoothingPeriod; multiple of these buckets kBitrateSmoothingBuckets
+  // create a time window in which we calculate the average bitrate.
+  int current_packet_bucket_;  // Last active bucket in window.
+  int first_packet_bucket_;  // First active bucket in window.
+  uint32 packet_history_[kBitrateSmoothingBuckets];  // The window.
+  scoped_ptr<SendAlgorithmInterface> send_algorithm_;
+  // TODO(pwestin): should we combine the packet_history_ bucket with this map?
+  // For now I keep it separate for easy implementation.
+  PendingPacketsMap pending_packets_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_QUIC_SEND_SCHEDULER_H_
diff --git a/net/quic/congestion_control/quic_send_scheduler_test.cc b/net/quic/congestion_control/quic_send_scheduler_test.cc
new file mode 100644
index 0000000..f25adda
--- /dev/null
+++ b/net/quic/congestion_control/quic_send_scheduler_test.cc
@@ -0,0 +1,149 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/quic_send_scheduler.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/quic_protocol.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class QuicSendSchedulerTest : public ::testing::Test {
+ protected:
+  void SetUpCongestionType(CongestionFeedbackType congestion_type) {
+    sender_.reset(new QuicSendScheduler(&clock_, congestion_type));
+  }
+
+  MockClock clock_;
+  scoped_ptr<QuicSendScheduler> sender_;
+};
+
+TEST_F(QuicSendSchedulerTest, FixedRateSenderAPI) {
+  SetUpCongestionType(kFixRate);
+  QuicAckFrame ack;
+  ack.congestion_info.type = kFixRate;
+  ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 300000;
+  sender_->OnIncomingAckFrame(ack);
+  EXPECT_EQ(-1, sender_->PeakSustainedBandwidth());
+  EXPECT_EQ(0, sender_->TimeUntilSend(false));
+  EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+  sender_->SentPacket(1, 1200, false);
+  EXPECT_EQ(0u, sender_->AvailableCongestionWindow());
+  EXPECT_EQ(4000, sender_->TimeUntilSend(false));
+  clock_.AdvanceTime(0.002);
+  EXPECT_EQ(2000, sender_->TimeUntilSend(false));
+  clock_.AdvanceTime(0.002);
+  EXPECT_EQ(0, sender_->TimeUntilSend(false));
+}
+
+TEST_F(QuicSendSchedulerTest, FixedRatePacing) {
+  SetUpCongestionType(kFixRate);
+  QuicAckFrame ack;
+  ack.congestion_info.type = kFixRate;
+  ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
+  ack.received_info.largest_received = 0;
+  sender_->OnIncomingAckFrame(ack);
+  double acc_advance_time = 0.0;
+  for (int i = 0; i < 100; ++i) {
+    EXPECT_EQ(0, sender_->TimeUntilSend(false));
+    EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+    sender_->SentPacket(i, 1200, false);
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    acc_advance_time += advance_time;
+    // Ack the packet we sent.
+    ack.received_info.largest_received = i;
+    sender_->OnIncomingAckFrame(ack);
+  }
+  EXPECT_EQ(1200, floor((acc_advance_time * 1000) + 0.5));
+}
+
+TEST_F(QuicSendSchedulerTest, AvailableCongestionWindow) {
+  SetUpCongestionType(kFixRate);
+  QuicAckFrame ack;
+  ack.congestion_info.type = kFixRate;
+  ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
+  sender_->OnIncomingAckFrame(ack);
+  EXPECT_EQ(0, sender_->TimeUntilSend(false));
+  EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+  for (int i = 1; i <= 12; i++) {
+    sender_->SentPacket(i, 100, false);
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    EXPECT_EQ(kMaxPacketSize - (i * 100), sender_->AvailableCongestionWindow());
+  }
+  // Ack the packet we sent.
+  ack.received_info.largest_received = 12;
+  sender_->OnIncomingAckFrame(ack);
+  EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+}
+
+TEST_F(QuicSendSchedulerTest, FixedRateBandwidth) {
+  SetUpCongestionType(kFixRate);
+  QuicAckFrame ack;
+  ack.congestion_info.type = kFixRate;
+  ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
+  sender_->OnIncomingAckFrame(ack);
+  for (int i = 0; i < 100; ++i) {
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    EXPECT_EQ(0, sender_->TimeUntilSend(false));
+    EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+    sender_->SentPacket(i, 1000, false);
+    // Ack the packet we sent.
+    ack.received_info.largest_received = i;
+    sender_->OnIncomingAckFrame(ack);
+  }
+  EXPECT_EQ(100000, sender_->BandwidthEstimate());
+  EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
+  EXPECT_EQ(100000, sender_->SentBandwidth());
+}
+
+TEST_F(QuicSendSchedulerTest, BandwidthWith3SecondGap) {
+  SetUpCongestionType(kFixRate);
+  QuicAckFrame ack;
+  ack.congestion_info.type = kFixRate;
+  ack.congestion_info.fix_rate.bitrate_in_bytes_per_second = 100000;
+  sender_->OnIncomingAckFrame(ack);
+  for (int i = 0; i < 100; ++i) {
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    EXPECT_EQ(0, sender_->TimeUntilSend(false));
+    EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+    sender_->SentPacket(i, 1000, false);
+    // Ack the packet we sent.
+    ack.received_info.largest_received = i;
+    sender_->OnIncomingAckFrame(ack);
+  }
+  EXPECT_EQ(100000, sender_->BandwidthEstimate());
+  EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
+  EXPECT_EQ(100000, sender_->SentBandwidth());
+  clock_.AdvanceTime(1.0);
+  EXPECT_EQ(50000, sender_->SentBandwidth());
+  clock_.AdvanceTime(2.1);
+  EXPECT_EQ(100000, sender_->BandwidthEstimate());
+  EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
+  EXPECT_EQ(0, sender_->SentBandwidth());
+  for (int i = 0; i < 150; ++i) {
+    EXPECT_EQ(0, sender_->TimeUntilSend(false));
+    EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
+    sender_->SentPacket(i + 100, 1000, false);
+    double advance_time = sender_->TimeUntilSend(false) / 1000000.0;
+    clock_.AdvanceTime(advance_time);
+    // Ack the packet we sent.
+    ack.received_info.largest_received = i + 100;
+    sender_->OnIncomingAckFrame(ack);
+  }
+  EXPECT_EQ(100000, sender_->BandwidthEstimate());
+  EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
+  EXPECT_EQ(50000, sender_->SentBandwidth());
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/receive_algorithm_interface.cc b/net/quic/congestion_control/receive_algorithm_interface.cc
new file mode 100644
index 0000000..3d6819b
--- /dev/null
+++ b/net/quic/congestion_control/receive_algorithm_interface.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
+
+#include "net/quic/congestion_control/fix_rate_receiver.h"
+
+namespace net {
+
+// Factory for receive side congestion control algorithm.
+ReceiveAlgorithmInterface* ReceiveAlgorithmInterface::Create(
+    QuicClock* clock,
+    CongestionFeedbackType type) {
+  switch (type) {
+    case kNone:
+      LOG(DFATAL) << "Attempted to create a ReceiveAlgorithm with kNone.";
+      break;
+    case kTCP:
+      //return new TcpReceiver(clock);
+    case kInterArrival:
+      break;  // TODO(pwestin) Implement.
+    case kFixRate:
+      return new FixRateReceiver();
+  }
+  return NULL;
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/receive_algorithm_interface.h b/net/quic/congestion_control/receive_algorithm_interface.h
new file mode 100644
index 0000000..1acdb9f
--- /dev/null
+++ b/net/quic/congestion_control/receive_algorithm_interface.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The pure virtual class for receive side congestion algorithm.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
+#define NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
+
+#include "base/basictypes.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE ReceiveAlgorithmInterface {
+ public:
+  static ReceiveAlgorithmInterface* Create(QuicClock* clock,
+                                           CongestionFeedbackType type);
+
+  virtual ~ReceiveAlgorithmInterface() {}
+
+  // Returns false if no CongestionInfo block is needed otherwise fills in
+  // congestion_info and return true.
+  virtual bool GenerateCongestionInfo(CongestionInfo* congestion_info) = 0;
+
+  // Should be called for each incoming packet.
+  // bytes: is the packet size in bytes including IP headers.
+  // sequence_number: is the unique sequence number from the QUIC packet header.
+  // timestamp_us: is the sent timestamp from the QUIC packet header.
+  // revived: is set if the packet is lost and then recovered with help of FEC
+  // (Forward Error Correction) packet(s).
+  virtual void RecordIncomingPacket(size_t bytes,
+                                    QuicPacketSequenceNumber sequence_number,
+                                    uint64 timestamp_us,
+                                    bool revived) = 0;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc
new file mode 100644
index 0000000..45e793e9
--- /dev/null
+++ b/net/quic/congestion_control/send_algorithm_interface.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+
+#include "net/quic/congestion_control/fix_rate_sender.h"
+
+namespace net {
+
+// TODO(pwestin): Change to cubic when implemented.
+const bool kUseReno = true;
+
+// Factory for send side congestion control algorithm.
+SendAlgorithmInterface* SendAlgorithmInterface::Create(
+    QuicClock* clock,
+    CongestionFeedbackType type) {
+  switch (type) {
+    case kNone:
+      LOG(DFATAL) << "Attempted to create a SendAlgorithm with kNone.";
+      break;
+    case kTCP:
+      //return new TcpCubicSender(clock, kUseReno);
+    case kInterArrival:
+      break;  // TODO(pwestin) Implement.
+    case kFixRate:
+      return new FixRateSender(clock);
+  }
+  return NULL;
+}
+
+}  // namespace net
diff --git a/net/quic/congestion_control/send_algorithm_interface.h b/net/quic/congestion_control/send_algorithm_interface.h
new file mode 100644
index 0000000..b2196616
--- /dev/null
+++ b/net/quic/congestion_control/send_algorithm_interface.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The pure virtual class for send side congestion control algorithm.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+#define NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+
+#include "base/basictypes.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE SendAlgorithmInterface {
+ public:
+  static SendAlgorithmInterface* Create(QuicClock* clock,
+                                        CongestionFeedbackType type);
+
+  virtual ~SendAlgorithmInterface() {}
+
+  // Called when we receive congestion information from remote peer.
+  virtual void OnIncomingCongestionInfo(
+      const CongestionInfo& congestion_info) = 0;
+
+  // Called for each received ACK, with sequence number from remote peer.
+  virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+                             size_t acked_bytes,
+                             uint64 rtt_us) = 0;
+
+  virtual void OnIncomingLoss(int number_of_lost_packets) = 0;
+
+  // Inform that we sent x bytest to the wire, and if that was a retransmission.
+  // Note: this function must be called for every packet sent to the wire.
+  virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
+                          size_t bytes,
+                          bool retransmit) = 0;
+
+  // Calculate the time until we can send the next packet.
+  // Usage: When this returns 0, CongestionWindow returns the number of bytes
+  // of the congestion window.
+  virtual int TimeUntilSend(bool retransmit) = 0;
+
+  // The current available congestion window in bytes.
+  virtual size_t AvailableCongestionWindow() = 0;
+
+  // What's the current estimated bandwidth in bytes per second.
+  virtual int BandwidthEstimate() = 0;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
diff --git a/net/quic/quic_clock.cc b/net/quic/quic_clock.cc
new file mode 100644
index 0000000..0d7d54a3
--- /dev/null
+++ b/net/quic/quic_clock.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_clock.h"
+
+#include "base/time.h"
+
+namespace net {
+
+QuicClock::QuicClock() {
+}
+
+QuicClock::~QuicClock() {}
+
+uint64 QuicClock::NowInUsec() {
+  base::TimeDelta delta = base::Time::Now() - base::Time::UnixEpoch();
+  return delta.InMicroseconds();
+}
+
+}  // namespace net
diff --git a/net/quic/quic_clock.h b/net/quic/quic_clock.h
new file mode 100644
index 0000000..df5f510
--- /dev/null
+++ b/net/quic/quic_clock.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_CLOCK_H_
+#define NET_QUIC_QUIC_CLOCK_H_
+
+#include "base/basictypes.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+typedef double WallTime;
+
+// Clock to efficiently retrieve an approximately accurate time from an
+// EpollServer.
+class NET_EXPORT_PRIVATE QuicClock {
+ public:
+  QuicClock();
+  virtual ~QuicClock();
+
+  // Returns the approximate current time as the number of microseconds
+  // since the Unix epoch.
+  virtual uint64 NowInUsec();
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_CLOCK_H_
diff --git a/net/quic/test_tools/mock_clock.cc b/net/quic/test_tools/mock_clock.cc
new file mode 100644
index 0000000..59067f4
--- /dev/null
+++ b/net/quic/test_tools/mock_clock.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/test_tools/mock_clock.h"
+
+namespace net {
+
+MockClock::MockClock() : now_(0) {
+}
+
+MockClock::~MockClock() {
+}
+
+uint64 MockClock::NowInUsec() {
+  return now_;
+}
+
+}  // namespace net
diff --git a/net/quic/test_tools/mock_clock.h b/net/quic/test_tools/mock_clock.h
new file mode 100644
index 0000000..3a69869
--- /dev/null
+++ b/net/quic/test_tools/mock_clock.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_TEST_TOOLS_MOCK_CLOCK_H_
+#define NET_QUIC_TEST_TOOLS_MOCK_CLOCK_H_
+
+#include "net/quic/quic_clock.h"
+
+#include "base/compiler_specific.h"
+#include "base/time.h"
+
+namespace net {
+
+class MockClock : public QuicClock {
+ public:
+  MockClock();
+
+  virtual ~MockClock();
+
+  virtual uint64 NowInUsec() OVERRIDE;
+
+  void AdvanceTime(WallTime delta) {
+    uint64 delta_us = delta * base::Time::kMicrosecondsPerSecond;
+    now_ += delta_us;
+  }
+
+ private:
+  uint64 now_;
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_TEST_TOOLS_MOCK_CLOCK_H_