--- /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())