Incast, TCP options
authorAdrian S Tam <adrian.sw.tam@gmail.com>
Wed, 07 Dec 2011 15:43:04 -0500
changeset 7620 b2579b330f01
parent 7619 b4dee6307aa7
child 7621 ab42fd168916
Incast, TCP options
scratch/incast.cc
src/applications/model/incast-agg.cc
src/applications/model/incast-agg.h
src/applications/model/incast-send.cc
src/applications/model/incast-send.h
src/applications/wscript
src/internet/model/tcp-admctrl.cc
src/internet/model/tcp-admctrl.h
src/internet/model/tcp-header.cc
src/internet/model/tcp-header.h
src/internet/model/tcp-l4-protocol.cc
src/internet/model/tcp-option-end.cc
src/internet/model/tcp-option-end.h
src/internet/model/tcp-option-mss.cc
src/internet/model/tcp-option-mss.h
src/internet/model/tcp-option-nop.cc
src/internet/model/tcp-option-nop.h
src/internet/model/tcp-option-sack-permitted.cc
src/internet/model/tcp-option-sack-permitted.h
src/internet/model/tcp-option-sack.cc
src/internet/model/tcp-option-sack.h
src/internet/model/tcp-option-ts.cc
src/internet/model/tcp-option-ts.h
src/internet/model/tcp-option-winscale.cc
src/internet/model/tcp-option-winscale.h
src/internet/model/tcp-option.cc
src/internet/model/tcp-option.h
src/internet/model/tcp-socket-base.cc
src/internet/wscript
src/network/utils/drop-tail-queue.h
src/point-to-point/model/point-to-point-net-device.cc
src/point-to-point/model/point-to-point-net-device.h
src/point-to-point/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scratch/incast.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,152 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2011 (c) New York University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@google.com>
+ *
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/netanim-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/point-to-point-layout-module.h"
+
+// Network topology (default)
+//
+//        n2 n3 n4              .
+//         \ | /                .
+//          \|/                 .
+//     n1--- n0---n5            .
+//          /|\                 .
+//         / | \                .
+//        n8 n7 n6              .
+//
+
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("IncastSim");
+
+int 
+main (int argc, char *argv[])
+{
+  //
+  // Default number of nodes in the star.  Overridable by command line argument.
+  //
+  uint32_t nIncaster = 3;     // Number of incast senders
+  uint32_t bufSize = 32768;
+  uint32_t sru = 4096;
+  uint32_t unitsize = 3000;
+  uint16_t maxwin = 65535;
+  bool useStdout = true;
+
+  CommandLine cmd;
+  cmd.AddValue ("incaster", "Number of incast senders", nIncaster);
+  cmd.AddValue ("stdout", "Output packet trace to stdout", useStdout);
+  cmd.AddValue ("bufsize", "Drop-tail queue buffer size in bytes", bufSize);
+  cmd.AddValue ("sru", "Size of server request unit in bytes", sru);
+  cmd.AddValue ("unitsize", "Size of virtual bytes increment upon SYN packets", unitsize);
+  cmd.AddValue ("maxwin", "Maximum size of advertised window", maxwin);
+
+  cmd.Parse (argc, argv);
+
+  NS_LOG_INFO ("Build star topology.");
+  PointToPointHelper pointToPoint;
+  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("1000Mbps"));
+  pointToPoint.SetDeviceAttribute ("UnitSize", UintegerValue (unitsize));
+  pointToPoint.SetChannelAttribute ("Delay", StringValue ("25us"));
+  pointToPoint.SetQueue("ns3::DropTailQueue",
+    "Mode", EnumValue(DropTailQueue::BYTES),
+    "MaxBytes", UintegerValue(bufSize));
+  PointToPointStarHelper star (nIncaster+1, pointToPoint);
+
+  NS_LOG_INFO ("Install internet stack on all nodes.");
+  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue(1448));
+  Config::SetDefault ("ns3::TcpSocketBase::MaxWindowSize", UintegerValue(maxwin));
+  Config::SetDefault ("ns3::TcpNewReno::ReTxThreshold", UintegerValue(2));
+  //Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue(0));
+  InternetStackHelper internet;
+  star.InstallStack (internet);
+
+  NS_LOG_INFO ("Assign IP Addresses.");
+  star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"));
+  std::list<Ipv4Address> senders;
+  for (uint32_t i=1; i <= nIncaster; i++)
+    {
+      NS_LOG_INFO ("Sender IP " << star.GetSpokeIpv4Address (i));
+      senders.push_back (star.GetSpokeIpv4Address (i));
+    };
+
+
+  NS_LOG_INFO ("Create applications.");
+
+  //
+  // Create a packet sink on spoke 0 to receive packets.
+  // 
+  Ptr<IncastAggregator> app = CreateObject<IncastAggregator> ();
+  app->SetSenders (senders);
+  app->SetStartTime (Seconds (1.0));
+  star.GetSpokeNode (0)->AddApplication(app);
+
+  //
+  // Create send applications to send TCP to spoke 0, one on each other spoke node.
+  //
+  for (uint32_t i = 1; i < star.SpokeCount (); ++i)
+    {
+      Ptr<IncastSender> sendApp = CreateObject<IncastSender> ();
+      sendApp->SetAttribute ("Aggregator", Ipv4AddressValue(star.GetSpokeIpv4Address (0)));
+      sendApp->SetAttribute ("SRU", UintegerValue(sru));
+      sendApp->SetStartTime (Seconds (1.0));
+      star.GetSpokeNode (i)->AddApplication(sendApp);
+    }
+
+  NS_LOG_INFO ("Enable static global routing.");
+  //
+  // Turn on global static routing so we can actually be routed across the star.
+  //
+  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+  //
+  // Turn on trace
+  //
+  if (useStdout)
+    {
+      std::cout << std::setprecision(9) << std::fixed;
+      std::cerr << std::setprecision(9) << std::fixed;
+      std::clog << std::setprecision(9) << std::fixed;
+      pointToPoint.EnableAsciiAll (Create<OutputStreamWrapper>(&std::clog));
+    }
+  else
+    {
+      AsciiTraceHelper ascii;
+      Ptr<OutputStreamWrapper> tracefile = ascii.CreateFileStream ("incast.tr");
+      *(tracefile->GetStream()) << std::setprecision(9) << std::fixed;
+      pointToPoint.EnableAsciiAll (tracefile);
+    }
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/model/incast-agg.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,249 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 New York University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/boolean.h"
+#include "ns3/internet-module.h"
+#include "ns3/incast-agg.h"
+
+NS_LOG_COMPONENT_DEFINE ("IncastAggregator");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (IncastAggregator);
+
+TypeId
+IncastAggregator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IncastAggregator")
+    .SetParent<Application> ()
+    .AddConstructor<IncastAggregator> ()
+    .AddAttribute ("Port",
+                   "TCP port number for the incast applications",
+                   UintegerValue (5000),
+                   MakeUintegerAccessor (&IncastAggregator::m_port),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("Initiator",
+                   "The aggregator is the initiator of the connections",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&IncastAggregator::m_init),
+                   MakeBooleanChecker ())
+    .AddAttribute ("Protocol", "The type of connection-oriented protocol to use.",
+                   TypeIdValue (TcpAdmCtrl::GetTypeId ()),
+                   MakeTypeIdAccessor (&IncastAggregator::m_tid),
+                   MakeTypeIdChecker ())
+  ;
+  return tid;
+}
+
+
+IncastAggregator::IncastAggregator ()
+  : m_running (false),
+    m_listened (false)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+IncastAggregator::~IncastAggregator ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+IncastAggregator::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_sockets.clear ();
+  // chain up
+  Application::DoDispose ();
+}
+
+void
+IncastAggregator::SetSenders (const std::list<Ipv4Address>& n)
+{
+  NS_LOG_FUNCTION (this);
+  m_senders = n;
+}
+
+// Application Methods
+void IncastAggregator::StartApplication (void) // Called at time specified by Start
+{
+  NS_LOG_FUNCTION (this);
+
+  // Do nothing if incast is running
+  if (m_running) return;
+
+  m_running = true;
+  m_closeCount = 0;
+
+  if (m_init)
+    { // Connection initiator. Connect to each peer and wait for data.
+      for (std::list<Ipv4Address>::iterator i = m_senders.begin (); i != m_senders.end (); ++i)
+        {
+          Ptr<TcpAdmCtrl> s = GetNode ()->GetObject<TcpL4Protocol> ()->CreateSocket(m_tid)->GetObject<TcpAdmCtrl> ();
+          // Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
+          if (s->GetSocketType () != Socket::NS3_SOCK_STREAM &&
+              s->GetSocketType () != Socket::NS3_SOCK_SEQPACKET)
+            {
+              NS_FATAL_ERROR ("Only NS_SOCK_STREAM or NS_SOCK_SEQPACKET sockets are allowed.");
+            }
+
+          // Bind, connect, and wait for data
+          NS_LOG_LOGIC ("Connect to " << *i);
+          s->Bind ();
+          s->Connect (InetSocketAddress (*i, m_port));
+          s->ShutdownSend ();
+          s->SetRecvCallback (MakeCallback (&IncastAggregator::HandleRead, this));
+          s->SetCloseCallbacks (
+            MakeCallback (&IncastAggregator::HandleClose, this),
+            MakeCallback (&IncastAggregator::HandleClose, this));
+          s->SetAdmCtrlCallback (MakeCallback (&IncastAggregator::HandleAdmCtrl, this));
+          // Remember this socket, in case we need to terminate all of them prematurely
+          m_sockets.push_back(s);
+        }
+    }
+  else if (!m_listened)
+    { // Connection responder. Wait for connection.
+      Ptr<TcpAdmCtrl> s = GetNode ()->GetObject<TcpL4Protocol> ()->CreateSocket(m_tid)->GetObject<TcpAdmCtrl> ();
+      s->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_port));
+      s->Listen ();
+      s->ShutdownSend ();
+      s->SetRecvCallback (MakeCallback (&IncastAggregator::HandleRead, this));
+      s->SetAcceptCallback (
+        MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
+        MakeCallback (&IncastAggregator::HandleAccept, this));
+      s->SetAdmCtrlCallback (MakeCallback (&IncastAggregator::HandleAdmCtrl, this));
+      m_listened = true;
+      // Remember this listening socket, terminate this when application finishes
+      m_sockets.push_back(s);
+    };
+}
+
+void IncastAggregator::HandleAdmCtrl (Ptr<TcpAdmCtrl> sock, Ipv4Address addr, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << addr << port);
+  m_suspendedSocket.push_back(sock);
+}
+
+void IncastAggregator::HandleRead (Ptr<Socket> socket)
+{
+  // Discard all data being read
+  NS_LOG_FUNCTION (this << socket);
+  Ptr<Packet> packet;
+  uint32_t bytecount = 0;
+  while (packet = socket->Recv ())
+    {
+      bytecount += packet->GetSize ();
+    };
+  std::list<Ptr<Socket> >::iterator i = std::find(m_runningSockets.begin (), m_runningSockets.end (), socket);
+  std::list<uint32_t>::iterator p = m_byteCount.begin ();
+  if (i == m_runningSockets.end ())
+    {
+      m_runningSockets.push_back (socket);
+      p = m_byteCount.insert (m_byteCount.end (), bytecount);
+    }
+  else
+    {
+      std::list<Ptr<Socket> >::iterator q = m_runningSockets.begin ();
+      while (q != i)
+        {
+          ++q; ++p;
+        }
+      *p += bytecount;
+    }
+  std::list<uint32_t>::iterator mincount;
+  std::list<uint32_t>::iterator maxcount;
+  mincount = std::min_element (m_byteCount.begin(), m_byteCount.end());
+  maxcount = std::max_element (m_byteCount.begin(), m_byteCount.end());
+  if ((*maxcount - *mincount >= 4096) && (*maxcount - *p <= 2048))
+    {
+      socket->SetAttribute ("MaxWindowSize", UintegerValue(6000));
+    }
+  else
+    {
+      socket->SetAttribute ("MaxWindowSize", UintegerValue(65535));
+    }
+}
+
+void IncastAggregator::HandleClose (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+  ++m_closeCount;
+  m_sockets.remove (socket);
+  std::list<uint32_t>::iterator p = m_byteCount.begin ();
+  std::list<Ptr<Socket> >::iterator q = m_runningSockets.begin ();
+  while (*q != socket && q != m_runningSockets.end ())
+    {
+      ++q; ++p;
+    }
+  if (q != m_runningSockets.end ())
+    {
+      m_byteCount.erase (p);
+      m_runningSockets.erase (q);
+    }
+  if (m_closeCount == m_senders.size ())
+    {
+      // Start next round of incast
+      m_running = false;
+      Simulator::ScheduleNow (&IncastAggregator::RoundFinish, this);
+    }
+  else if (!m_suspendedSocket.empty())
+    {
+      // Replace the terminated connection with a suspended one
+      Ptr<TcpAdmCtrl> sock = m_suspendedSocket.front();
+      m_suspendedSocket.pop_front();
+      sock->ResumeConnection ();
+    }
+}
+
+void IncastAggregator::RoundFinish (void)
+{
+  NS_LOG_FUNCTION (this);
+  if (!m_roundFinish.IsNull ()) m_roundFinish ();
+}
+
+void IncastAggregator::HandleAccept (Ptr<Socket> socket, const Address& from)
+{
+  NS_LOG_FUNCTION (this << socket << from);
+  socket->SetRecvCallback (MakeCallback (&IncastAggregator::HandleRead, this));
+  socket->SetCloseCallbacks (
+    MakeCallback (&IncastAggregator::HandleClose, this),
+    MakeCallback (&IncastAggregator::HandleClose, this));
+}
+
+void IncastAggregator::StopApplication (void) // Called at time specified by Stop
+{
+  NS_LOG_FUNCTION (this);
+
+  for (std::list<Ptr<Socket> >::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
+    {
+      (*i)->Close ();
+    }
+}
+
+void IncastAggregator::SetRoundFinishCallback (Callback<void> cb)
+{
+  NS_LOG_FUNCTION (this);
+  m_roundFinish = cb;
+};
+
+} // Namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/model/incast-agg.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,90 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 New York University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef INCAST_AGGREGATOR_H
+#define INCAST_AGGREGATOR_H
+
+#include "ns3/application.h"
+#include "ns3/ipv4-interface-container.h"
+#include "ns3/inet-socket-address.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup applications
+ * \defgroup incast IncastAggregator
+ *
+ * A part of the incast application. This component is the `aggregator' part of
+ * the incast application, namely, it accepts data from remote peers. Because
+ * of the connection-oriented assumption on the sockets, only SOCK_STREAM and
+ * SOCK_SEQPACKET sockets are supported, i.e. TCP but not UDP.
+ */
+class IncastAggregator : public Application
+{
+public:
+  static TypeId GetTypeId (void);
+
+  IncastAggregator ();
+
+  virtual ~IncastAggregator ();
+
+  /**
+   * Associate this incast aggregator with the incast senders
+   */
+  void SetSenders (const std::list<Ipv4Address>& n);
+
+  /**
+   * Set round finish callback
+   */
+  void SetRoundFinishCallback (Callback<void> cb);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  // inherited from Application base class.
+  virtual void StartApplication (void);    // Called at time specified by Start
+  virtual void StopApplication (void);     // Called at time specified by Stop
+
+  // Incast variables
+  uint16_t        m_port;         //< TCP port for incast applications
+  bool            m_init;         //< Aggregator is the connection initiator
+  TypeId          m_tid;          //< Socket's TypeId
+  bool            m_running;      //< Incast running
+  bool            m_listened;     //< Have a socket listening for incoming connection?
+  uint32_t        m_closeCount;   //< Count of closed connections
+  std::list<Ptr<Socket> >  m_sockets;      //< Associated sockets
+  std::list<Ipv4Address>   m_senders;      //< All incast senders
+  std::list<Ptr<TcpAdmCtrl> > m_suspendedSocket;       //< suspended TCP socket
+  std::list<Ptr<Socket> > m_runningSockets;       //< All running sockets
+  std::list<uint32_t> m_byteCount;
+
+  Callback<void>  m_roundFinish;  //< Round-finish callback
+
+private:
+  void HandleAccept (Ptr<Socket> socket, const Address& from);
+  void HandleClose (Ptr<Socket> socket);
+  void HandleRead (Ptr<Socket> socket);
+  void HandleAdmCtrl (Ptr<TcpAdmCtrl> sock, Ipv4Address addr, uint16_t port);
+  void RoundFinish (void);
+};
+
+} // namespace ns3
+
+#endif /* INCAST_AGGREGATOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/model/incast-send.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,162 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 New York University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/boolean.h"
+#include "ns3/internet-module.h"
+#include "ns3/incast-send.h"
+
+NS_LOG_COMPONENT_DEFINE ("IncastSender");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (IncastSender);
+
+TypeId
+IncastSender::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IncastSender")
+    .SetParent<Application> ()
+    .AddConstructor<IncastSender> ()
+    .AddAttribute ("SRU",
+                   "Size of one server request unit",
+                   UintegerValue (1000),
+                   MakeUintegerAccessor (&IncastSender::m_sru),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("Port",
+                   "TCP port number for the incast applications",
+                   UintegerValue (5000),
+                   MakeUintegerAccessor (&IncastSender::m_port),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("Initiator",
+                   "The sender is the initiator of the connections",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&IncastSender::m_init),
+                   MakeBooleanChecker ())
+    .AddAttribute ("Aggregator", "The address of the aggregator",
+                   Ipv4AddressValue (),
+                   MakeIpv4AddressAccessor (&IncastSender::m_agg),
+                   MakeIpv4AddressChecker ())
+    .AddAttribute ("Protocol", "The type of connection-oriented protocol to use.",
+                   TypeIdValue (TcpAdmCtrl::GetTypeId ()),
+                   MakeTypeIdAccessor (&IncastSender::m_tid),
+                   MakeTypeIdChecker ())
+  ;
+  return tid;
+}
+
+
+IncastSender::IncastSender () : m_socket (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+IncastSender::~IncastSender ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+IncastSender::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  m_socket = 0;
+  // chain up
+  Application::DoDispose ();
+}
+
+// Application Methods
+void IncastSender::StartApplication (void) // Called at time specified by Start
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_init)
+    { // Connection initiator. Make a new socket, connect to aggregator and send data.
+      m_socket = GetNode ()->GetObject<TcpL4Protocol> ()->CreateSocket(m_tid);
+      // Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
+      if (m_socket->GetSocketType () != Socket::NS3_SOCK_STREAM &&
+          m_socket->GetSocketType () != Socket::NS3_SOCK_SEQPACKET)
+        {
+          NS_FATAL_ERROR ("Only NS_SOCK_STREAM or NS_SOCK_SEQPACKET sockets are allowed.");
+        }
+
+      // Bind, connect, and send data
+      m_sentCount = 0;
+      m_socket->Bind ();
+      m_socket->Connect (InetSocketAddress (m_agg, m_port));
+      m_socket->ShutdownRecv ();
+      m_socket->SetSendCallback (MakeCallback (&IncastSender::HandleSend, this));
+    }
+  else
+    { // Connection responder. Wait for connection and send data.
+      m_sentCount = 0;
+      m_socket  = GetNode ()->GetObject<TcpL4Protocol> ()->CreateSocket(m_tid);
+      m_socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), m_port));
+      m_socket->Listen ();
+      m_socket->ShutdownRecv ();
+      m_socket->SetSendCallback (MakeCallback (&IncastSender::HandleSend, this));
+      m_socket->SetAcceptCallback (
+        MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
+        MakeCallback (&IncastSender::HandleAccept, this));
+    };
+}
+
+void IncastSender::HandleSend (Ptr<Socket> socket, uint32_t n)
+{
+  NS_LOG_FUNCTION (this);
+
+  while (m_sentCount < m_sru && socket->GetTxAvailable ())
+    { // Not yet finish the one SRU data
+      Ptr<Packet> packet = Create<Packet> (std::min(m_sru - m_sentCount, n));
+      int actual = socket->Send (packet);
+      if (actual > 0) m_sentCount += actual;
+      NS_LOG_LOGIC(actual << " bytes sent");
+    }
+  // If finished, close the socket
+  if (m_sentCount == m_sru)
+    {
+      NS_LOG_LOGIC("Socket close");
+      socket->Close ();
+    }
+}
+
+void IncastSender::HandleAccept (Ptr<Socket> socket, const Address& from)
+{
+  NS_LOG_FUNCTION (this << socket);
+  InetSocketAddress addr = InetSocketAddress::ConvertFrom(from);
+  NS_LOG_LOGIC ("Accepting connection from " << addr.GetIpv4() << ":" <<addr.GetPort());
+  if (!m_init)
+    { // Stop listening sockets to prevent parallel connections
+      m_socket->Close ();
+      m_socket = socket;
+    };
+  socket->SetSendCallback (MakeCallback (&IncastSender::HandleSend, this));
+}
+
+void IncastSender::StopApplication (void) // Called at time specified by Stop
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_socket) m_socket->Close ();
+}
+
+} // Namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/model/incast-send.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 New York University
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef INCAST_SENDER_H
+#define INCAST_SENDER_H
+
+#include "ns3/application.h"
+#include "ns3/ipv4-interface-container.h"
+#include "ns3/inet-socket-address.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup applications
+ * \defgroup incast IncastSender
+ *
+ * A part of the incast application. This component is the `sender' part of
+ * the incast application, namely, it accepts data from remote peers. Because
+ * of the connection-oriented assumption on the sockets, only SOCK_STREAM and
+ * SOCK_SEQPACKET sockets are supported, i.e. TCP but not UDP.
+ */
+class IncastSender : public Application
+{
+public:
+  static TypeId GetTypeId (void);
+
+  IncastSender ();
+
+  virtual ~IncastSender ();
+
+protected:
+  virtual void DoDispose (void);
+private:
+  // inherited from Application base class.
+  virtual void StartApplication (void);    // Called at time specified by Start
+  virtual void StopApplication (void);    // Called at time specified by Start
+
+  // Incast variables
+  uint32_t        m_sentCount;    //< Number of bytes sent
+  uint32_t        m_sru;          //< Size of one SRU
+  uint16_t        m_port;         //< TCP port for incast applications
+  bool            m_init;         //< SENDER is the connection initiator
+  Ipv4Address     m_agg;          //< Address of the aggregator, use when senders are connection initiators
+  TypeId          m_tid;          //< Socket's TypeId
+  Ptr<Socket>     m_socket;       //< TCP socket
+
+private:
+  void HandleAccept (Ptr<Socket> socket, const Address& from);
+  void HandleSend (Ptr<Socket> socket, uint32_t n);
+};
+
+} // namespace ns3
+
+#endif /* INCAST_SENDER_H */
--- a/src/applications/wscript	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/applications/wscript	Wed Dec 07 15:43:04 2011 -0500
@@ -18,6 +18,8 @@
         'model/udp-echo-client.cc',
         'model/udp-echo-server.cc',
         'model/v4ping.cc',
+        'model/incast-agg.cc',
+        'model/incast-send.cc',
         'helper/bulk-send-helper.cc',
         'helper/on-off-helper.cc',
         'helper/packet-sink-helper.cc',
@@ -50,6 +52,8 @@
         'model/udp-echo-client.h',
         'model/udp-echo-server.h',
         'model/v4ping.h',
+        'model/incast-agg.h',
+        'model/incast-send.h',
         'helper/bulk-send-helper.h',
         'helper/on-off-helper.h',
         'helper/packet-sink-helper.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-admctrl.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,166 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#define NS_LOG_APPEND_CONTEXT \
+  if (m_node) { std::clog << Simulator::Now ().GetSeconds () << " [node " << m_node->GetId () << "] "; }
+
+#include "tcp-admctrl.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "tcp-option-ts.h"
+
+NS_LOG_COMPONENT_DEFINE ("TcpAdmCtrl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpAdmCtrl);
+
+TypeId
+TcpAdmCtrl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpAdmCtrl")
+    .SetParent<TcpNewReno> ()
+    .AddConstructor<TcpAdmCtrl> ()
+  ;
+  return tid;
+}
+
+TcpAdmCtrl::TcpAdmCtrl (void)
+  : m_lastTS (0), m_ece (false), m_cwr (false)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+TcpAdmCtrl::TcpAdmCtrl (const TcpAdmCtrl& sock)
+  : TcpNewReno (sock), m_lastTS (0), m_ece (false), m_cwr (false)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_LOGIC ("Invoked the copy constructor");
+}
+
+TcpAdmCtrl::~TcpAdmCtrl (void)
+{
+}
+
+Ptr<TcpSocketBase>
+TcpAdmCtrl::Fork (void)
+{
+  return CopyObject<TcpAdmCtrl> (this);
+}
+
+/** Overloading TcpSocketBase::DoForwardUp to intercept the ECN mark in Ipv4Header */
+void
+TcpAdmCtrl::DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port,
+                          Ptr<Ipv4Interface> incomingInterface)
+{
+  TcpHeader tcpHeader;
+  packet->PeekHeader (tcpHeader);
+  if (header.GetEcn() == Ipv4Header::CE && !m_admCtrlCallback.IsNull ())
+    { // ECN-marked, if it is a SYN packet, hold it back for a while
+      if (tcpHeader.GetFlags () & TcpHeader::SYN)
+        {
+          NS_LOG_LOGIC("Marked handshake packet found.");
+          m_bufPacket = packet;
+          m_bufHeader = header;
+          m_bufPort = port;
+          m_bufIface = incomingInterface;
+          m_admCtrlCallback (this, header.GetSource(), port);
+          return;
+        }
+      else
+        { // Non handshake packet: Cut down window
+          m_ece = true;
+        }
+    }
+/*  if (tcpHeader.GetFlags () & TcpHeader::ECE)
+    {
+      // Peer echoed ECN. Reduce window
+      m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2);
+      m_cWnd = m_ssThresh + 3 * m_segmentSize;
+      m_cwr = true;
+    }
+  else if (m_cwr)
+    { // Peer acknowledged my window reduction. Reset CWR flag
+      m_cwr = false;
+    };
+  if (tcpHeader.GetFlags () & TcpHeader::CWR)
+    { // Peer reduced window. Reset ECE flag
+      m_ece = false;
+    }
+*/  // Run the normal DoForwardUp() function
+  TcpSocketBase::DoForwardUp(packet, header, port, incomingInterface);
+}
+
+void
+TcpAdmCtrl::SetAdmCtrlCallback(Callback<void, Ptr<TcpAdmCtrl>, Ipv4Address, uint16_t> cb)
+{
+  m_admCtrlCallback = cb;
+}
+
+void
+TcpAdmCtrl::ResumeConnection (void)
+{
+  NS_LOG_FUNCTION(this);
+  TcpSocketBase::DoForwardUp(m_bufPacket, m_bufHeader, m_bufPort, m_bufIface);
+  m_bufPacket = 0;
+  m_bufIface = 0;
+}
+
+void
+TcpAdmCtrl::AddOptions (TcpHeader& h)
+{
+  Ptr<TcpOptionTS> op = CreateObject<TcpOptionTS> ();
+  op->SetTimestamp (uint32_t (Now ().GetNanoSeconds () & std::numeric_limits<uint32_t>::max ()));
+  op->SetEcho (m_lastTS);
+  h.AppendOption (op);
+}
+
+void
+TcpAdmCtrl::ReadOptions (const TcpHeader& h)
+{
+  Ptr<TcpOption> opt = h.GetOption (8);
+  if (opt == NULL) return;
+  Ptr<TcpOptionTS> op = opt->GetObject<TcpOptionTS> ();
+
+  m_lastTS = op->GetTimestamp ();
+  if (! m_inFastRec) return;
+  // RFC 3626 algorithm:
+  //  echoTS is 'greater than' m_retxTS if
+  //    echoTS > m_retxTX && echoTS - m_retxTS <= MAXVALUE/2
+  // OR echoTS < m_retxTS && m_retxTS - echoTS > MAXVALUE/2
+  uint32_t echoTS  = op->GetEcho ();
+  static const uint32_t halfMax = std::numeric_limits<uint32_t>::max ()/2;
+  if (((echoTS > m_retxTS) && (echoTS - m_retxTS) <= halfMax)
+      || ((echoTS < m_retxTS) && (m_retxTS - echoTS) > halfMax))
+    { // The retransmitted packet is probably lost again!
+      DoRetransmit ();
+    }
+}
+
+void
+TcpAdmCtrl::DoRetransmit (void)
+{
+  m_retxTS = uint32_t (Now ().GetNanoSeconds () & std::numeric_limits<uint32_t>::max ());
+  TcpSocketBase::DoRetransmit ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-admctrl.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_ADMCTRL_H
+#define TCP_ADMCTRL_H
+
+#include "tcp-newreno.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup socket
+ * \ingroup tcp
+ *
+ * \brief An implementation of a stream socket using TCP.
+ *
+ * This class contains the NewReno implementation of TCP, as of RFC2582.
+ */
+class TcpAdmCtrl : public TcpNewReno
+{
+public:
+  static TypeId GetTypeId (void);
+  /**
+   * Create an unbound tcp socket.
+   */
+  TcpAdmCtrl (void);
+  TcpAdmCtrl (const TcpAdmCtrl& sock);
+  virtual ~TcpAdmCtrl (void);
+  void SetAdmCtrlCallback(Callback<void, Ptr<TcpAdmCtrl>, Ipv4Address, uint16_t> cb);
+  void ResumeConnection (void);
+
+protected:
+  virtual Ptr<TcpSocketBase> Fork (void);
+  virtual void DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface);
+  virtual void AddOptions (TcpHeader& h);
+  virtual void ReadOptions (const TcpHeader& h);
+  virtual void DoRetransmit (void);
+
+private:
+  Ptr<Packet>        m_bufPacket;
+  Ipv4Header         m_bufHeader;
+  uint16_t           m_bufPort;
+  Ptr<Ipv4Interface> m_bufIface;
+  uint32_t           m_lastTS;
+  uint32_t           m_retxTS;
+  bool               m_ece; // Should send ECE flag
+  bool               m_cwr; // Should send CWR flag
+
+  Callback<void, Ptr<TcpAdmCtrl>, Ipv4Address, uint16_t> m_admCtrlCallback;
+};
+
+} // namespace ns3
+
+#endif /* TCP_NEWRENO_H */
--- a/src/internet/model/tcp-header.cc	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/internet/model/tcp-header.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <iostream>
 #include "tcp-header.h"
+#include "tcp-option.h"
 #include "ns3/buffer.h"
 #include "ns3/address-utils.h"
 
@@ -70,6 +71,7 @@
 }
 void TcpHeader::SetLength (uint8_t length)
 {
+  // Caution: Setting length may fail the execution as the real length shall be calculated automatically
   m_length = length;
 }
 void TcpHeader::SetFlags (uint8_t flags)
@@ -208,10 +210,16 @@
       os<<"]";
     }
   os<<" Seq="<<m_sequenceNumber<<" Ack="<<m_ackNumber<<" Win="<<m_windowSize;
+  for (std::list<Ptr<TcpOption> >::const_iterator op = m_options.begin (); op != m_options.end (); ++op)
+    {
+      os<<" "<< (*op)->GetInstanceTypeId ().GetName () <<"(";
+      (*op)->Print (os);
+      os<<")";
+    }
 }
 uint32_t TcpHeader::GetSerializedSize (void)  const
 {
-  return 4*m_length;
+  return 4*GetLength ();
 }
 void TcpHeader::Serialize (Buffer::Iterator start)  const
 {
@@ -220,11 +228,27 @@
   i.WriteHtonU16 (m_destinationPort);
   i.WriteHtonU32 (m_sequenceNumber.GetValue ());
   i.WriteHtonU32 (m_ackNumber.GetValue ());
-  i.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
+  i.WriteHtonU16 (GetLength () << 12 | m_flags); //reserved bits are all zero
   i.WriteHtonU16 (m_windowSize);
   i.WriteHtonU16 (0);
   i.WriteHtonU16 (m_urgentPointer);
 
+  // Serialize options if they exists
+  unsigned optionLen = 0;
+  for (std::list<Ptr<TcpOption> >::const_iterator op = m_options.begin (); op != m_options.end (); ++op)
+    {
+      optionLen += (*op)->GetSerializedSize ();
+      (*op)->Serialize(i);
+      i.Next ((*op)->GetSerializedSize ());
+
+    };
+  while (optionLen % 4)
+    {
+      ++optionLen;
+      i.WriteU8 (0);
+    };
+
+  // Make checksum
   if(m_calcChecksum)
     {
       uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
@@ -250,6 +274,30 @@
   i.Next (2);
   m_urgentPointer = i.ReadNtohU16 ();
 
+  // Deserialize options if they exist
+  m_options.clear ();
+  unsigned optionLen = (m_length - 5) * 4;
+  while (optionLen)
+    {
+      uint8_t kind = i.ReadU8 ();
+      Ptr<TcpOption> op = TcpOption::CreateOption (kind);
+      optionLen -= op->Deserialize (i);
+      i.Next (op->GetSerializedSize () - 1);
+      if (op->GetKind () != 0)
+        {
+          m_options.push_back (op);
+        }
+      else
+        {
+          while(optionLen)
+            {
+              i.Next (1);
+              --optionLen;
+            };
+        }
+    };
+
+  // Do checksum
   if(m_calcChecksum)
     {
       uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
@@ -261,5 +309,32 @@
   return GetSerializedSize ();
 }
 
+void TcpHeader::AppendOption (Ptr<TcpOption> option)
+{
+  if (option->GetKind () != 0)
+    {
+      m_options.push_back (option);
+    }
+  // Update length
+  unsigned totalLen = 20;
+  for (std::list<Ptr<TcpOption> >::iterator i = m_options.begin (); i != m_options.end (); ++i)
+  {
+    totalLen += (*i)->GetSerializedSize ();
+  };
+  if (totalLen > 20) totalLen += 3;
+  m_length = totalLen >> 2;
+}
+
+Ptr<TcpOption> TcpHeader::GetOption (uint8_t kind) const
+{
+  for (std::list<Ptr<TcpOption> >::const_iterator i = m_options.begin (); i != m_options.end () ; ++i)
+    {
+      if ((*i)->GetKind () == kind)
+        {
+          return (*i);
+        }
+    }
+  return NULL;
+}
 
 } // namespace ns3
--- a/src/internet/model/tcp-header.h	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/internet/model/tcp-header.h	Wed Dec 07 15:43:04 2011 -0500
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include "ns3/header.h"
+#include "ns3/tcp-option.h"
 #include "ns3/buffer.h"
 #include "ns3/tcp-socket-factory.h"
 #include "ns3/ipv4-address.h"
@@ -117,6 +118,14 @@
    * \return the urgent pointer for this TcpHeader
    */
   uint16_t GetUrgentPointer () const;
+  /**
+   * \return Whether the header contains a specific kind of option
+   */
+  Ptr<TcpOption> GetOption (uint8_t kind) const;
+  /**
+   * \brief Add an option to the TCP header
+   */
+  void AppendOption (Ptr<TcpOption> option);
 
   /**
    * \param source the ip source to use in the underlying
@@ -167,6 +176,8 @@
   uint16_t m_initialChecksum;
   bool m_calcChecksum;
   bool m_goodChecksum;
+
+  std::list<Ptr<TcpOption> > m_options;
 };
 
 } // namespace ns3
--- a/src/internet/model/tcp-l4-protocol.cc	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/internet/model/tcp-l4-protocol.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -350,7 +350,7 @@
   // XXX outgoingHeader cannot be logged
 
   TcpHeader outgoingHeader = outgoing;
-  outgoingHeader.SetLength (5); //header length in units of 32bit words
+  /* outgoingHeader.SetLength (5); //header length in units of 32bit words */
   /* outgoingHeader.SetUrgentPointer (0); //XXX */
   if(Node::ChecksumEnabled ())
     {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-end.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-end.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionEnd);
+
+TcpOptionEnd::TcpOptionEnd ()
+{
+}
+
+TcpOptionEnd::~TcpOptionEnd ()
+{
+}
+
+TypeId
+TcpOptionEnd::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionEnd")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionEnd::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionEnd::Print (std::ostream &os) const
+{
+}
+
+uint32_t
+TcpOptionEnd::GetSerializedSize (void) const
+{
+  return 1;
+}
+
+void
+TcpOptionEnd::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (0);
+} 
+
+uint32_t
+TcpOptionEnd::Deserialize (Buffer::Iterator start)
+{
+  return 1;
+}
+
+uint8_t
+TcpOptionEnd::GetKind (void) const
+{
+  return 0;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-end.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_END_H
+#define TCP_OPTION_END_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 0 (end of option list) as in RFC793
+ */
+
+class TcpOptionEnd : public TcpOption
+{
+public:
+  TcpOptionEnd ();
+  virtual ~TcpOptionEnd ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+protected:
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_END_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-mss.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-mss.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionMSS);
+
+TcpOptionMSS::TcpOptionMSS ()
+  : m_mss (1460)
+{
+}
+
+TcpOptionMSS::~TcpOptionMSS ()
+{
+}
+
+TypeId
+TcpOptionMSS::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionMSS")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionMSS::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionMSS::Print (std::ostream &os) const
+{
+  os << m_mss;
+}
+
+uint32_t
+TcpOptionMSS::GetSerializedSize (void) const
+{
+  return 4;
+}
+
+void
+TcpOptionMSS::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (2); // Kind
+  i.WriteU8 (4); // Length
+  i.WriteHtonU16 (m_mss); // Max segment size
+} 
+
+uint32_t
+TcpOptionMSS::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t size = i.ReadU8 ();
+  NS_ASSERT (size == 4);
+  m_mss = i.ReadNtohU16 ();
+  return 4;
+}
+
+uint8_t
+TcpOptionMSS::GetKind (void) const
+{
+  return 2;
+}
+
+uint16_t
+TcpOptionMSS::GetMSS (void) const
+{
+  return m_mss;
+}
+
+void
+TcpOptionMSS::SetMSS (uint16_t mss)
+{
+  m_mss = mss;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-mss.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_MSS_H
+#define TCP_OPTION_MSS_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 2 (maximum segment size) as in RFC793
+ */
+
+class TcpOptionMSS : public TcpOption
+{
+public:
+  TcpOptionMSS ();
+  virtual ~TcpOptionMSS ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+
+  uint16_t GetMSS (void) const;
+  void SetMSS (uint16_t mss);
+protected:
+  uint16_t m_mss; // maximum segment size
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_MSS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-nop.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-nop.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionNOP);
+
+TcpOptionNOP::TcpOptionNOP ()
+{
+}
+
+TcpOptionNOP::~TcpOptionNOP ()
+{
+}
+
+TypeId
+TcpOptionNOP::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionNOP")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionNOP::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionNOP::Print (std::ostream &os) const
+{
+}
+
+uint32_t
+TcpOptionNOP::GetSerializedSize (void) const
+{
+  return 1;
+}
+
+void
+TcpOptionNOP::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (1);
+} 
+
+uint32_t
+TcpOptionNOP::Deserialize (Buffer::Iterator start)
+{
+  return 1;
+}
+
+uint8_t
+TcpOptionNOP::GetKind (void) const
+{
+  return 1;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-nop.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_NOP_H
+#define TCP_OPTION_NOP_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 1 (no operation) as in RFC793
+ */
+
+class TcpOptionNOP : public TcpOption
+{
+public:
+  TcpOptionNOP ();
+  virtual ~TcpOptionNOP ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+protected:
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_NOP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-sack-permitted.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-sack-permitted.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionSackPermitted);
+
+TcpOptionSackPermitted::TcpOptionSackPermitted ()
+{
+}
+
+TcpOptionSackPermitted::~TcpOptionSackPermitted ()
+{
+}
+
+TypeId
+TcpOptionSackPermitted::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionSackPermitted")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionSackPermitted::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionSackPermitted::Print (std::ostream &os) const
+{
+}
+
+uint32_t
+TcpOptionSackPermitted::GetSerializedSize (void) const
+{
+  return 2;
+}
+
+void
+TcpOptionSackPermitted::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (4); // Kind
+  i.WriteU8 (2); // Length
+} 
+
+uint32_t
+TcpOptionSackPermitted::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t size = i.ReadU8 ();
+  NS_ASSERT (size == 2);
+  return 2;
+}
+
+uint8_t
+TcpOptionSackPermitted::GetKind (void) const
+{
+  return 4;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-sack-permitted.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_SACK_PERMITTED_H
+#define TCP_OPTION_SACK_PERMITTED_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 4 (Selective Acknowledgement Permitted) as in RFC2018
+ */
+
+class TcpOptionSackPermitted : public TcpOption
+{
+public:
+  TcpOptionSackPermitted ();
+  virtual ~TcpOptionSackPermitted ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+protected:
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_SACK_PERMITTED_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-sack.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-sack.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionSack);
+
+TcpOptionSack::TcpOptionSack ()
+{
+}
+
+TcpOptionSack::~TcpOptionSack ()
+{
+}
+
+TypeId
+TcpOptionSack::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionSack")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionSack::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionSack::Print (std::ostream &os) const
+{
+}
+
+uint32_t
+TcpOptionSack::GetSerializedSize (void) const
+{
+  return 2;
+}
+
+void
+TcpOptionSack::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (5); // Kind
+  i.WriteU8 (2); // Length
+} 
+
+uint32_t
+TcpOptionSack::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t size = i.ReadU8 ();
+  NS_ASSERT (size == 2);
+  return 2;
+}
+
+uint8_t
+TcpOptionSack::GetKind (void) const
+{
+  return 5;
+}
+
+void
+TcpOptionSack::AddSack (SackBlock s)
+{
+  // Assumed s has no overlap with any SACK block in m_sb
+  for (ScoreBoard::iterator i = m_sb.begin (); i != m_sb.end (); ++i)
+    {
+      if (s.first < i->first)
+        {
+          m_sb.insert(i,s);
+          break;
+        }
+    }
+}
+
+uint32_t
+TcpOptionSack::SackCount (void) const
+{
+  return m_sb.size ();
+}
+
+void
+TcpOptionSack::ClearSack (void)
+{
+  m_sb.clear ();
+}
+
+SackBlock
+TcpOptionSack::GetSack (int offset)
+{
+  ScoreBoard::iterator i = m_sb.begin ();
+  while (offset--) ++i;
+  return *i;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-sack.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_SACK_H
+#define TCP_OPTION_SACK_H
+
+#include "tcp-option.h"
+#include "ns3/sequence-number.h"
+
+namespace ns3 {
+
+typedef std::pair<SequenceNumber32, SequenceNumber32> SackBlock;
+typedef std::list<SackBlock> ScoreBoard;
+
+/**
+ * Defines the TCP option of kind 5 (Selective Acknowledgement) as in RFC2018
+ */
+
+class TcpOptionSack : public TcpOption
+{
+public:
+  TcpOptionSack ();
+  virtual ~TcpOptionSack ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+
+  void AddSack (SackBlock s);
+  uint32_t SackCount (void) const;
+  void ClearSack (void);
+  SackBlock GetSack (int offset);
+protected:
+  ScoreBoard m_sb;
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_SACK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-ts.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-ts.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionTS);
+
+TcpOptionTS::TcpOptionTS ()
+  : m_timestamp (0), m_echo (0)
+{
+}
+
+TcpOptionTS::~TcpOptionTS ()
+{
+}
+
+TypeId
+TcpOptionTS::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionTS")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionTS::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionTS::Print (std::ostream &os) const
+{
+  os << m_timestamp << ";" << m_echo;
+}
+
+uint32_t
+TcpOptionTS::GetSerializedSize (void) const
+{
+  return 10;
+}
+
+void
+TcpOptionTS::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (8); // Kind
+  i.WriteU8 (10); // Length
+  i.WriteHtonU32 (m_timestamp); // Local timestamp
+  i.WriteHtonU32 (m_echo); // Echo timestamp
+} 
+
+uint32_t
+TcpOptionTS::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t size = i.ReadU8 ();
+  NS_ASSERT (size == 10);
+  m_timestamp = i.ReadNtohU32 ();
+  m_echo = i.ReadNtohU32 ();
+  return 10;
+}
+
+uint8_t
+TcpOptionTS::GetKind (void) const
+{
+  return 8;
+}
+
+uint32_t
+TcpOptionTS::GetTimestamp (void) const
+{
+  return m_timestamp;
+}
+
+uint32_t
+TcpOptionTS::GetEcho (void) const
+{
+  return m_echo;
+}
+
+void
+TcpOptionTS::SetTimestamp (uint32_t ts)
+{
+  m_timestamp = ts;
+}
+
+void
+TcpOptionTS::SetEcho (uint32_t ts)
+{
+  m_echo = ts;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-ts.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_TS_H
+#define TCP_OPTION_TS_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 8 (timestamp option) as in RFC1323
+ */
+
+class TcpOptionTS : public TcpOption
+{
+public:
+  TcpOptionTS ();
+  virtual ~TcpOptionTS ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+
+  uint32_t GetTimestamp (void) const;
+  uint32_t GetEcho (void) const;
+  void SetTimestamp (uint32_t ts);
+  void SetEcho (uint32_t ts);
+protected:
+  uint32_t m_timestamp; // local timestamp
+  uint32_t m_echo; // echo timestamp
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_TS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-winscale.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option-winscale.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOptionWinScale);
+
+TcpOptionWinScale::TcpOptionWinScale ()
+  : m_scale (0)
+{
+}
+
+TcpOptionWinScale::~TcpOptionWinScale ()
+{
+}
+
+TypeId
+TcpOptionWinScale::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOptionWinScale")
+    .SetParent<TcpOption> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOptionWinScale::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+TcpOptionWinScale::Print (std::ostream &os) const
+{
+  os << m_scale;
+}
+
+uint32_t
+TcpOptionWinScale::GetSerializedSize (void) const
+{
+  return 3;
+}
+
+void
+TcpOptionWinScale::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (2); // Kind
+  i.WriteU8 (3); // Length
+  i.WriteU8 (m_scale); // Max segment size
+} 
+
+uint32_t
+TcpOptionWinScale::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t size = i.ReadU8 ();
+  NS_ASSERT (size == 3);
+  m_scale = i.ReadU8 ();
+  return 3;
+}
+
+uint8_t
+TcpOptionWinScale::GetKind (void) const
+{
+  return 3;
+}
+
+uint8_t
+TcpOptionWinScale::GetScale (void) const
+{
+  return m_scale;
+}
+
+void
+TcpOptionWinScale::SetScale (uint8_t scale)
+{
+  m_scale = scale;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option-winscale.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_WINSCALE_H
+#define TCP_OPTION_WINSCALE_H
+
+#include "tcp-option.h"
+
+namespace ns3 {
+
+/**
+ * Defines the TCP option of kind 3 (window scale option) as in RFC1323
+ */
+
+class TcpOptionWinScale : public TcpOption
+{
+public:
+  TcpOptionWinScale ();
+  virtual ~TcpOptionWinScale ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  virtual uint8_t GetKind (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+
+  uint8_t GetScale (void) const;
+  void SetScale (uint8_t scale);
+protected:
+  uint8_t m_scale; // Window scaling in number of bit shift
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION_WINSCALE */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#include "tcp-option.h"
+#include "tcp-option-end.h"
+#include "tcp-option-nop.h"
+#include "tcp-option-mss.h"
+#include "tcp-option-winscale.h"
+#include "tcp-option-sack-permitted.h"
+#include "tcp-option-sack.h"
+#include "tcp-option-ts.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TcpOption);
+
+TcpOption::TcpOption ()
+{
+}
+
+TcpOption::~TcpOption ()
+{
+}
+
+TypeId
+TcpOption::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpOption")
+    .SetParent<Object> ()
+  ;
+  return tid;
+}
+
+TypeId
+TcpOption::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+Ptr<TcpOption>
+TcpOption::CreateOption (uint8_t kind)
+{
+  if (kind == 0)
+    {
+      return CreateObject<TcpOptionEnd> ();
+    }
+  else if (kind == 1)
+    {
+      return CreateObject<TcpOptionNOP> ();
+    }
+  else if (kind == 2)
+    {
+      return CreateObject<TcpOptionMSS> ();
+    }
+  else if (kind == 3)
+    {
+      return CreateObject<TcpOptionWinScale> ();
+    }
+  else if (kind == 4)
+    {
+      return CreateObject<TcpOptionSackPermitted> ();
+    }
+  else if (kind == 5)
+    {
+      return CreateObject<TcpOptionSack> ();
+    }
+  else if (kind == 8)
+    {
+      return CreateObject<TcpOptionTS> ();
+    }
+  return NULL;
+} 
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/tcp-option.h	Wed Dec 07 15:43:04 2011 -0500
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Adrian Sai-wah Tam
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Adrian Sai-wah Tam <adrian.sw.tam@gmail.com>
+ */
+
+#ifndef TCP_OPTION_H
+#define TCP_OPTION_H
+
+#include <stdint.h>
+#include "ns3/object.h"
+#include "ns3/buffer.h"
+
+namespace ns3 {
+
+/**
+ * Base class for all kinds of TCP options
+ */
+
+class TcpOption : public Object
+{
+public:
+  TcpOption ();
+  virtual ~TcpOption ();
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual void Print (std::ostream &os) const = 0;
+  virtual void Serialize (Buffer::Iterator start) const = 0;
+  virtual uint32_t Deserialize (Buffer::Iterator start) = 0;
+
+  virtual uint8_t GetKind (void) const = 0; // Get the `kind' (as in RFC793) of this option
+  virtual uint32_t GetSerializedSize (void) const = 0; // Get the total length of this option, >= 1
+
+  static Ptr<TcpOption> CreateOption (uint8_t kind); // Factory method for all options
+protected:
+};
+
+} // namespace ns3
+
+#endif /* TCP_OPTION */
--- a/src/internet/model/tcp-socket-base.cc	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/internet/model/tcp-socket-base.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -677,7 +677,8 @@
   m_rWnd = tcpHeader.GetWindowSize ();
 
   // Discard fully out of range packets
-  if (OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
+  if (packet->GetSize () &&
+      OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
     {
       NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
                     " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
@@ -706,6 +707,8 @@
       // Do nothing
       break;
     case CLOSED:
+      // Special treatment to prevent BTTO: ignore FIN packets on CLOSED state
+      if (tcpHeader.GetFlags () & TcpHeader::FIN) return;
       // Send RST if the incoming packet is not a RST
       if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
         { // Since m_endPoint is not configured yet, we cannot use SendRST here
@@ -807,7 +810,13 @@
       if (tcpHeader.GetAckNumber () < m_nextTxSequence)
         {
           NS_LOG_LOGIC ("Dupack of " << tcpHeader.GetAckNumber ());
+          TcpStates_t oldState = m_state;
           DupAck (tcpHeader, ++m_dupAckCount);
+          // Special treatment to prevent BTTO: Resend FIN packet until ACK is received
+          if ((m_state == FIN_WAIT_1 || m_state == LAST_ACK) && m_state == oldState)
+            {
+               SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+            }
         }
       // otherwise, the ACK is precisely equal to the nextTxSequence
       NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence);
@@ -815,8 +824,15 @@
   else if (tcpHeader.GetAckNumber () > m_txBuffer.HeadSequence ())
     { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer
       NS_LOG_LOGIC ("New ack of " << tcpHeader.GetAckNumber ());
+      TcpStates_t oldState = m_state;
       NewAck (tcpHeader.GetAckNumber ());
       m_dupAckCount = 0;
+      // Special treatment to prevent BTTO: Resend FIN packet until ACK is received
+      if ((m_state == FIN_WAIT_1 || m_state == LAST_ACK) && m_state == oldState &&
+          tcpHeader.GetAckNumber () != m_highTxMark + SequenceNumber32 (1))
+        {
+          SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+        }
     }
   // If there is any data piggybacked, store it into m_rxBuffer
   if (packet->GetSize () > 0)
@@ -1132,6 +1148,8 @@
   // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose
   if (!m_rxBuffer.Finished ())
     {
+      // Special treatment to prevent BTTO: Send ACK when FIN is out of sequence
+      SendEmptyPacket (TcpHeader::ACK);
       return;
     };
 
--- a/src/internet/wscript	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/internet/wscript	Wed Dec 07 15:43:04 2011 -0500
@@ -97,6 +97,14 @@
         'model/ipv4-l4-protocol.cc',
         'model/udp-header.cc',
         'model/tcp-header.cc',
+        'model/tcp-option.cc',
+        'model/tcp-option-end.cc',
+        'model/tcp-option-nop.cc',
+        'model/tcp-option-mss.cc',
+        'model/tcp-option-winscale.cc',
+        'model/tcp-option-sack-permitted.cc',
+        'model/tcp-option-sack.cc',
+        'model/tcp-option-ts.cc',
         'model/ipv4-interface.cc',
         'model/ipv4-l3-protocol.cc',
         'model/ipv4-end-point.cc',
@@ -140,6 +148,7 @@
         'model/tcp-newreno.cc',
         'model/tcp-rx-buffer.cc',
         'model/tcp-tx-buffer.cc',
+        'model/tcp-admctrl.cc',
         'model/ipv4-packet-info-tag.cc',
         'model/ipv6-packet-info-tag.cc',
         'model/ipv4-interface-address.cc',
@@ -213,6 +222,7 @@
     headers.source = [
         'model/udp-header.h',
         'model/tcp-header.h',
+        'model/tcp-option.h',
         'model/icmpv4.h',
         'model/icmpv6-header.h',
         # used by routing
@@ -245,6 +255,15 @@
         'model/udp-socket-factory.h',
         'model/tcp-socket.h',
         'model/tcp-socket-factory.h',
+        'model/tcp-socket-base.h',
+        'model/tcp-rfc793.h',
+        'model/tcp-tahoe.h',
+        'model/tcp-reno.h',
+        'model/tcp-newreno.h',
+        'model/tcp-rx-buffer.h',
+        'model/tcp-tx-buffer.h',
+        'model/tcp-admctrl.h',
+        'model/rtt-estimator.h',
         'model/ipv4.h',
         'model/ipv4-raw-socket-factory.h',
         'model/ipv4-raw-socket-impl.h',
--- a/src/network/utils/drop-tail-queue.h	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/network/utils/drop-tail-queue.h	Wed Dec 07 15:43:04 2011 -0500
@@ -70,6 +70,7 @@
   DropTailQueue::Mode  GetMode (void);
 
 private:
+  friend class PointToPointNetDevice;
   virtual bool DoEnqueue (Ptr<Packet> p);
   virtual Ptr<Packet> DoDequeue (void);
   virtual Ptr<const Packet> DoPeek (void) const;
--- a/src/point-to-point/model/point-to-point-net-device.cc	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/point-to-point/model/point-to-point-net-device.cc	Wed Dec 07 15:43:04 2011 -0500
@@ -29,6 +29,9 @@
 #include "point-to-point-net-device.h"
 #include "point-to-point-channel.h"
 #include "ppp-header.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/tcp-header.h"
 
 NS_LOG_COMPONENT_DEFINE ("PointToPointNetDevice");
 
@@ -67,6 +70,11 @@
                    TimeValue (Seconds (0.0)),
                    MakeTimeAccessor (&PointToPointNetDevice::m_tInterframeGap),
                    MakeTimeChecker ())
+    .AddAttribute ("UnitSize",
+                   "Size of unit jump of virtual bytes when SYN packet is seen",
+                   UintegerValue (3000),
+                   MakeUintegerAccessor (&PointToPointNetDevice::m_unitSize),
+                   MakeUintegerChecker<uint32_t> ())
 
     //
     // Transmit queueing discipline for the device which includes its own set
@@ -146,6 +154,8 @@
 
 PointToPointNetDevice::PointToPointNetDevice () 
   :
+    m_virtBytes (0),
+    m_unitSize (3000),
     m_txMachineState (READY),
     m_channel (0),
     m_linkUp (false),
@@ -215,6 +225,12 @@
   // schedule an event that will be executed when the transmission is complete.
   //
   NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit");
+  double nBytes = (Now() - m_idleBeginTime) * m_bps / 8;
+  if (nBytes >= m_virtBytes) {
+          m_virtBytes = 0;
+  } else {
+          m_virtBytes -= unsigned(nBytes);
+  };
   m_txMachineState = BUSY;
   m_currentPkt = p;
   m_phyTxBeginTrace (m_currentPkt);
@@ -246,6 +262,7 @@
   //
   NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
   m_txMachineState = READY;
+  m_idleBeginTime = Now();
 
   NS_ASSERT_MSG (m_currentPkt != 0, "PointToPointNetDevice::TransmitComplete(): m_currentPkt zero");
 
@@ -460,6 +477,12 @@
 }
 
 bool
+PointToPointNetDevice::QFull (void) const
+{
+  return m_virtBytes + m_queue->GetNBytes() >= (m_queue->GetObject<DropTailQueue>()->m_maxBytes)*0.85;
+}
+
+bool
 PointToPointNetDevice::Send (
   Ptr<Packet> packet, 
   const Address &dest, 
@@ -480,6 +503,31 @@
     }
 
   //
+  // Checking for (1) if SYN packet, raise the virtual byte count, (2) if
+  // queue's virtual size is full, set ECN marks
+  //
+  if (m_unitSize)
+    {
+      Ipv4Header h;
+      packet->PeekHeader(h);
+      if (h.GetProtocol() == 6) {
+              Ptr<Packet> q = packet->Copy();
+              q->RemoveHeader(h);
+              TcpHeader tcph;
+              q->RemoveHeader(tcph);
+              if (tcph.GetFlags() & TcpHeader::SYN) {
+                      m_virtBytes += m_unitSize;
+              };
+      }
+      if (QFull())
+        {
+          packet->RemoveHeader(h);
+          h.SetEcn(Ipv4Header::CE);
+          packet->AddHeader(h);
+        }
+    }
+
+  //
   // Stick a point to point protocol header on the packet in preparation for
   // shoving it out the door.
   //
--- a/src/point-to-point/model/point-to-point-net-device.h	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/point-to-point/model/point-to-point-net-device.h	Wed Dec 07 15:43:04 2011 -0500
@@ -188,6 +188,11 @@
 protected:
   void DoMpiReceive (Ptr<Packet> p);
 
+  bool QFull (void) const;
+  uint32_t m_virtBytes;
+  uint32_t m_unitSize;
+  Time m_idleBeginTime;
+
 private:
 
   PointToPointNetDevice& operator = (const PointToPointNetDevice &);
--- a/src/point-to-point/wscript	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/point-to-point/wscript	Wed Dec 07 15:43:04 2011 -0500
@@ -2,7 +2,7 @@
 
 
 def build(bld):
-    module = bld.create_ns3_module('point-to-point', ['network', 'mpi'])
+    module = bld.create_ns3_module('point-to-point', ['network', 'mpi', 'internet'])
     module.source = [
         'model/point-to-point-net-device.cc',
         'model/point-to-point-channel.cc',
--- a/src/wscript	Wed Dec 07 11:22:10 2011 -0500
+++ b/src/wscript	Wed Dec 07 15:43:04 2011 -0500
@@ -464,7 +464,7 @@
             up = m.update
             up(self.__class__.__name__.encode())
             for x in self.inputs + self.outputs:
-                up(x.abspath().encode())
+                up(x.abspath())
             up(self.mode)
             if self.mode == 'remove':
                 up(self.header_to_remove.abspath().encode())