--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-large-transfer-errors.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,240 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+// 10Mb/s, 10ms 10Mb/s, 10ms
+// n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file
+// "tcp-large-transfer-errors.tr"
+// - pcap traces also generated in the following files
+// "tcp-large-transfer-errors.pcap-$n-$i" where n and i represent node and interface numbers respectively
+// Usage (e.g.): ./waf --run tcp-large-transfer-errors
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpLargeTransferErrors");
+
+void
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+ const Address &addr)
+{
+ if (!g_log.IsNoneEnabled ()) {
+ if (InetSocketAddress::IsMatchingType (addr) )
+ {
+ InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+ std::cout << "PacketSink received size " <<
+ packet->GetSize () << " at time " <<
+ Simulator::Now ().GetSeconds () << " from address: " <<
+ address.GetIpv4 () << std::endl;
+ char buf[2000];
+ memcpy(buf, packet->PeekData (), packet->GetSize ());
+ for (uint32_t i=0; i < packet->GetSize (); i++)
+ {
+ std::cout << buf[i];
+ if (i && i % 60 == 0)
+ std::cout << std::endl;
+ }
+ std::cout << std::endl << std::endl;
+ }
+ }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+ //localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
+ uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+ localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+ Callback<void, Ptr<Socket> > (),
+ Callback<void, Ptr<Socket> > ());
+ //we want to close as soon as the connection is established
+ //the tcp state machine and outgoing buffer will assure that
+ //all of the data is delivered
+
+ // Perform series of 1040 byte writes (this is a multiple of 26 since
+ // we want to detect data splicing in the output stream)
+ uint32_t writeSize = 1040;
+ uint8_t data[writeSize];
+ while (nBytes > 0) {
+ uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
+ for(uint32_t i = 0; i < curSize; ++i)
+ {
+ char m = toascii (97 + i % 26);
+ data[i] = m;
+ }
+ localSocket->Send (data, curSize);
+ nBytes -= curSize;
+ }
+}
+
+int main (int argc, char *argv[])
+{
+
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+ //LogComponentEnable("TcpLargeTransferErrors", LOG_LEVEL_ALL);
+
+ // Allow the user to override any of the defaults and the above
+ // Bind()s at run-time, via command-line arguments
+ CommandLine::Parse (argc, argv);
+
+ // Here, we will explicitly create three nodes. In more sophisticated
+ // topologies, we could configure a node factory.
+ Ptr<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<PointToPointChannel> channel0 =
+ PointToPointTopology::AddPointToPointLink (
+ n0, n1, DataRate(10000000), MilliSeconds(10));
+
+ // Later, we add IP addresses.
+ PointToPointTopology::AddIpv4Addresses (
+ channel0, n0, Ipv4Address("10.1.3.1"),
+ n1, Ipv4Address("10.1.3.2"));
+
+ Ptr<PointToPointChannel> channel1 =
+ PointToPointTopology::AddPointToPointLink (
+ n1, n2, DataRate(10000000), MilliSeconds(10));
+
+ PointToPointTopology::AddIpv4Addresses (
+ channel1, n1, Ipv4Address("10.1.2.1"),
+ n2, Ipv4Address("10.1.2.2"));
+
+ // Finally, we add static routes. These three steps (Channel and
+ // NetDevice creation, IP Address assignment, and routing) are
+ // separated because there may be a need to postpone IP Address
+ // assignment (emulation) or modify to use dynamic routing
+ PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+ PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+ Ptr<Ipv4> ipv4;
+ ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+ ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Simulation 1
+ //
+ // Send 2000000 bytes over a connection to server port 50000 at time 0
+ // Should observe SYN exchange, a lot of data segments, and FIN exchange
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ int nBytes = 2000000;
+ uint16_t servPort = 50000;
+
+ Ptr<SocketFactory> socketFactory =
+ n0->QueryInterface<SocketFactory> (Tcp::iid);
+ Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+ localSocket->Bind ();
+
+ // Create a packet sink to receive these packets
+ Ptr<PacketSink> sink = Create<PacketSink> (
+ n2,
+ InetSocketAddress (Ipv4Address::GetAny (), servPort),
+ "Tcp");
+ sink->Start (Seconds (0.0));
+ sink->Stop (Seconds (10000.0));
+
+ //
+ // Error models
+ //
+ // We want to add an error model to node 2's NetDevice
+ // We can obtain a handle to the NetDevice via the channel and node
+ // pointers
+ Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
+ (n2, channel1);
+ Ptr<RateErrorModel> rem = Create<RateErrorModel> ();
+ // The first data segment for this flow is packet uid=4
+ rem->SetRandomVariable (UniformVariable ());
+ rem->SetUnit (EU_PKT);
+ rem->SetRate (0.05);
+ nd2->AddReceiveErrorModel (rem);
+
+ Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+ servPort);
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the simple-examples.tr file
+ AsciiTrace asciitrace ("tcp-large-transfer-errors.tr");
+ asciitrace.TraceAllQueues ();
+ asciitrace.TraceAllNetDeviceRx ();
+
+
+ // Also configure some tcpdump traces; each interface will be traced
+ // The output files will be named
+ // simple-examples.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("tcp-large-transfer-errors.pcap");
+ pcaptrace.TraceAllIp ();
+
+ NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+ Simulator::StopAt (Seconds(10000));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-large-transfer.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,225 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+// 10Mb/s, 10ms 10Mb/s, 10ms
+// n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file
+// "tcp-large-transfer.tr"
+// - pcap traces also generated in the following files
+// "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
+// Usage (e.g.): ./waf --run tcp-large-transfer
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
+
+void
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+ const Address &addr)
+{
+ if (!g_log.IsNoneEnabled ()) {
+ if (InetSocketAddress::IsMatchingType (addr) )
+ {
+ InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+ std::cout << "PacketSink received size " <<
+ packet->GetSize () << " at time " <<
+ Simulator::Now ().GetSeconds () << " from address: " <<
+ address.GetIpv4 () << std::endl;
+ char buf[2000];
+ memcpy(buf, packet->PeekData (), packet->GetSize ());
+ for (uint32_t i=0; i < packet->GetSize (); i++)
+ {
+ std::cout << buf[i];
+ if (i && i % 60 == 0)
+ std::cout << std::endl;
+ }
+ std::cout << std::endl << std::endl;
+ }
+ }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+ //localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
+ uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+ localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+ Callback<void, Ptr<Socket> > (),
+ Callback<void, Ptr<Socket> > ());
+ //we want to close as soon as the connection is established
+ //the tcp state machine and outgoing buffer will assure that
+ //all of the data is delivered
+
+ // Perform series of 1040 byte writes (this is a multiple of 26 since
+ // we want to detect data splicing in the output stream)
+ uint32_t writeSize = 1040;
+ uint8_t data[writeSize];
+ while (nBytes > 0) {
+ uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
+ for(uint32_t i = 0; i < curSize; ++i)
+ {
+ char m = toascii (97 + i % 26);
+ data[i] = m;
+ }
+ localSocket->Send (data, curSize);
+ nBytes -= curSize;
+ }
+}
+
+int main (int argc, char *argv[])
+{
+
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+ //LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
+
+ // Allow the user to override any of the defaults and the above
+ // Bind()s at run-time, via command-line arguments
+ CommandLine::Parse (argc, argv);
+
+ // Here, we will explicitly create three nodes. In more sophisticated
+ // topologies, we could configure a node factory.
+ Ptr<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<PointToPointChannel> channel0 =
+ PointToPointTopology::AddPointToPointLink (
+ n0, n1, DataRate(10000000), MilliSeconds(10));
+
+ // Later, we add IP addresses.
+ PointToPointTopology::AddIpv4Addresses (
+ channel0, n0, Ipv4Address("10.1.3.1"),
+ n1, Ipv4Address("10.1.3.2"));
+
+ Ptr<PointToPointChannel> channel1 =
+ PointToPointTopology::AddPointToPointLink (
+ n1, n2, DataRate(10000000), MilliSeconds(10));
+
+ PointToPointTopology::AddIpv4Addresses (
+ channel1, n1, Ipv4Address("10.1.2.1"),
+ n2, Ipv4Address("10.1.2.2"));
+
+ // Finally, we add static routes. These three steps (Channel and
+ // NetDevice creation, IP Address assignment, and routing) are
+ // separated because there may be a need to postpone IP Address
+ // assignment (emulation) or modify to use dynamic routing
+ PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+ PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+ Ptr<Ipv4> ipv4;
+ ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+ ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Simulation 1
+ //
+ // Send 2000000 bytes over a connection to server port 50000 at time 0
+ // Should observe SYN exchange, a lot of data segments, and FIN exchange
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ int nBytes = 2000000;
+ uint16_t servPort = 50000;
+
+ Ptr<SocketFactory> socketFactory =
+ n0->QueryInterface<SocketFactory> (Tcp::iid);
+ Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+ localSocket->Bind ();
+
+ // Create a packet sink to receive these packets
+ Ptr<PacketSink> sink = Create<PacketSink> (
+ n2,
+ InetSocketAddress (Ipv4Address::GetAny (), servPort),
+ "Tcp");
+ sink->Start (Seconds (0.0));
+ sink->Stop (Seconds (100.0));
+
+ Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+ servPort);
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the simple-examples.tr file
+ AsciiTrace asciitrace ("tcp-large-transfer.tr");
+ asciitrace.TraceAllQueues ();
+ asciitrace.TraceAllNetDeviceRx ();
+
+
+ // Also configure some tcpdump traces; each interface will be traced
+ // The output files will be named
+ // simple-examples.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("tcp-large-transfer.pcap");
+ pcaptrace.TraceAllIp ();
+
+ NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+ Simulator::StopAt (Seconds(1000));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-nonlistening-server.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+// 100Kb/s, 10ms 1Mb/s, 10ms
+// n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file
+// "tcp-nonlistening-server.tr"
+// - pcap traces also generated in the following files
+// "tcp-nonlistening-server.pcap-$n-$i" where n and i represent node and interface numbers respectively
+// Usage (e.g.): ./waf --run tcp-nonlistening-server
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpNonListeningServer");
+
+void ConnectionSucceededCallback (Ptr<Socket> localSocket)
+{
+ uint32_t nBytes = 2000;
+ uint8_t data[nBytes];
+ for(uint32_t i = 0; i < nBytes; ++i)
+ {
+ char m = 'A';
+ data[i] = m;
+ } //put something interesting in the packets ABCDEF...
+ localSocket->Send (data, nBytes);
+}
+
+void ConnectionFailedCallback (Ptr<Socket> localSocket)
+{
+ NS_LOG_ERROR("Connection failed at time " << Simulator::Now ().GetSeconds ());
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint16_t servPort)
+{
+ NS_LOG_LOGIC(std::endl << "Connection attempt at time " <<
+ Simulator::Now ().GetSeconds () << std::endl);
+ localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
+ localSocket->SetConnectCallback (
+ MakeCallback (&ConnectionSucceededCallback),
+ MakeCallback (&ConnectionFailedCallback),
+ MakeNullCallback<void, Ptr<Socket> > () );
+}
+
+int main (int argc, char *argv[])
+{
+
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+ //LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+ //LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+ LogComponentEnable("TcpNonListeningServer", LOG_LEVEL_ALL);
+
+ // Allow the user to override any of the defaults and the above
+ // Bind()s at run-time, via command-line arguments
+ CommandLine::Parse (argc, argv);
+
+ // Here, we will explicitly create three nodes. In more sophisticated
+ // topologies, we could configure a node factory.
+ Ptr<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<PointToPointChannel> channel0 =
+ PointToPointTopology::AddPointToPointLink (
+ n0, n1, DataRate(1000000), MilliSeconds(10));
+
+ // Later, we add IP addresses.
+ PointToPointTopology::AddIpv4Addresses (
+ channel0, n0, Ipv4Address("10.1.3.1"),
+ n1, Ipv4Address("10.1.3.2"));
+
+ Ptr<PointToPointChannel> channel1 =
+ PointToPointTopology::AddPointToPointLink (
+ n1, n2, DataRate(100000), MilliSeconds(10));
+
+ PointToPointTopology::AddIpv4Addresses (
+ channel1, n1, Ipv4Address("10.1.2.1"),
+ n2, Ipv4Address("10.1.2.2"));
+
+ // Finally, we add static routes. These three steps (Channel and
+ // NetDevice creation, IP Address assignment, and routing) are
+ // separated because there may be a need to postpone IP Address
+ // assignment (emulation) or modify to use dynamic routing
+ PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+ PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+ Ptr<Ipv4> ipv4;
+ ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+ ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Simulation 1
+ //
+ // Send 2000 bytes over a connection to server port 500 at time 0
+ // Should observe SYN exchange, two data segments, and FIN exchange
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ uint16_t servPort = 500;
+
+ Ptr<SocketFactory> socketFactory =
+ n0->QueryInterface<SocketFactory> (Tcp::iid);
+ Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+ localSocket->Bind ();
+
+#ifdef NOTFORTHISSCRIPT
+ // Create an optional packet sink to receive these packets
+ Ptr<PacketSink> sink = Create<PacketSink> (
+ n2,
+ InetSocketAddress (Ipv4Address::GetAny (), servPort),
+ "Tcp");
+ // Start the sink
+ sink->Start (Seconds (0.0));
+ sink->Stop (Seconds (10.0));
+#endif
+
+ Simulator::Schedule(Seconds(0), &StartFlow, localSocket, servPort);
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the simple-examples.tr file
+ AsciiTrace asciitrace ("tcp-nonlistening-server.tr");
+ asciitrace.TraceAllQueues ();
+ asciitrace.TraceAllNetDeviceRx ();
+
+ // Also configure some tcpdump traces; each interface will be traced
+ // The output files will be named
+ // simple-examples.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("tcp-nonlistening-server.pcap");
+ pcaptrace.TraceAllIp ();
+
+
+ Simulator::StopAt (Seconds(1000));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-small-transfer-oneloss.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,222 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+// 100Kb/s, 10ms 1Mb/s, 10ms
+// n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file
+// "tcp-small-transfer-oneloss.tr"
+// - pcap traces also generated in the following files
+// "tcp-small-transfer-oneloss.pcap-$n-$i" where n and i represent node and interface numbers respectively
+// Usage (e.g.): ./waf --run tcp-small-transfer-oneloss
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpSmallTransferOneloss");
+
+void
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+ const Address &addr)
+{
+ if (!g_log.IsNoneEnabled ()) {
+ if (InetSocketAddress::IsMatchingType (addr) )
+ {
+ InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+ std::cout << "PacketSink received size " <<
+ packet->GetSize () << " at time " <<
+ Simulator::Now ().GetSeconds () << " from address: " <<
+ address.GetIpv4 () << std::endl;
+ char buf[2000];
+ memcpy(buf, packet->PeekData (), packet->GetSize ());
+ for (uint32_t i=0; i < packet->GetSize (); i++)
+ {
+ std::cout << buf[i];
+ if (i && i % 60 == 0)
+ std::cout << std::endl;
+ }
+ std::cout << std::endl << std::endl;
+ }
+ }
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
+ uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));
+ uint8_t data[nBytes];
+ for(uint32_t i = 0; i < nBytes; ++i)
+ {
+ char m = toascii (97 + i % 26);
+ data[i] = m;
+ }
+ localSocket->Send (data, nBytes);
+}
+
+int main (int argc, char *argv[])
+{
+
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+// LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+ LogComponentEnable("TcpSmallTransferOneloss", LOG_LEVEL_ALL);
+
+ // Allow the user to override any of the defaults and the above
+ // Bind()s at run-time, via command-line arguments
+ CommandLine::Parse (argc, argv);
+
+ // Here, we will explicitly create three nodes. In more sophisticated
+ // topologies, we could configure a node factory.
+ Ptr<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<PointToPointChannel> channel0 =
+ PointToPointTopology::AddPointToPointLink (
+ n0, n1, DataRate(1000000), MilliSeconds(10));
+
+ // Later, we add IP addresses.
+ PointToPointTopology::AddIpv4Addresses (
+ channel0, n0, Ipv4Address("10.1.3.1"),
+ n1, Ipv4Address("10.1.3.2"));
+
+ Ptr<PointToPointChannel> channel1 =
+ PointToPointTopology::AddPointToPointLink (
+ n1, n2, DataRate(100000), MilliSeconds(10));
+
+ PointToPointTopology::AddIpv4Addresses (
+ channel1, n1, Ipv4Address("10.1.2.1"),
+ n2, Ipv4Address("10.1.2.2"));
+
+ // Finally, we add static routes. These three steps (Channel and
+ // NetDevice creation, IP Address assignment, and routing) are
+ // separated because there may be a need to postpone IP Address
+ // assignment (emulation) or modify to use dynamic routing
+ PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+ PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+ Ptr<Ipv4> ipv4;
+ ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+ ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Simulation 1
+ //
+ // Send 2000 bytes over a connection to server port 500 at time 0
+ // Should observe SYN exchange, two data segments, and FIN exchange
+ // Force the loss of the first data segment
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ int nBytes = 2000;
+ uint16_t servPort = 500;
+
+ Ptr<SocketFactory> socketFactory =
+ n0->QueryInterface<SocketFactory> (Tcp::iid);
+ Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+ localSocket->Bind ();
+
+ // Create a packet sink to receive these packets
+ Ptr<PacketSink> sink = Create<PacketSink> (
+ n2,
+ InetSocketAddress (Ipv4Address::GetAny (), servPort),
+ "Tcp");
+ sink->Start (Seconds (0.0));
+ sink->Stop (Seconds (100.0));
+
+ //
+ // Error models
+ //
+ // We want to add an error model to node 2's NetDevice
+ // We can obtain a handle to the NetDevice via the channel and node
+ // pointers
+ Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
+ (n2, channel1);
+ Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
+ std::list<uint32_t> sampleList;
+ // The first data segment for this flow is packet uid=4
+ sampleList.push_back (4);
+ pem->SetList (sampleList);
+ nd2->AddReceiveErrorModel (pem);
+
+ Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+ servPort);
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the simple-examples.tr file
+ AsciiTrace asciitrace ("tcp-small-transfer-oneloss.tr");
+ asciitrace.TraceAllQueues ();
+ asciitrace.TraceAllNetDeviceRx ();
+
+
+ // Also configure some tcpdump traces; each interface will be traced
+ // The output files will be named
+ // simple-examples.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("tcp-small-transfer-oneloss.pcap");
+ pcaptrace.TraceAllIp ();
+
+ NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+ Simulator::StopAt (Seconds(1000));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-small-transfer.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,217 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+// 100Kb/s, 10ms 1Mb/s, 10ms
+// n0-----------------n1-----------------n2
+//
+//
+// - Tracing of queues and packet receptions to file
+// "tcp-small-transfer.tr"
+// - pcap traces also generated in the following files
+// "tcp-small-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
+// Usage (e.g.): ./waf --run tcp-small-transfer
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/log.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/error-model.h"
+#include "ns3/node-list.h"
+
+#include "ns3/tcp.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpSmallTransfer");
+
+void
+ApplicationTraceSink (const TraceContext &context, Ptr<const Packet> packet,
+ const Address &addr)
+{
+ if (!g_log.IsNoneEnabled ()) {
+ if (InetSocketAddress::IsMatchingType (addr) )
+ {
+ InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
+ std::cout << "PacketSink received size " <<
+ packet->GetSize () << " at time " <<
+ Simulator::Now ().GetSeconds () << " from address: " <<
+ address.GetIpv4 () << std::endl;
+ char buf[2000];
+ memcpy(buf, packet->PeekData (), packet->GetSize ());
+ for (uint32_t i=0; i < packet->GetSize (); i++)
+ {
+ std::cout << buf[i];
+ if (i && i % 60 == 0)
+ std::cout << std::endl;
+ }
+ std::cout << std::endl << std::endl;
+ }
+ }
+}
+
+void CloseConnection (Ptr<Socket> localSocket)
+{
+ localSocket->Close ();
+}
+
+void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes,
+ uint16_t servPort)
+{
+ // NS_LOG_LOGIC("Starting flow at time " << Simulator::Now ().GetSeconds ());
+ localSocket->Connect (InetSocketAddress ("10.1.2.2", servPort));//connect
+ localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
+ MakeNullCallback<void, Ptr<Socket> > (),
+ MakeNullCallback<void, Ptr<Socket> > ());
+ //we want to close as soon as the connection is established
+ //the tcp state machine and outgoing buffer will assure that
+ //all of the data is delivered
+ uint8_t data[nBytes];
+ for(uint32_t i = 0; i < nBytes; ++i)
+ {
+ char m = toascii (97 + i % 26);
+ data[i] = m;
+ }
+ localSocket->Send (data, nBytes);
+}
+
+int main (int argc, char *argv[])
+{
+
+ // Users may find it convenient to turn on explicit debugging
+ // for selected modules; the below lines suggest how to do this
+// LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
+ // LogComponentEnable("TcpSocket", LOG_LEVEL_ALL);
+// LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
+ LogComponentEnable("TcpSmallTransfer", LOG_LEVEL_ALL);
+
+ // Allow the user to override any of the defaults and the above
+ // Bind()s at run-time, via command-line arguments
+ CommandLine::Parse (argc, argv);
+
+ // Here, we will explicitly create three nodes. In more sophisticated
+ // topologies, we could configure a node factory.
+ Ptr<Node> n0 = Create<InternetNode> ();
+ Ptr<Node> n1 = Create<InternetNode> ();
+ Ptr<Node> n2 = Create<InternetNode> ();
+
+ // We create the channels first without any IP addressing information
+ Ptr<PointToPointChannel> channel0 =
+ PointToPointTopology::AddPointToPointLink (
+ n0, n1, DataRate(1000000), MilliSeconds(10));
+
+ // Later, we add IP addresses.
+ PointToPointTopology::AddIpv4Addresses (
+ channel0, n0, Ipv4Address("10.1.3.1"),
+ n1, Ipv4Address("10.1.3.2"));
+
+ Ptr<PointToPointChannel> channel1 =
+ PointToPointTopology::AddPointToPointLink (
+ n1, n2, DataRate(100000), MilliSeconds(10));
+
+ PointToPointTopology::AddIpv4Addresses (
+ channel1, n1, Ipv4Address("10.1.2.1"),
+ n2, Ipv4Address("10.1.2.2"));
+
+ // Finally, we add static routes. These three steps (Channel and
+ // NetDevice creation, IP Address assignment, and routing) are
+ // separated because there may be a need to postpone IP Address
+ // assignment (emulation) or modify to use dynamic routing
+ PointToPointTopology::AddIpv4Routes(n0, n1, channel0);
+ PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+ Ptr<Ipv4> ipv4;
+ ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.2"), 1);
+ ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+ ipv4->SetDefaultRoute (Ipv4Address ("10.1.2.1"), 1);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Simulation 1
+ //
+ // Send 2000 bytes over a connection to server port 500 at time 0
+ // Should observe SYN exchange, two data segments, and FIN exchange
+ //
+ ///////////////////////////////////////////////////////////////////////////
+
+ int nBytes = 2000;
+ uint16_t servPort = 500;
+
+ Ptr<SocketFactory> socketFactory =
+ n0->QueryInterface<SocketFactory> (Tcp::iid);
+ Ptr<Socket> localSocket = socketFactory->CreateSocket ();
+ localSocket->Bind ();
+
+ // Create a packet sink to receive these packets
+ Ptr<PacketSink> sink = Create<PacketSink> (
+ n2,
+ InetSocketAddress (Ipv4Address::GetAny (), servPort),
+ "Tcp");
+ sink->Start (Seconds (0.0));
+ sink->Stop (Seconds (100.0));
+
+ Simulator::Schedule(Seconds(0), &StartFlow, localSocket, nBytes,
+ servPort);
+
+ // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+ // Trace output will be sent to the simple-examples.tr file
+ AsciiTrace asciitrace ("tcp-small-transfer.tr");
+ asciitrace.TraceAllQueues ();
+ asciitrace.TraceAllNetDeviceRx ();
+
+
+ // Also configure some tcpdump traces; each interface will be traced
+ // The output files will be named
+ // simple-examples.pcap-<nodeId>-<interfaceId>
+ // and can be read by the "tcpdump -r" command (use "-tt" option to
+ // display timestamps correctly)
+ PcapTrace pcaptrace ("tcp-small-transfer.pcap");
+ pcaptrace.TraceAllIp ();
+
+ NodeList::Connect ("/nodes/*/applications/*/rx", MakeCallback (&ApplicationTraceSink));
+
+ Simulator::StopAt (Seconds(1000));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
--- a/examples/wscript Sat Jan 19 21:03:18 2008 -0800
+++ b/examples/wscript Fri Jan 25 13:57:38 2008 -0500
@@ -45,3 +45,25 @@
obj = bld.create_ns3_program('simple-point-to-point-olsr',
['point-to-point', 'internet-node', 'olsr'])
obj.source = 'simple-point-to-point-olsr.cc'
+
+ obj = bld.create_ns3_program('tcp-large-transfer',
+ ['point-to-point', 'internet-node'])
+ obj.source = 'tcp-large-transfer.cc'
+
+ obj = bld.create_ns3_program('tcp-large-transfer-errors',
+ ['point-to-point', 'internet-node'])
+ obj.source = 'tcp-large-transfer-errors.cc'
+
+ obj = bld.create_ns3_program('tcp-nonlistening-server',
+ ['point-to-point', 'internet-node'])
+ obj.source = 'tcp-nonlistening-server.cc'
+
+ obj = bld.create_ns3_program('tcp-small-transfer',
+ ['point-to-point', 'internet-node'])
+ obj.source = 'tcp-small-transfer.cc'
+
+ obj = bld.create_ns3_program('tcp-small-transfer-oneloss',
+ ['point-to-point', 'internet-node'])
+ obj.source = 'tcp-small-transfer-oneloss.cc'
+
+
--- a/src/applications/packet-sink/packet-sink.cc Sat Jan 19 21:03:18 2008 -0800
+++ b/src/applications/packet-sink/packet-sink.cc Fri Jan 25 13:57:38 2008 -0500
@@ -78,9 +78,14 @@
GetNode ()->QueryInterface<SocketFactory> (iid);
m_socket = socketFactory->CreateSocket ();
m_socket->Bind (m_local);
+ m_socket->Listen (0);
}
m_socket->SetRecvCallback (MakeCallback(&PacketSink::Receive, this));
+ m_socket->SetAcceptCallback (
+ MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
+ MakeNullCallback<void, Ptr<Socket>, const Address&> (),
+ MakeCallback(&PacketSink::CloseConnection, this) );
}
void PacketSink::StopApplication() // Called at time specified by Stop
@@ -106,6 +111,11 @@
m_rxTrace (packet, from);
}
+void PacketSink::CloseConnection (Ptr<Socket> socket)
+{
+ socket->Close ();
+}
+
Ptr<TraceResolver>
PacketSink::GetTraceResolver (void) const
{
--- a/src/applications/packet-sink/packet-sink.h Sat Jan 19 21:03:18 2008 -0800
+++ b/src/applications/packet-sink/packet-sink.h Fri Jan 25 13:57:38 2008 -0500
@@ -78,6 +78,7 @@
std::string iid);
virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
+ virtual void CloseConnection (Ptr<Socket> socket);
Ptr<Socket> m_socket; // Associated socket
Address m_local; // Local address to bind to
--- a/src/internet-node/internet-node.cc Sat Jan 19 21:03:18 2008 -0800
+++ b/src/internet-node/internet-node.cc Fri Jan 25 13:57:38 2008 -0500
@@ -28,9 +28,11 @@
#include "ipv4-l4-demux.h"
#include "internet-node.h"
#include "udp-l4-protocol.h"
+#include "tcp-l4-protocol.h"
#include "ipv4-l3-protocol.h"
#include "arp-l3-protocol.h"
#include "udp-impl.h"
+#include "tcp-impl.h"
#include "ipv4-impl.h"
namespace ns3 {
@@ -62,15 +64,20 @@
Ptr<Ipv4L4Demux> ipv4L4Demux = Create<Ipv4L4Demux> (this);
Ptr<UdpL4Protocol> udp = Create<UdpL4Protocol> (this);
+ Ptr<TcpL4Protocol> tcp = Create<TcpL4Protocol> (this);
+
ipv4L4Demux->Insert (udp);
+ ipv4L4Demux->Insert (tcp);
Ptr<UdpImpl> udpImpl = Create<UdpImpl> (udp);
+ Ptr<TcpImpl> tcpImpl = Create<TcpImpl> (tcp);
Ptr<Ipv4Impl> ipv4Impl = Create<Ipv4Impl> (ipv4);
Object::AddInterface (ipv4);
Object::AddInterface (arp);
Object::AddInterface (ipv4Impl);
Object::AddInterface (udpImpl);
+ Object::AddInterface (tcpImpl);
Object::AddInterface (ipv4L4Demux);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/pending-data.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,222 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// This is a port of Data PDU Headers from:
+// Georgia Tech Network Simulator
+// George F. Riley. Georgia Tech, Spring 2002
+
+#include <iostream>
+#include <algorithm>
+
+#include <string.h>
+
+#include "pending-data.h"
+#include "ns3/packet.h"
+#include "ns3/fatal-error.h"
+namespace ns3
+{
+
+namespace Serializable
+{
+ uint8_t* GetSize (uint8_t* b, uint32_t& r, uint32_t& s)
+ { // Get the size of the next size field
+ if (sizeof(s) > r)
+ {
+ NS_FATAL_ERROR ("Serialization error; remaining " << r
+ << " thissize " << sizeof(s) << std::endl);
+ }
+ r -= sizeof (s); // Reduce remaining for next time
+ memcpy (&s, b, sizeof(s));
+ return b + sizeof (s);
+ }
+}
+
+PendingData::PendingData () : size (0), data (0),
+ msgSize (0), responseSize (0)
+{
+}
+
+PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp)
+ : size (s), data (0), msgSize (msg), responseSize (resp)
+{ // Make a copy of the data
+ if (d)
+ {
+ data = new uint8_t[s];
+ memcpy (data, d, s);
+ }
+}
+
+PendingData::PendingData(const std::string& s)
+ : size (s.length () + 1), data ((uint8_t*)strdup(s.c_str ())),
+ msgSize (0), responseSize (0)
+{
+}
+
+PendingData::PendingData(const PendingData& c)
+ : size (c.Size ()), data (0),
+ msgSize (c.msgSize), responseSize (c.responseSize)
+{ // Copy constructor
+ if (c.Contents())
+ { // Has data
+ data = new uint8_t[Size ()];
+ memcpy(data, c.Contents (), Size ());
+ }
+}
+
+PendingData::~PendingData()
+{ // destructor
+ if (data)
+ {
+ delete [] data;
+ }
+}
+
+PendingData* PendingData::Copy () const
+{
+ return new PendingData (*this);
+};
+
+PendingData* PendingData::CopyS (uint32_t s)
+{ // Copy, but with new size (assumes no associated data);
+ return new PendingData (s, 0, msgSize, responseSize);
+}
+
+PendingData* PendingData::CopySD (uint32_t s, uint8_t* d)
+{ // Copy, but with new size (assumes no associated data);
+ return new PendingData (s, d, msgSize, responseSize);
+}
+
+void PendingData::Clear ()
+{ // Remove all pending data
+ if (data)
+ {
+ delete [] data; // Free memory if used
+ }
+ data = 0;
+ size = 0;
+}
+
+void PendingData::Add (uint32_t s, const uint8_t* d)
+{
+ if (data)
+ { // PendingData exists, realloc and copy
+ uint8_t* n = new uint8_t[Size () + s];
+ memcpy(n, data, Size ());
+ if (d)
+ { // New data specified
+ memcpy(n + Size (), d, s); // Append the new data
+ }
+ else
+ {
+ memset(n + Size (), 0, s); // Apend zeros
+ }
+ delete [] data; // Delete the old data
+ data = n; // Points to new one
+ }
+ else
+ { // No existing data, see if new data
+ if (d)
+ {
+ data = new uint8_t[s];
+ memcpy (data, d, s);
+ }
+ }
+ size += s;
+}
+
+void PendingData::Remove(uint32_t s)
+{
+ uint32_t r = s > Size () ? Size () : s;
+
+ size -= r; // Reduce size from current
+ if (data)
+ { // data actually exists, realloc and copy
+ if (size)
+ {
+ uint8_t* d = new uint8_t[Size ()];
+ memcpy(d, data, Size ());
+ delete [] data;
+ data = d;
+ }
+ else
+ { // Zero size, so don't need the data anymore
+ delete [] data;
+ data = NULL;
+ }
+ }
+}
+
+uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{
+ uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data
+ return SizeFromOffset (o1); // Amount of data after offset
+}
+
+uint32_t PendingData::SizeFromOffset (uint32_t o)
+{ // Find out how much data is available from offset
+ if (o > size) return 0; // No data at requested offset
+ return size - o; // Available data after offset
+}
+
+uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o)
+{ // f is the first sequence number in this data, o is offset sequence
+ if (o < f)
+ {
+ return 0; // HuH? Shouldn't happen
+ }
+ return o - f;
+}
+
+PendingData* PendingData::CopyFromOffset (uint32_t s, uint32_t o)
+{ // Make a copy of data from starting position "o" for "s" bytes
+ // Return NULL if results in zero length data
+ uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data
+ if (s1 == 0)
+ {
+ return NULL; // No data requested
+ }
+ if (data)
+ { // Actual data exists, make copy and return it
+ uint8_t* d1 = new uint8_t[s1]; // Allocate memory for the copy
+ memcpy (d1, &data[o], s1); // Copy the data
+ PendingData* d = new PendingData (s1, d1, msgSize, responseSize); // Return copy
+ return d;
+ }
+ else
+ { // No actual data, just return non-data pdu of correct size
+ return new PendingData (s1, 0, msgSize, responseSize);
+ }
+}
+
+PendingData* PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o)
+{
+ PendingData* d = CopyFromOffset (s, OffsetFromSeq(f,o));
+ return d;
+}
+
+}//namepsace ns3
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/pending-data.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Data Descriptors
+// George F. Riley. Georgia Tech, Spring 2002
+
+#ifndef __datapdu_h__
+#define __datapdu_h__
+
+#include "pending-data.h"
+#include "sequence-number.h"
+namespace ns3
+{
+class Packet;
+//Doc:ClassXRef
+class PendingData {
+public:
+ PendingData ();
+ PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0);
+ PendingData (const std::string&); // Construct from string
+ PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer
+ PendingData (const PendingData&); // Copy constructor
+ virtual ~PendingData (); // Destructor
+ uint32_t Size () const { return size;}
+ // Serialization
+ uint32_t SSize (); // Size needed for serialization
+ uint8_t* Serialize (uint8_t*, uint32_t&); // Serialize to a buffer
+ uint8_t* Construct (uint8_t*, uint32_t&); // Construct from buffer
+ virtual void Clear ();// Remove all associated data
+ virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end
+ virtual void Remove (uint32_t); // Remove data from head
+ // Inquire available data from (f,o) sequence pair
+ virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&);
+ // Inquire available data from offset
+ virtual uint32_t SizeFromOffset (uint32_t);
+ // Available size from sequence difference
+ virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&);
+ virtual PendingData* CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret pointer
+ // Copy data, size, offset specified by sequence difference
+ virtual PendingData* CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&);
+ PendingData* Copy () const; // Create a copy of this header
+ PendingData* CopyS (uint32_t); // Copy with new size
+ PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data
+ virtual uint8_t* Contents() const { return data;}
+public:
+ uint32_t size; // Number of data bytes
+ uint8_t* data; // Corresponding data (may be null)
+ // The next two fields allow simulated applications to exchange some info
+ uint32_t msgSize; // Total size of message
+ uint32_t responseSize;// Size of response requested
+};
+
+}//namepsace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/rtt-estimator.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,233 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#include <iostream>
+
+#include "rtt-estimator.h"
+#include "ns3/simulator.h"
+
+namespace ns3{
+
+//RttEstimator iid
+const InterfaceId RttEstimator::iid = MakeInterfaceId ("RttEstimator",
+ Object::iid);
+
+//Default values
+ClassIdDefaultValue RttEstimator::defaultCid ("RttEstimator",
+ "Tahoe round trip time estimation",
+ RttEstimator::iid, "RttMeanDeviation");
+NumericDefaultValue<double> RttEstimator::defaultMaxMultiplier ("RttMaxMultiplier","",64.0);
+
+// RttEstimator Static Member variables
+Time RttEstimator::initialEstimate = Seconds (1.0); // Default initial estimate
+
+//RttHistory methods
+RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t)
+ : seq (s), count (c), time (t), retx (false)
+ {
+ }
+
+RttHistory::RttHistory (const RttHistory& h)
+ : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
+ {
+ }
+
+// Base class methods
+
+RttEstimator::RttEstimator () : next (1), history (), est (initialEstimate),
+ nSamples (0), multiplier (1.0)
+{
+ //note next=1 everywhere since first segment will have sequence 1
+ SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::RttEstimator (Time e) : next (1), history (), est (e),
+ nSamples (0), multiplier (1.0)
+{
+ SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::RttEstimator(const RttEstimator& c)
+ : next(c.next), history(c.history), est(c.est), nSamples(c.nSamples),
+ multiplier(c.multiplier)
+{
+ SetInterfaceId (RttEstimator::iid);
+}
+
+RttEstimator::~RttEstimator ()
+{
+}
+
+void RttEstimator::SentSeq (SequenceNumber s, uint32_t c)
+{ // Note that a particular sequence has been sent
+ if (s == next)
+ { // This is the next expected one, just log at end
+ history.push_back (RttHistory (s, c, Simulator::Now () ));
+ next = s + SequenceNumber (c); // Update next expected
+ }
+ else
+ { // This is a retransmit, find in list and mark as re-tx
+ for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i)
+ {
+ if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count))))
+ { // Found it
+ i->retx = true;
+ // One final test..be sure this re-tx does not extend "next"
+ if ((s + SequenceNumber (c)) > next)
+ {
+ next = s + SequenceNumber (c);
+ i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist
+ }
+ break;
+ }
+ }
+ }
+}
+
+Time RttEstimator::AckSeq (SequenceNumber a)
+{ // An ack has been received, calculate rtt and log this measurement
+ // Note we use a linear search (O(n)) for this since for the common
+ // case the ack'ed packet will be at the head of the list
+ Time m = Seconds (0.0);
+ if (history.size () == 0) return (m); // No pending history, just exit
+ RttHistory& h = history.front ();
+ if (!h.retx && a >= (h.seq + SequenceNumber (h.count)))
+ { // Ok to use this sample
+ m = Simulator::Now () - h.time; // Elapsed time
+ Measurement(m); // Log the measurement
+ ResetMultiplier(); // Reset multiplier on valid measurement
+ }
+ // Now delete all ack history with seq <= ack
+ while(history.size() > 0)
+ {
+ RttHistory& h = history.front ();
+ if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing
+ history.pop_front (); // Remove
+ }
+ return m;
+}
+
+void RttEstimator::ClearSent ()
+{ // Clear all history entries
+ next = 1;
+ history.clear ();
+}
+
+void RttEstimator::IncreaseMultiplier ()
+{
+ multiplier = std::min (multiplier * 2.0, defaultMaxMultiplier.GetValue ());
+}
+
+void RttEstimator::ResetMultiplier ()
+{
+ multiplier = 1.0;
+}
+
+void RttEstimator::Reset ()
+{ // Reset to initial state
+ next = 1;
+ est = initialEstimate;
+ history.clear (); // Remove all info from the history
+ nSamples = 0;
+ ResetMultiplier ();
+}
+
+// Base class, static methods
+void RttEstimator::InitialEstimate (Time e)
+{ // Set a new default initial estimate
+ initialEstimate = e;
+}
+
+Ptr<RttEstimator> RttEstimator::CreateDefault ()
+{
+ ClassId classId = defaultCid.GetValue ();
+ Ptr<RttEstimator> rtte = ComponentManager::Create<RttEstimator> (
+ classId, RttEstimator::iid, 0.1, initialEstimate
+ );
+ return rtte;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// Mean-Deviation Estimator
+const ClassId RttMeanDeviation::cid =
+ MakeClassId<RttMeanDeviation, double, Time> ("RttMeanDeviation",
+ RttEstimator::iid);
+
+RttMeanDeviation::RttMeanDeviation(double g) :
+ gain (g), variance (ns3::Seconds(0))
+{
+}
+
+RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
+ : RttEstimator (c), gain (c.gain), variance (c.variance)
+{
+}
+
+RttMeanDeviation::RttMeanDeviation (double g, Time e) :
+ RttEstimator (e), gain (g), variance (ns3::Seconds(0))
+{
+}
+
+void RttMeanDeviation::Measurement (Time m)
+{
+ if (nSamples)
+ { // Not first
+ Time err = m - est;
+ est = est + Scalar (gain) * err; // estimated rtt
+ err = Abs (err); // absolute value of error
+ variance = variance + Scalar (gain) * (err - variance); // variance of rtt
+ }
+ else
+ { // First sample
+ est = m; // Set estimate to current
+ //variance = m / 2; // And variance to current / 2
+ variance = m; // try this
+ }
+ nSamples++;
+}
+
+Time RttMeanDeviation::RetransmitTimeout ()
+{
+ // If not enough samples, justjust return 2 times estimate
+ //if (nSamples < 2) return est * 2;
+ if (variance < est / Scalar (4.0))
+ return est * Scalar (2 * multiplier); // At least twice current est
+ return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson
+}
+
+RttEstimator* RttMeanDeviation::Copy () const
+{
+ return new RttMeanDeviation (*this);
+}
+
+void RttMeanDeviation::Reset ()
+{ // Reset to initial state
+ variance = Seconds (0.0);
+ RttEstimator::Reset ();
+}
+}//namepsace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/rtt-estimator.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#ifndef __rtt_estimator_h__
+#define __rtt_estimator_h__
+
+#include <deque>
+#include "sequence-number.h"
+#include "ns3/nstime.h"
+#include "ns3/object.h"
+#include "ns3/component-manager.h"
+
+namespace ns3 {
+
+class RttHistory {
+public:
+ RttHistory (SequenceNumber s, uint32_t c, Time t);
+ RttHistory (const RttHistory& h); // Copy constructor
+public:
+ SequenceNumber seq; // First sequence number in packet sent
+ uint32_t count; // Number of bytes sent
+ Time time; // Time this one was sent
+ bool retx; // True if this has been retransmitted
+};
+
+typedef std::deque<RttHistory> RttHistory_t;
+
+class RttEstimator : public Object { // Base class for all RTT Estimators
+public:
+ static const InterfaceId iid;
+
+ RttEstimator();
+ RttEstimator(Time e);
+ RttEstimator(const RttEstimator&); // Copy constructor
+ virtual ~RttEstimator();
+
+ virtual void SentSeq(SequenceNumber, uint32_t);
+ virtual Time AckSeq(SequenceNumber);
+ virtual void ClearSent();
+ virtual void Measurement(Time t) = 0;
+ virtual Time Estimate() = 0;
+ virtual Time RetransmitTimeout() = 0;
+ void Init(SequenceNumber s) { next = s;}
+ virtual RttEstimator* Copy() const = 0;
+ virtual void IncreaseMultiplier();
+ virtual void ResetMultiplier();
+ virtual void Reset();
+
+private:
+ SequenceNumber next; // Next expected sequence to be sent
+ RttHistory_t history; // List of sent packet
+public:
+ Time est; // Current estimate
+ uint32_t nSamples;// Number of samples
+ double multiplier; // RTO Multiplier
+public:
+ static void InitialEstimate(Time);
+ static Ptr<RttEstimator> CreateDefault(); // Retrieve current default
+
+ static ClassIdDefaultValue defaultCid;
+ static NumericDefaultValue<double> defaultMaxMultiplier;
+
+private:
+ static Time initialEstimate; // Default initial estimate
+};
+
+// The "Mean-Deviation" estimator, as discussed by Van Jacobson
+// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+
+ //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator
+ //Doc:Class as described by Van Jacobson
+ //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+class RttMeanDeviation : public RttEstimator {
+public :
+ static const ClassId cid;
+
+ //Doc:Desc Constructor for {\tt RttMeanDeviation} specifying the gain factor for the
+ //Doc:Desc estimator.
+ //Doc:Arg1 Gain factor.
+ RttMeanDeviation (double g);
+
+ //Doc:Desc Constructor for {\tt RttMeanDeviation} specifying the gain factor
+ //Doc:Desc and the initial estimate.
+ //Doc:Arg1 Gain factor.
+ //Doc:Arg2 Initial estimate.
+ RttMeanDeviation (double g, Time e);
+
+ //Doc:Method
+ RttMeanDeviation (const RttMeanDeviation&); // Copy constructor
+ //Doc:Desc Copy constructor.
+ //Doc:Arg1 {\tt RttMeanDeviation} object to copy.
+
+ void Measurement (Time);
+ Time Estimate () { return est;}
+ Time Variance () { return variance;}
+ Time RetransmitTimeout ();
+ RttEstimator* Copy () const;
+ void Reset ();
+ void Gain (double g) { gain = g;}
+
+public:
+ double gain; // Filter gain
+ Time variance; // Current variance
+};
+}//namespace ns3
+#endif
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/sequence-number.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#include "sequence-number.h"
+
+bool operator< (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+ return l.seq < r.seq;
+}
+
+bool operator<= (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover
+ return l.seq <= r.seq;
+}
+
+bool operator> (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+ return l.seq > r.seq;
+}
+
+bool operator>= (const SequenceNumber l, const SequenceNumber r)
+{ // Account for 32 bit rollover
+ if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover
+ return l.seq >= r.seq;
+}
+
+// Non-Member Arithmetic operators
+SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r)
+{
+ return SequenceNumber (l.seq + r.seq);
+}
+
+SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r)
+{ // This assumes l is always bigger than r (allows for rollover)
+ if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq);
+ return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1); // Adjust for rollover
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/sequence-number.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// 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: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Ported from:
+// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers
+// George F. Riley. Georgia Tech, Spring 2002
+
+// Class to manage arithmetic operations on sequence numbers (mod 2^32)
+
+#ifndef __seq_h__
+#define __seq_h__
+
+#include <stdint.h>
+
+#define MAX_SEQ ((uint32_t)0xffffffff)
+
+class SequenceNumber {
+public:
+ SequenceNumber () : seq(0) { }
+ SequenceNumber (const uint32_t s) : seq (s) { }
+
+ operator uint32_t () const { return seq;}
+
+ SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;}
+
+ SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;}
+ SequenceNumber operator++ () { seq++; return *this;}
+ SequenceNumber operator++ (int) { SequenceNumber ss (seq); seq++; return ss;}
+ SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;}
+ SequenceNumber operator-- () { seq--; return *this;}
+ SequenceNumber operator-- (int) { SequenceNumber ss (seq); seq--; return ss;}
+public:
+ uint32_t seq;
+};
+
+// Comparison operators
+
+bool operator< (const SequenceNumber l, const SequenceNumber r);
+bool operator<= (const SequenceNumber l, const SequenceNumber r);
+bool operator> (const SequenceNumber l, const SequenceNumber r);
+bool operator>= (const SequenceNumber l, const SequenceNumber r);
+
+// Non-member arithmetic operators
+SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r);
+SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r);
+
+#endif
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-header.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include <stdint.h>
+#include <iostream>
+#include "tcp-socket.h"
+#include "tcp-header.h"
+#include "ns3/buffer.h"
+
+namespace ns3 {
+
+NS_HEADER_ENSURE_REGISTERED (TcpHeader);
+
+bool TcpHeader::m_calcChecksum = false;
+
+uint32_t
+TcpHeader::GetUid (void)
+{
+ static uint32_t uid = AllocateUid<TcpHeader> ("TcpHeader.ns3");
+ return uid;
+}
+
+TcpHeader::TcpHeader ()
+ : m_sourcePort (0),
+ m_destinationPort (0),
+ m_sequenceNumber (0),
+ m_ackNumber (0),
+ m_length (5),
+ m_flags (0),
+ m_windowSize (Tcp::defaultAdvWin.GetValue ()),
+ m_checksum (0),
+ m_urgentPointer (0)
+{
+}
+
+TcpHeader::~TcpHeader ()
+{}
+
+void
+TcpHeader::EnableChecksums (void)
+{
+ m_calcChecksum = true;
+}
+
+void TcpHeader::SetSourcePort (uint16_t port)
+{
+ m_sourcePort = port;
+}
+void TcpHeader::SetDestinationPort (uint16_t port)
+{
+ m_destinationPort = port;
+}
+void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber)
+{
+ m_sequenceNumber = sequenceNumber;
+}
+void TcpHeader::SetAckNumber (SequenceNumber ackNumber)
+{
+ m_ackNumber = ackNumber;
+}
+void TcpHeader::SetLength (uint8_t length)
+{
+ m_length = length;
+}
+void TcpHeader::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void TcpHeader::SetWindowSize (uint16_t windowSize)
+{
+ m_windowSize = windowSize;
+}
+void TcpHeader::SetChecksum (uint16_t checksum)
+{
+ m_checksum = checksum;
+}
+void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
+{
+ m_urgentPointer = urgentPointer;
+}
+
+uint16_t TcpHeader::GetSourcePort () const
+{
+ return m_sourcePort;
+}
+uint16_t TcpHeader::GetDestinationPort () const
+{
+ return m_destinationPort;
+}
+SequenceNumber TcpHeader::GetSequenceNumber () const
+{
+ return m_sequenceNumber;
+}
+SequenceNumber TcpHeader::GetAckNumber () const
+{
+ return m_ackNumber;
+}
+uint8_t TcpHeader::GetLength () const
+{
+ return m_length;
+}
+uint8_t TcpHeader::GetFlags () const
+{
+ return m_flags;
+}
+uint16_t TcpHeader::GetWindowSize () const
+{
+ return m_windowSize;
+}
+uint16_t TcpHeader::GetChecksum () const
+{
+ return m_checksum;
+}
+uint16_t TcpHeader::GetUrgentPointer () const
+{
+ return m_urgentPointer;
+}
+
+void
+TcpHeader::InitializeChecksum (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol)
+{
+ m_checksum = 0;
+//XXX requires peeking into IP to get length of the TCP segment
+}
+
+std::string
+TcpHeader::GetName (void) const
+{
+ return "TCP";
+}
+
+void TcpHeader::Print (std::ostream &os) const
+{
+ //XXX
+}
+uint32_t TcpHeader::GetSerializedSize (void) const
+{
+ return 20; //tcp headers are 20 bytes
+}
+void TcpHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteHtonU16 (m_sourcePort);
+ start.WriteHtonU16 (m_destinationPort);
+ start.WriteHtonU32 (m_sequenceNumber);
+ start.WriteHtonU32 (m_ackNumber);
+ start.WriteHtonU16 (m_length << 12 | m_flags); //reserved bits are all zero
+ start.WriteHtonU16 (m_windowSize);
+ //XXX calculate checksum here
+ start.WriteHtonU16 (m_checksum);
+ start.WriteHtonU16 (m_urgentPointer);
+}
+uint32_t TcpHeader::Deserialize (Buffer::Iterator start)
+{
+ m_sourcePort = start.ReadNtohU16 ();
+ m_destinationPort = start.ReadNtohU16 ();
+ m_sequenceNumber = start.ReadNtohU32 ();
+ m_ackNumber = start.ReadNtohU32 ();
+ uint16_t field = start.ReadNtohU16 ();
+ m_flags = field & 0x3F;
+ m_length = field>>12;
+ m_windowSize = start.ReadNtohU16 ();
+ m_checksum = start.ReadNtohU16 ();
+ m_urgentPointer = start.ReadNtohU16 ();
+ return GetSerializedSize ();
+}
+
+
+}; // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-header.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_HEADER_H
+#define TCP_HEADER_H
+
+#include <stdint.h>
+#include "ns3/header.h"
+#include "ns3/buffer.h"
+#include "ns3/tcp.h"
+#include "ns3/ipv4-address.h"
+#include "sequence-number.h"
+
+namespace ns3 {
+
+class TcpHeader : public Header {
+public:
+ static uint32_t GetUid (void);
+
+ TcpHeader ();
+ virtual ~TcpHeader ();
+
+ /**
+ * \brief Enable checksum calculation for TCP (XXX currently has no effect)
+ */
+ static void EnableChecksums (void);
+//Setters
+ /**
+ * \param port The source port for this TcpHeader
+ */
+ void SetSourcePort (uint16_t port);
+ /**
+ * \param port the destination port for this TcpHeader
+ */
+ void SetDestinationPort (uint16_t port);
+ /**
+ * \param sequenceNumber the sequence number for this TcpHeader
+ */
+ void SetSequenceNumber (SequenceNumber sequenceNumber);
+ /**
+ * \param ackNumber the ACK number for this TcpHeader
+ */
+ void SetAckNumber (SequenceNumber ackNumber);
+ /**
+ * \param length the length of this TcpHeader
+ */
+ void SetLength (uint8_t length);
+ /**
+ * \param flags the flags for this TcpHeader
+ */
+ void SetFlags (uint8_t flags);
+ /**
+ * \param windowSize the window size for this TcpHeader
+ */
+ void SetWindowSize (uint16_t windowSize);
+ /**
+ * \param checksum the checksum for this TcpHeader
+ */
+ void SetChecksum (uint16_t checksum);
+ /**
+ * \param urgentPointer the urgent pointer for this TcpHeader
+ */
+ void SetUrgentPointer (uint16_t urgentPointer);
+
+
+//Getters
+ /**
+ * \return The source port for this TcpHeader
+ */
+ uint16_t GetSourcePort () const;
+ /**
+ * \return the destination port for this TcpHeader
+ */
+ uint16_t GetDestinationPort () const;
+ /**
+ * \return the sequence number for this TcpHeader
+ */
+ SequenceNumber GetSequenceNumber () const;
+ /**
+ * \return the ACK number for this TcpHeader
+ */
+ SequenceNumber GetAckNumber () const;
+ /**
+ * \return the length of this TcpHeader
+ */
+ uint8_t GetLength () const;
+ /**
+ * \return the flags for this TcpHeader
+ */
+ uint8_t GetFlags () const;
+ /**
+ * \return the window size for this TcpHeader
+ */
+ uint16_t GetWindowSize () const;
+ /**
+ * \return the checksum for this TcpHeader
+ */
+ uint16_t GetChecksum () const;
+ /**
+ * \return the urgent pointer for this TcpHeader
+ */
+ uint16_t GetUrgentPointer () const;
+
+ /**
+ * \param source the ip source to use in the underlying
+ * ip packet.
+ * \param destination the ip destination to use in the
+ * underlying ip packet.
+ * \param protocol the protocol number to use in the underlying
+ * ip packet.
+ *
+ * If you want to use tcp checksums, you should call this
+ * method prior to adding the header to a packet.
+ */
+ void InitializeChecksum (Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol);
+
+ typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16,
+ URG = 32} Flags_t;
+
+ std::string GetName (void) const;
+ void Print (std::ostream &os) const;
+ uint32_t GetSerializedSize (void) const;
+ void Serialize (Buffer::Iterator start) const;
+ uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+ uint16_t m_sourcePort;
+ uint16_t m_destinationPort;
+ uint32_t m_sequenceNumber;
+ uint32_t m_ackNumber;
+ uint8_t m_length; // really a uint4_t
+ uint8_t m_flags; // really a uint6_t
+ uint16_t m_windowSize;
+ uint16_t m_checksum;
+ uint16_t m_urgentPointer;
+
+ static bool m_calcChecksum;
+};
+
+}; // namespace ns3
+
+#endif /* TCP_HEADER */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-impl.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#include "tcp-impl.h"
+#include "tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+TcpImpl::TcpImpl (Ptr<TcpL4Protocol> tcp)
+ : m_tcp (tcp)
+{}
+TcpImpl::~TcpImpl ()
+{
+ NS_ASSERT (m_tcp == 0);
+}
+
+Ptr<Socket>
+TcpImpl::CreateSocket (void)
+{
+ return m_tcp->CreateSocket ();
+}
+
+void
+TcpImpl::DoDispose (void)
+{
+ m_tcp = 0;
+ Tcp::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-impl.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_IMPL_H
+#define TCP_IMPL_H
+
+#include "ns3/tcp.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class TcpL4Protocol;
+
+/**
+ * \ingroup InternetNode
+ * \defgroup Tcp Tcp
+ *
+ * \section Tcp Overview
+ *
+ * The TCP code in ns3::InternetNode is ported from the
+ * <a href="http://www.ece.gatech.edu/research/labs/MANIACS/GTNetS/">
+ * Georgia Tech Network Simulator (GTNetS)</a>.
+ *
+ * Most of the logic is in class ns3::TcpSocket.
+ */
+class TcpImpl : public Tcp
+{
+public:
+ TcpImpl (Ptr<TcpL4Protocol> tcp);
+ virtual ~TcpImpl ();
+
+ virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<TcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* TCP_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-l4-protocol.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,485 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "tcp-l4-protocol.h"
+#include "tcp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "tcp-socket.h"
+
+#include "tcp-typedefs.h"
+
+#include <vector>
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol");
+
+namespace ns3 {
+
+//State Machine things --------------------------------------------------------
+TcpStateMachine::TcpStateMachine()
+ : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)),
+ eV (MAX_FLAGS)
+{
+ NS_LOG_FUNCTION;
+
+ // Create the state table
+ // Closed state
+ aT[CLOSED][APP_LISTEN] = SA (LISTEN, NO_ACT);
+ aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[CLOSED][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SEQ_RECV] = SA (CLOSED, NO_ACT);
+ aT[CLOSED][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[CLOSED][TIMEOUT] = SA (CLOSED, RST_TX);
+ aT[CLOSED][ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][FIN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSED][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSED][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Listen State
+ // For the listen state, anything other than CONNECT or SEND
+ // is simply ignored....this likely indicates the child TCP
+ // has finished and issued unbind call, but the remote end
+ // has not yet closed.
+ aT[LISTEN][APP_LISTEN] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[LISTEN][APP_SEND] = SA (SYN_SENT, SYN_TX);
+ aT[LISTEN][SEQ_RECV] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[LISTEN][TIMEOUT] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); //XXX hacked for now, should stay in listen and replicate
+ aT[LISTEN][SYN_ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][FIN_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][FIN_ACK_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][RST_RX] = SA (LISTEN, NO_ACT);
+ aT[LISTEN][BAD_FLAGS] = SA (LISTEN, NO_ACT);
+
+ // Syn Sent State
+ aT[SYN_SENT][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[SYN_SENT][APP_SEND] = SA (SYN_SENT, NO_ACT);
+ aT[SYN_SENT][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
+ aT[SYN_SENT][APP_CLOSE] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][TIMEOUT] = SA (CLOSED, NO_ACT);
+ aT[SYN_SENT][ACK_RX] = SA (SYN_SENT, NO_ACT);
+ aT[SYN_SENT][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[SYN_SENT][SYN_ACK_RX] = SA (ESTABLISHED, ACK_TX_1);
+ aT[SYN_SENT][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][FIN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_SENT][RST_RX] = SA (CLOSED, APP_NOTIFY);
+ aT[SYN_SENT][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Syn Recvd State
+ aT[SYN_RCVD][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX);
+ aT[SYN_RCVD][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
+ aT[SYN_RCVD][TIMEOUT] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][ACK_RX] = SA (ESTABLISHED, SERV_NOTIFY);
+ aT[SYN_RCVD][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[SYN_RCVD][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][FIN_RX] = SA (CLOSED, RST_TX);
+ aT[SYN_RCVD][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[SYN_RCVD][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[SYN_RCVD][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Established State
+ aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED, RST_TX);
+ aT[ESTABLISHED][APP_SEND] = SA (ESTABLISHED,TX_DATA);
+ aT[ESTABLISHED][SEQ_RECV] = SA (ESTABLISHED,NEW_SEQ_RX);
+ aT[ESTABLISHED][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX);
+ aT[ESTABLISHED][TIMEOUT] = SA (ESTABLISHED,RETX);
+ aT[ESTABLISHED][ACK_RX] = SA (ESTABLISHED,NEW_ACK);
+ aT[ESTABLISHED][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX);
+ aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT);
+ aT[ESTABLISHED][FIN_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE);
+ aT[ESTABLISHED][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[ESTABLISHED][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Close Wait State
+ aT[CLOSE_WAIT][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[CLOSE_WAIT][APP_SEND] = SA (CLOSE_WAIT, TX_DATA);
+ aT[CLOSE_WAIT][SEQ_RECV] = SA (CLOSE_WAIT, NEW_SEQ_RX);
+ aT[CLOSE_WAIT][APP_CLOSE] = SA (LAST_ACK, FIN_ACK_TX);
+ aT[CLOSE_WAIT][TIMEOUT] = SA (CLOSE_WAIT, NO_ACT);
+ aT[CLOSE_WAIT][ACK_RX] = SA (CLOSE_WAIT, NO_ACT);
+ aT[CLOSE_WAIT][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSE_WAIT][FIN_RX] = SA (CLOSE_WAIT, ACK_TX);
+ aT[CLOSE_WAIT][FIN_ACK_RX] = SA (CLOSE_WAIT, ACK_TX);
+ aT[CLOSE_WAIT][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSE_WAIT][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // Close Last Ack State
+ aT[LAST_ACK][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT, SYN_TX);
+ aT[LAST_ACK][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][SEQ_RECV] = SA (LAST_ACK, NEW_SEQ_RX);
+ aT[LAST_ACK][APP_CLOSE] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][TIMEOUT] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][ACK_RX] = SA (CLOSED, APP_CLOSED);
+ aT[LAST_ACK][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[LAST_ACK][FIN_RX] = SA (LAST_ACK, FIN_ACK_TX);
+ aT[LAST_ACK][FIN_ACK_RX] = SA (CLOSED, NO_ACT);
+ aT[LAST_ACK][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[LAST_ACK][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // FIN_WAIT_1 state
+ aT[FIN_WAIT_1][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][SEQ_RECV] = SA (FIN_WAIT_1, NEW_SEQ_RX);
+ aT[FIN_WAIT_1][APP_CLOSE] = SA (FIN_WAIT_1, NO_ACT);
+ aT[FIN_WAIT_1][TIMEOUT] = SA (FIN_WAIT_1, NO_ACT);
+ aT[FIN_WAIT_1][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
+ aT[FIN_WAIT_1][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_1][FIN_RX] = SA (CLOSING, ACK_TX);
+ aT[FIN_WAIT_1][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_1][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[FIN_WAIT_1][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // FIN_WAIT_2 state
+ aT[FIN_WAIT_2][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][SEQ_RECV] = SA (FIN_WAIT_2, NO_ACT);
+ aT[FIN_WAIT_2][APP_CLOSE] = SA (FIN_WAIT_2, NO_ACT);
+ aT[FIN_WAIT_2][TIMEOUT] = SA (FIN_WAIT_2, NO_ACT);
+ aT[FIN_WAIT_2][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK);
+ aT[FIN_WAIT_2][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[FIN_WAIT_2][FIN_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_2][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX);
+ aT[FIN_WAIT_2][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[FIN_WAIT_2][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // CLOSING state
+ aT[CLOSING][APP_LISTEN] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_CONNECT] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_SEND] = SA (CLOSED, RST_TX);
+ aT[CLOSING][SEQ_RECV] = SA (CLOSED, RST_TX);
+ aT[CLOSING][APP_CLOSE] = SA (CLOSED, RST_TX);
+ aT[CLOSING][TIMEOUT] = SA (CLOSING, NO_ACT);
+ aT[CLOSING][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[CLOSING][SYN_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSING][SYN_ACK_RX] = SA (CLOSED, RST_TX);
+ aT[CLOSING][FIN_RX] = SA (CLOSED, ACK_TX);
+ aT[CLOSING][FIN_ACK_RX] = SA (CLOSED, ACK_TX);
+ aT[CLOSING][RST_RX] = SA (CLOSED, CANCEL_TM);
+ aT[CLOSING][BAD_FLAGS] = SA (CLOSED, RST_TX);
+
+ // TIMED_WAIT state
+ aT[TIMED_WAIT][APP_LISTEN] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_SEND] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SEQ_RECV] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][APP_CLOSE] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][TIMEOUT] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SYN_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][SYN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][FIN_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][FIN_ACK_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][RST_RX] = SA (TIMED_WAIT, NO_ACT);
+ aT[TIMED_WAIT][BAD_FLAGS] = SA (TIMED_WAIT, NO_ACT);
+
+ // Create the flags lookup table
+ eV[ 0x00] = SEQ_RECV; // No flags
+ eV[ 0x01] = FIN_RX; // Fin
+ eV[ 0x02] = SYN_RX; // Syn
+ eV[ 0x03] = BAD_FLAGS; // Illegal
+ eV[ 0x04] = RST_RX; // Rst
+ eV[ 0x05] = BAD_FLAGS; // Illegal
+ eV[ 0x06] = BAD_FLAGS; // Illegal
+ eV[ 0x07] = BAD_FLAGS; // Illegal
+ eV[ 0x08] = SEQ_RECV; // Psh flag is not used
+ eV[ 0x09] = FIN_RX; // Fin
+ eV[ 0x0a] = SYN_RX; // Syn
+ eV[ 0x0b] = BAD_FLAGS; // Illegal
+ eV[ 0x0c] = RST_RX; // Rst
+ eV[ 0x0d] = BAD_FLAGS; // Illegal
+ eV[ 0x0e] = BAD_FLAGS; // Illegal
+ eV[ 0x0f] = BAD_FLAGS; // Illegal
+ eV[ 0x10] = ACK_RX; // Ack
+ eV[ 0x11] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x12] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x13] = BAD_FLAGS; // Illegal
+ eV[ 0x14] = RST_RX; // Rst
+ eV[ 0x15] = BAD_FLAGS; // Illegal
+ eV[ 0x16] = BAD_FLAGS; // Illegal
+ eV[ 0x17] = BAD_FLAGS; // Illegal
+ eV[ 0x18] = ACK_RX; // Ack
+ eV[ 0x19] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x1b] = BAD_FLAGS; // Illegal
+ eV[ 0x1c] = RST_RX; // Rst
+ eV[ 0x1d] = BAD_FLAGS; // Illegal
+ eV[ 0x1e] = BAD_FLAGS; // Illegal
+ eV[ 0x1f] = BAD_FLAGS; // Illegal
+ eV[ 0x20] = SEQ_RECV; // No flags (Urgent not presently used)
+ eV[ 0x21] = FIN_RX; // Fin
+ eV[ 0x22] = SYN_RX; // Syn
+ eV[ 0x23] = BAD_FLAGS; // Illegal
+ eV[ 0x24] = RST_RX; // Rst
+ eV[ 0x25] = BAD_FLAGS; // Illegal
+ eV[ 0x26] = BAD_FLAGS; // Illegal
+ eV[ 0x27] = BAD_FLAGS; // Illegal
+ eV[ 0x28] = SEQ_RECV; // Psh flag is not used
+ eV[ 0x29] = FIN_RX; // Fin
+ eV[ 0x2a] = SYN_RX; // Syn
+ eV[ 0x2b] = BAD_FLAGS; // Illegal
+ eV[ 0x2c] = RST_RX; // Rst
+ eV[ 0x2d] = BAD_FLAGS; // Illegal
+ eV[ 0x2e] = BAD_FLAGS; // Illegal
+ eV[ 0x2f] = BAD_FLAGS; // Illegal
+ eV[ 0x30] = ACK_RX; // Ack (Urgent not used)
+ eV[ 0x31] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x32] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x33] = BAD_FLAGS; // Illegal
+ eV[ 0x34] = RST_RX; // Rst
+ eV[ 0x35] = BAD_FLAGS; // Illegal
+ eV[ 0x36] = BAD_FLAGS; // Illegal
+ eV[ 0x37] = BAD_FLAGS; // Illegal
+ eV[ 0x38] = ACK_RX; // Ack
+ eV[ 0x39] = FIN_ACK_RX;// Fin/Ack
+ eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack
+ eV[ 0x3b] = BAD_FLAGS; // Illegal
+ eV[ 0x3c] = RST_RX; // Rst
+ eV[ 0x3d] = BAD_FLAGS; // Illegal
+ eV[ 0x3e] = BAD_FLAGS; // Illegal
+ eV[ 0x3f] = BAD_FLAGS; // Illegal
+}
+
+SA TcpStateMachine::Lookup (States_t s, Events_t e)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << s << e);
+ return aT[s][e];
+}
+
+Events_t TcpStateMachine::FlagsEvent (uint8_t f)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << f);
+ // Lookup event from flags
+ if (f >= MAX_FLAGS) return BAD_FLAGS;
+ return eV[f]; // Look up flags event
+}
+
+static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine
+
+//TcpL4Protocol stuff----------------------------------------------------------
+
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
+
+TcpL4Protocol::TcpL4Protocol (Ptr<Node> node)
+ : Ipv4L4Protocol (PROT_NUMBER, 2),
+ m_node (node),
+ m_endPoints (new Ipv4EndPointDemux ())
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << node);
+ NS_LOG_LOGIC("Made a TcpL4Protocol "<<this);
+}
+
+TcpL4Protocol::~TcpL4Protocol ()
+{
+ NS_LOG_FUNCTION;
+ }
+
+void
+TcpL4Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION;
+ if (m_endPoints != 0)
+ {
+ delete m_endPoints;
+ m_endPoints = 0;
+ }
+ m_node = 0;
+ Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+TcpL4Protocol::CreateSocket (void)
+{
+ NS_LOG_FUNCTION;
+ Ptr<Socket> socket = Create<TcpSocket> (m_node, this);
+ return socket;
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (void)
+{
+ NS_LOG_FUNCTION;
+ return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << address);
+ return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (uint16_t port)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << port);
+ return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << address << port);
+ return m_endPoints->Allocate (address, port);
+}
+
+Ipv4EndPoint *
+TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << localAddress << localPort << peerAddress << peerPort);
+ return m_endPoints->Allocate (localAddress, localPort,
+ peerAddress, peerPort);
+}
+
+void
+TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << endPoint);
+ m_endPoints->DeAllocate (endPoint);
+}
+
+void
+TcpL4Protocol::Receive (Ptr<Packet> packet,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << packet << source << destination << incomingInterface);
+
+ TcpHeader tcpHeader;
+ //these two do a peek, so that the packet can be forwarded up
+ packet->RemoveHeader (tcpHeader);
+ packet->AddHeader (tcpHeader);
+ NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
+ Ipv4EndPointDemux::EndPoints endPoints =
+ m_endPoints->Lookup (destination, tcpHeader.GetDestinationPort (),
+ source, tcpHeader.GetSourcePort (),incomingInterface);
+ if (endPoints.empty ())
+ {
+ NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<<this);
+ std::ostringstream oss;
+ oss<<" destination IP: ";
+ destination.Print (oss);
+ oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
+ source.Print (oss);
+ oss<<" source port: "<<tcpHeader.GetSourcePort ();
+ NS_LOG_LOGIC (oss.str ());
+ }
+ for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+ endPoint != endPoints.end (); endPoint++)
+ {
+ NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
+ (*endPoint)->ForwardUp (packet, source, tcpHeader.GetSourcePort ());
+ }
+}
+
+void
+TcpL4Protocol::Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << packet << saddr << daddr << sport << dport);
+
+ TcpHeader tcpHeader;
+ tcpHeader.SetDestinationPort (dport);
+ tcpHeader.SetSourcePort (sport);
+ tcpHeader.InitializeChecksum (saddr,
+ daddr,
+ PROT_NUMBER);
+ tcpHeader.SetFlags (TcpHeader::ACK);
+ tcpHeader.SetAckNumber (0);
+
+ packet->AddHeader (tcpHeader);
+
+ Ptr<Ipv4L3Protocol> ipv4 =
+ m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+ if (ipv4 != 0)
+ {
+ ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+ }
+}
+
+void
+TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
+ Ipv4Address saddr, Ipv4Address daddr)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << packet << saddr << daddr);
+ // XXX outgoingHeader cannot be logged
+
+ outgoingHeader.SetLength (5); //header length in units of 32bit words
+ outgoingHeader.SetChecksum (0); //XXX
+ outgoingHeader.SetUrgentPointer (0); //XXX
+
+ packet->AddHeader (outgoingHeader);
+
+ Ptr<Ipv4L3Protocol> ipv4 =
+ m_node->QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
+ if (ipv4 != 0)
+ {
+ ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+ }
+ else
+ NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
+}
+
+}; // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-l4-protocol.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+#ifndef TCP_L4_PROTOCOL_H
+#define TCP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+
+#include "tcp-header.h"
+#include "tcp-typedefs.h"
+
+namespace ns3 {
+
+class Node;
+class TraceResolver;
+class TraceContext;
+class Socket;
+class TcpHeader;
+/**
+ * \brief Implementation of the TCP protocol
+ */
+class TcpL4Protocol : public Ipv4L4Protocol {
+public:
+ static const uint8_t PROT_NUMBER;
+ /**
+ * \brief Constructor
+ * \param node The node this protocol is associated with
+ */
+ TcpL4Protocol (Ptr<Node> node);
+ virtual ~TcpL4Protocol ();
+
+ /**
+ * \return A smart Socket pointer to a TcpSocket, allocated by this instance
+ * of the TCP protocol
+ */
+ Ptr<Socket> CreateSocket (void);
+
+ Ipv4EndPoint *Allocate (void);
+ Ipv4EndPoint *Allocate (Ipv4Address address);
+ Ipv4EndPoint *Allocate (uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort);
+
+ void DeAllocate (Ipv4EndPoint *endPoint);
+
+// // called by TcpSocket.
+// bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr,
+// uint16_t sport, uint16_t dport);
+
+ /**
+ * \brief Send a packet via TCP
+ * \param packet The packet to send
+ * \param saddr The source Ipv4Address
+ * \param daddr The destination Ipv4Address
+ * \param sport The source port number
+ * \param dport The destination port number
+ */
+ void Send (Ptr<Packet> packet,
+ Ipv4Address saddr, Ipv4Address daddr,
+ uint16_t sport, uint16_t dport);
+ /**
+ * \brief Recieve a packet up the protocol stack
+ * \param p The Packet to dump the contents into
+ * \param source The source's Ipv4Address
+ * \param destination The destinations Ipv4Address
+ * \param incomingInterface The Ipv4Interface it was received on
+ */
+ virtual void Receive (Ptr<Packet> p,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<Node> m_node;
+ Ipv4EndPointDemux *m_endPoints;
+private:
+ friend class TcpSocket;
+ void SendPacket (Ptr<Packet>, TcpHeader,
+ Ipv4Address, Ipv4Address);
+};
+
+}; // namespace ns3
+
+#endif /* TCP_L4_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,1077 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "tcp-socket.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+#include "ns3/simulation-singleton.h"
+#include "tcp-typedefs.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/default-value.h"
+
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("TcpSocket");
+
+using namespace std;
+
+namespace ns3 {
+
+TcpSocket::TcpSocket (Ptr<Node> node, Ptr<TcpL4Protocol> tcp)
+ : m_skipRetxResched (false),
+ m_dupAckCount (0),
+ m_endPoint (0),
+ m_node (node),
+ m_tcp (tcp),
+ m_errno (ERROR_NOTERROR),
+ m_shutdownSend (false),
+ m_shutdownRecv (false),
+ m_connected (false),
+ m_state (CLOSED),
+ m_closeNotified (false),
+ m_closeRequestNotified (false),
+ m_closeOnEmpty (false),
+ m_nextTxSequence (0),
+ m_highTxMark (0),
+ m_highestRxAck (0),
+ m_lastRxAck (0),
+ m_nextRxSequence (0),
+ m_pendingData (0),
+ m_segmentSize (Tcp::defaultSegSize.GetValue()),
+ m_rxWindowSize (Tcp::defaultAdvWin.GetValue()),
+ m_advertisedWindowSize (Tcp::defaultAdvWin.GetValue()),
+ m_cWnd (Tcp::defaultInitialCWnd.GetValue() * m_segmentSize),
+ m_ssThresh (Tcp::defaultSSThresh.GetValue()),
+ m_initialCWnd (Tcp::defaultInitialCWnd.GetValue()),
+ m_rtt (RttEstimator::CreateDefault()),
+ m_lastMeasuredRtt (Seconds(0.0)),
+ m_cnTimeout (Seconds (Tcp::defaultConnTimeout.GetValue ())),
+ m_cnCount (Tcp::defaultConnCount.GetValue ())
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this<<node<<tcp);
+}
+
+TcpSocket::~TcpSocket ()
+{
+ NS_LOG_FUNCTION;
+ m_node = 0;
+ if (m_endPoint != 0)
+ {
+ NS_ASSERT (m_tcp != 0);
+ /**
+ * Note that this piece of code is a bit tricky:
+ * when DeAllocate is called, it will call into
+ * Ipv4EndPointDemux::Deallocate which triggers
+ * a delete of the associated endPoint which triggers
+ * in turn a call to the method ::Destroy below
+ * will will zero the m_endPoint field.
+ */
+ NS_ASSERT (m_endPoint != 0);
+ m_tcp->DeAllocate (m_endPoint);
+ NS_ASSERT (m_endPoint == 0);
+ }
+ m_tcp = 0;
+ delete m_pendingData; //prevents leak
+}
+
+enum Socket::SocketErrno
+TcpSocket::GetErrno (void) const
+{
+ NS_LOG_FUNCTION;
+ return m_errno;
+}
+
+Ptr<Node>
+TcpSocket::GetNode (void) const
+{
+ NS_LOG_FUNCTION;
+ return m_node;
+}
+
+void
+TcpSocket::Destroy (void)
+{
+ NS_LOG_FUNCTION;
+ m_node = 0;
+ m_endPoint = 0;
+ m_tcp = 0;
+}
+int
+TcpSocket::FinishBind (void)
+{
+ NS_LOG_FUNCTION;
+ if (m_endPoint == 0)
+ {
+ return -1;
+ }
+ m_endPoint->SetRxCallback (MakeCallback (&TcpSocket::ForwardUp, this));
+ m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocket::Destroy, this));
+ return 0;
+}
+
+int
+TcpSocket::Bind (void)
+{
+ NS_LOG_FUNCTION;
+ m_endPoint = m_tcp->Allocate ();
+ return FinishBind ();
+}
+int
+TcpSocket::Bind (const Address &address)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this<<address);
+ if (!InetSocketAddress::IsMatchingType (address))
+ {
+ return ERROR_INVAL;
+ }
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ if (ipv4 == Ipv4Address::GetAny () && port == 0)
+ {
+ m_endPoint = m_tcp->Allocate ();
+ NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (port);
+ NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4);
+ NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4, port);
+ NS_LOG_LOGIC ("TcpSocket "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+
+ return FinishBind ();
+}
+
+int
+TcpSocket::ShutdownSend (void)
+{
+ NS_LOG_FUNCTION;
+ m_shutdownSend = true;
+ return 0;
+}
+int
+TcpSocket::ShutdownRecv (void)
+{
+ NS_LOG_FUNCTION;
+ m_shutdownRecv = false;
+ return 0;
+}
+
+int
+TcpSocket::Close (void)
+{
+ NS_LOG_FUNCTION;
+ if (m_state == CLOSED)
+ {
+ return -1;
+ }
+ Actions_t action = ProcessEvent (APP_CLOSE);
+ if (m_pendingData)
+ {
+ if (action == FIN_TX && m_pendingData->Size () != 0 )
+ {
+ m_closeOnEmpty = true;
+ return 0;
+ }
+ }
+ ProcessAction (action);
+ ShutdownSend ();
+ return 0;
+}
+
+int
+TcpSocket::Connect (const Address & address)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << address);
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ m_defaultAddress = transport.GetIpv4 ();
+ m_defaultPort = transport.GetPort ();
+
+ uint32_t localIfIndex;
+ Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+
+ if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
+ {
+ m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
+ }
+ else
+ {
+ m_errno = ERROR_NOROUTETOHOST;
+ return -1;
+ }
+
+ Actions_t action = ProcessEvent (APP_CONNECT);
+ bool success = ProcessAction (action);
+ if (success)
+ {
+ return 0;
+ }
+ return -1;
+}
+int
+TcpSocket::Send (const Ptr<Packet> p) //p here is just data, no headers
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << p);
+ if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+ { // Ok to buffer some data to send
+ if (!m_pendingData)
+ {
+ m_pendingData = new PendingData (0); // Create if non-existent
+ m_firstPendingSequence = m_nextTxSequence; // Note seq of first
+ }
+ //PendingData::Add always copies the data buffer, never modifies
+ m_pendingData->Add (p->GetSize (), p->PeekData ());
+ Actions_t action = ProcessEvent (APP_SEND);
+ if (!ProcessAction (action))
+ {
+ return -1; // Failed, return zero
+ }
+ return p->GetSize ();
+ }
+ else
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+}
+
+int TcpSocket::Send (const uint8_t* buf, uint32_t size)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << buf << size);
+ if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+ { // Ok to buffer some data to send
+ if (!m_pendingData)
+ {
+ m_pendingData = new PendingData (); // Create if non-existent
+ m_firstPendingSequence = m_nextTxSequence; // Note seq of first
+ }
+ //PendingData::Add always copies the data buffer, never modifies
+ m_pendingData->Add (size,buf);
+ Actions_t action = ProcessEvent (APP_SEND);
+ if (!ProcessAction (action))
+ {
+ return -1; // Failed, return zero
+ }
+ return size;
+ }
+ else
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+}
+
+int TcpSocket::DoSendTo (Ptr<Packet> p, const Address &address)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << p << address);
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ return DoSendTo (p, ipv4, port);
+}
+
+int TcpSocket::DoSendTo (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << p << ipv4 << port);
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+ m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
+ m_endPoint->GetLocalPort (), port);
+ NotifyDataSent (p->GetSize ());
+ return 0;
+}
+
+int
+TcpSocket::SendTo (const Address &address, Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << address << p);
+ if (!m_connected)
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+ else
+ {
+ return Send (p); //drop the address according to BSD manpages
+ }
+}
+
+int
+TcpSocket::Listen (uint32_t q)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << q);
+ Actions_t action = ProcessEvent (APP_LISTEN);
+ ProcessAction (action);
+ return 0;
+}
+
+void
+TcpSocket::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << packet << ipv4 << port);
+ if (m_shutdownRecv)
+ {
+ return;
+ }
+ TcpHeader tcpHeader;
+ packet->RemoveHeader (tcpHeader);
+
+ if (tcpHeader.GetFlags () & TcpHeader::ACK)
+ {
+ Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
+ if (m != Seconds (0.0))
+ {
+ m_lastMeasuredRtt = m;
+ }
+ }
+
+ Events_t event = SimulationSingleton<TcpStateMachine>::Get ()->FlagsEvent (tcpHeader.GetFlags () );
+ Actions_t action = ProcessEvent (event); //updates the state
+ Address address = InetSocketAddress (ipv4, port);
+ ProcessPacketAction (action, packet, tcpHeader, address);
+}
+
+Actions_t TcpSocket::ProcessEvent (Events_t e)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << e);
+ States_t saveState = m_state;
+ NS_LOG_LOGIC ("TcpSocket " << this << " processing event " << e);
+ // simulation singleton is a way to get a single global static instance of a
+ // class intended to be a singleton; see simulation-singleton.h
+ SA stateAction = SimulationSingleton<TcpStateMachine>::Get ()->Lookup (m_state,e);
+ // debug
+ if (stateAction.action == RST_TX)
+ {
+ NS_LOG_LOGIC ("TcpSocket " << this << " sending RST from state "
+ << saveState << " event " << e);
+ }
+ bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED
+ && e != TIMEOUT);
+ m_state = stateAction.state;
+ NS_LOG_LOGIC ("TcpSocket " << this << " moved from state " << saveState
+ << " to state " <<m_state);
+ NS_LOG_LOGIC ("TcpSocket " << this << " pendingData " << m_pendingData);
+ if (saveState == SYN_SENT && m_state == ESTABLISHED)
+ // this means the application side has completed its portion of
+ // the handshaking
+ {
+ NotifyConnectionSucceeded ();
+ m_connected = true;
+ m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+ NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
+ }
+ if (needCloseNotify && !m_closeNotified)
+ {
+ NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from "
+ << m_state << " event " << e << " closeNot " << m_closeNotified
+ << " action " << stateAction.action);
+ NotifyCloseCompleted ();
+ m_closeNotified = true;
+ NS_LOG_LOGIC ("TcpSocket " << this << " calling Closed from PE"
+ << " origState " << saveState
+ << " event " << e);
+ NS_LOG_LOGIC ("TcpSocket " << this << " transition to CLOSED from "
+ << m_state << " event " << e
+ << " set CloseNotif ");
+ }
+ return stateAction.action;
+}
+
+void TcpSocket::SendEmptyPacket (uint8_t flags)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << flags);
+ Ptr<Packet> p = Create<Packet> ();
+ TcpHeader header;
+
+ header.SetFlags (flags);
+ header.SetSequenceNumber (m_nextTxSequence);
+ header.SetAckNumber (m_nextRxSequence);
+ header.SetSourcePort (m_endPoint->GetLocalPort ());
+ header.SetDestinationPort (m_defaultPort);
+ header.SetWindowSize (m_advertisedWindowSize);
+ m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
+ m_defaultAddress);
+ Time rto = m_rtt->RetransmitTimeout ();
+ if (flags & TcpHeader::SYN)
+ {
+ rto = m_cnTimeout;
+ m_cnCount--;
+ }
+ if (m_retxEvent.IsExpired () ) //no outstanding timer
+ {
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+ << Simulator::Now ().GetSeconds () << " to expire at time "
+ << (Simulator::Now () + rto).GetSeconds ());
+ m_retxEvent = Simulator::Schedule (rto, &TcpSocket::ReTxTimeout, this);
+ }
+}
+
+bool TcpSocket::ProcessAction (Actions_t a)
+{ // These actions do not require a packet or any TCP Headers
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << a);
+ switch (a)
+ {
+ case NO_ACT:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action: NO_ACT");
+ break;
+ case ACK_TX:
+ SendEmptyPacket (TcpHeader::ACK);
+ break;
+ case ACK_TX_1:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case RST_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action RST_TX");
+ SendEmptyPacket (TcpHeader::RST);
+ break;
+ case SYN_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_TX");
+ // TCP SYN Flag consumes one byte
+ m_nextTxSequence+= 1;
+ SendEmptyPacket (TcpHeader::SYN);
+ break;
+ case SYN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
+ SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+ break;
+ case FIN_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_TX");
+ SendEmptyPacket (TcpHeader::FIN);
+ break;
+ case FIN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action FIN_ACK_TX");
+ SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+ break;
+ case NEW_ACK:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case NEW_SEQ_RX:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ break;
+ case RETX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action RETX");
+ break;
+ case TX_DATA:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action TX_DATA");
+ SendPendingData ();
+ break;
+ case PEER_CLOSE:
+ NS_ASSERT (false); // This should be processed in ProcessPacketAction
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action PEER_CLOSE");
+ break;
+ case APP_CLOSED:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_CLOSED");
+ break;
+ case CANCEL_TM:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action CANCEL_TM");
+ break;
+ case APP_NOTIFY:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action APP_NOTIFY");
+ break;
+ case SERV_NOTIFY:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action SERV_NOTIFY");
+ NS_LOG_LOGIC ("TcpSocket " << this << " Connected!");
+ NotifyConnectionSucceeded ();
+ m_connected = true; // ! This is bogus; fix when we clone the tcp
+ m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+ break;
+ case LAST_ACTION:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action LAST_ACTION");
+ break;
+ }
+ return true;
+}
+
+bool TcpSocket::ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
+ uint32_t localIfIndex;
+ Ptr<Ipv4> ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+ switch (a)
+ {
+ case SYN_ACK_TX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action SYN_ACK_TX");
+ m_defaultPort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
+ m_defaultAddress =
+ InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
+ m_endPoint->SetPeer (m_defaultAddress, m_defaultPort);
+ if (ipv4->GetIfIndexForDestination (m_defaultAddress, localIfIndex))
+ {
+ m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex));
+ }
+ // TCP SYN consumes one byte
+ m_nextRxSequence++;
+ SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+ break;
+ case ACK_TX_1:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action ACK_TX_1");
+ // TCP SYN consumes one byte
+ m_nextRxSequence++;
+ SendEmptyPacket (TcpHeader::ACK);
+ m_rxWindowSize = tcpHeader.GetWindowSize ();
+ if (tcpHeader.GetAckNumber () > m_highestRxAck)
+ {
+ m_highestRxAck = tcpHeader.GetAckNumber ();
+ }
+ SendPendingData ();
+ break;
+ case NEW_ACK:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_ACK_TX");
+ if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing
+ {
+ break;
+ }
+ if (tcpHeader.GetAckNumber () == m_highestRxAck &&
+ tcpHeader.GetAckNumber () < m_nextTxSequence)
+ {
+ DupAck (tcpHeader, ++m_dupAckCount);
+ break;
+ }
+ if (tcpHeader.GetAckNumber () > m_highestRxAck)
+ {
+ m_dupAckCount = 0;
+ }
+ NewAck (tcpHeader.GetAckNumber ());
+ break;
+ case NEW_SEQ_RX:
+ NS_LOG_LOGIC ("TcpSocket " << this <<" Action NEW_SEQ_TX");
+ NewRx (p, tcpHeader, fromAddress); // Process new data received
+ break;
+ case PEER_CLOSE:
+ {
+ // First we have to be sure the FIN packet was not received
+ // out of sequence. If so, note pending close and process
+ // new sequence rx
+ if (tcpHeader.GetSequenceNumber () != m_nextRxSequence)
+ { // process close later
+ m_pendingClose = true;
+ NS_LOG_LOGIC ("TcpSocket " << this << " setting pendingClose"
+ << " rxseq " << tcpHeader.GetSequenceNumber ()
+ << " nextRxSeq " << m_nextRxSequence);
+ NewRx (p, tcpHeader, fromAddress);
+ return true;
+ }
+ // Now we need to see if any data came with the FIN
+ // if so, call NewRx
+ if (p->GetSize () != 0)
+ {
+ NewRx (p, tcpHeader, fromAddress);
+ }
+ States_t saveState = m_state; // Used to see if app responds
+ NS_LOG_LOGIC ("TcpSocket " << this
+ << " peer close, state " << m_state);
+ if (!m_closeRequestNotified)
+ {
+ NS_LOG_LOGIC ("TCP " << this
+ << " calling AppCloseRequest");
+ NotifyCloseRequested ();
+ m_closeRequestNotified = true;
+ }
+ NS_LOG_LOGIC ("TcpSocket " << this
+ << " peer close, state after " << m_state);
+ if (m_state == saveState)
+ { // Need to ack, the application will close later
+ SendEmptyPacket (TcpHeader::ACK);
+ // Also need to re-tx the ack if we
+ }
+ if (m_state == LAST_ACK)
+ {
+ NS_LOG_LOGIC ("TcpSocket " << this << " scheduling LATO1");
+ m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
+ &TcpSocket::LastAckTimeout,this);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return true;
+}
+
+bool TcpSocket::SendPendingData (bool withAck)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << withAck);
+ NS_LOG_LOGIC ("ENTERING SendPendingData");
+ if (!m_pendingData)
+ {
+ return false; // No data exists
+ }
+ uint32_t nPacketsSent = 0;
+ while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence))
+ {
+ uint32_t w = AvailableWindow ();// Get available window size
+ NS_LOG_LOGIC ("TcpSocket " << this << " SendPendingData"
+ << " w " << w
+ << " rxwin " << m_rxWindowSize
+ << " cWnd " << m_cWnd
+ << " segsize " << m_segmentSize
+ << " nextTxSeq " << m_nextTxSequence
+ << " highestRxAck " << m_highestRxAck
+ << " pd->Size " << m_pendingData->Size ()
+ << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence));
+
+ if (w < m_segmentSize && m_pendingData->Size () > w)
+ {
+ break; // No more
+ }
+ uint32_t s = std::min (w, m_segmentSize); // Send no more than window
+ PendingData* d = m_pendingData->CopyFromSeq (s, m_firstPendingSequence,
+ m_nextTxSequence);
+ NS_LOG_LOGIC("TcpSocket " << this << " sendPendingData"
+ << " txseq " << m_nextTxSequence
+ << " s " << s
+ << " datasize " << d->Size() );
+ uint8_t flags = 0;
+ if (withAck)
+ {
+ flags |= TcpHeader::ACK;
+ }
+ uint32_t sz = d->Size (); // Size of packet
+ uint32_t remainingData = m_pendingData->SizeFromSeq(
+ m_firstPendingSequence,
+ m_nextTxSequence + SequenceNumber (sz));
+ if (m_closeOnEmpty && (remainingData == 0))
+ {
+ flags = TcpHeader::FIN;
+ m_state = FIN_WAIT_1;
+ }
+ // Create and send the packet
+
+ Ptr<Packet> p = Create<Packet> (d->data, sz);
+
+ TcpHeader header;
+ header.SetFlags (flags);
+ header.SetSequenceNumber (m_nextTxSequence);
+ header.SetAckNumber (m_nextRxSequence);
+ header.SetSourcePort (m_endPoint->GetLocalPort());
+ header.SetDestinationPort (m_defaultPort);
+ if (m_shutdownSend)
+ {
+ m_errno = ERROR_SHUTDOWN;
+ return -1;
+ }
+
+ Time rto = m_rtt->RetransmitTimeout ();
+ if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit
+ {
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time " <<
+ Simulator::Now ().GetSeconds () << " to expire at time " <<
+ (Simulator::Now () + rto).GetSeconds () );
+ m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
+ }
+ NS_LOG_LOGIC ("About to send a packet with flags: " << flags);
+ m_tcp->SendPacket (p, header,
+ m_endPoint->GetLocalAddress (),
+ m_defaultAddress);
+ m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT
+ NotifyDataSent (p->GetSize () ); // notify the application
+ nPacketsSent++; // Count sent this loop
+ m_nextTxSequence += sz; // Advance next tx sequence
+ m_highTxMark = std::max (m_nextTxSequence, m_highTxMark);// Note the high water mark
+ }
+ NS_LOG_LOGIC ("Sent "<<nPacketsSent<<" packets");
+ NS_LOG_LOGIC("RETURN SendPendingData");
+ return (nPacketsSent>0);
+}
+
+uint32_t TcpSocket::UnAckDataCount ()
+{
+ NS_LOG_FUNCTION;
+ return m_nextTxSequence - m_highestRxAck;
+}
+
+uint32_t TcpSocket::BytesInFlight ()
+{
+ NS_LOG_FUNCTION;
+ return m_highTxMark - m_highestRxAck;
+}
+
+uint32_t TcpSocket::Window ()
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_LOGIC ("TcpSocket::Window() "<<this);
+ return std::min (m_rxWindowSize, m_cWnd);
+}
+
+uint32_t TcpSocket::AvailableWindow ()
+{
+ NS_LOG_FUNCTION;
+ uint32_t unack = UnAckDataCount (); // Number of outstanding bytes
+ uint32_t win = Window ();
+ if (win < unack)
+ {
+ return 0; // No space available
+ }
+ return (win - unack); // Amount of window space available
+}
+
+void TcpSocket::NewRx (Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << p << "tcpHeader " << fromAddress);
+ NS_LOG_LOGIC ("TcpSocket " << this << " NewRx, p.size is " << p->GetSize () );
+ States_t origState = m_state;
+ uint32_t s = p->GetSize (); // Size of associated data
+ if (s == 0)
+ {// Nothing to do if no associated data
+ return;
+ }
+ // Log sequence received if enabled
+ // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber);
+ // Three possibilities
+ // 1) Received seq is expected, deliver this and any buffered data
+ // 2) Received seq is < expected, just re-ack previous
+ // 3) Received seq is > expected, just re-ack previous and buffer data
+ if (tcpHeader.GetSequenceNumber () == m_nextRxSequence)
+ { // If seq is expected seq
+ // 1) Update nextRxSeq
+ // 2) Deliver to application this packet
+ // 3) See if any buffered can be delivered
+ // 4) Send the ack
+ m_nextRxSequence += s; // Advance next expected sequence
+ //bytesReceived += s; // Statistics
+ NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
+ NotifyDataReceived (p, fromAddress);
+ if (m_closeNotified)
+ {
+ NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif");
+ }
+ NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq by " << s);
+ // Look for buffered data
+ UnAckData_t::iterator i;
+ // Note that the bufferedData list DOES contain the tcp header
+ while (!m_bufferedData.empty ())
+ { // Check the buffered data for delivery
+ NS_LOG_LOGIC("TCP " << this << " bufferedData.size() "
+ << m_bufferedData.size ()
+ << " time " << Simulator::Now ());
+ i = m_bufferedData.begin ();
+ Ptr<Packet> p1 = i->second;
+ SequenceNumber s1 = 0;
+ if (i->first > m_nextRxSequence)
+ {
+ break; // Not next expected
+ }
+ // already have the header as a param
+ //TCPHeader* h = dynamic_cast<TCPHeader*>(p1->PopPDU());
+ // Check non-null here...
+ uint8_t flags = tcpHeader.GetFlags (); // Flags (used below)
+ if (i->first < m_nextRxSequence)
+ { // remove already delivered data
+ // Two cases here.
+ // 1) seq + length <= nextRxSeq, just discard
+ // 2) seq + length > nextRxSeq, can deliver partial
+ s1 = p->GetSize ();
+ if (i->first + s1 < m_nextRxSequence)
+ { // Just remove from list
+ //bufferedData.erase(i);
+ p1 = 0; // Nothing to deliver
+ }
+ else
+ { // Remove partial data to prepare for delivery
+ uint32_t dup = m_nextRxSequence - i->first;
+ i->second = p1->CreateFragment (0, p1->GetSize () - dup);
+ p1 = i->second;
+ }
+ }
+ else
+ { // At this point i->first must equal nextRxSeq
+ if (i->first != m_nextRxSequence)
+ {
+ NS_FATAL_ERROR ("HuH? NexRx failure, first "
+ << i->first << " nextRxSeq " << m_nextRxSequence);
+ }
+ s1 = p1->GetSize ();
+ }
+ NotifyDataReceived (p1, fromAddress);
+
+ NS_LOG_LOGIC ("TcpSocket " << this << " adv rxseq1 by " << s1 );
+ m_nextRxSequence += s1; // Note data received
+ m_bufferedData.erase (i); // Remove from list
+ if (flags & TcpHeader::FIN)
+ NS_LOG_LOGIC("TcpSocket " << this
+ << " found FIN in buffered");
+ }
+
+ if (m_pendingClose || (origState > ESTABLISHED))
+ { // See if we can close now
+ if (m_bufferedData.empty())
+ {
+ ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress);
+ }
+ }
+ }
+ else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence)
+ { // Need to buffer this one
+ NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () );
+ UnAckData_t::iterator i =
+ m_bufferedData.find (tcpHeader.GetSequenceNumber () );
+ if (i != m_bufferedData.end () )
+ {
+ i->second = 0; // relase reference to already buffered
+ }
+ // Save for later delivery
+ m_bufferedData[tcpHeader.GetSequenceNumber () ] = p;
+ }
+ else
+ { // debug
+ NS_LOG_LOGIC("TCP " << this
+ << " got seq " << tcpHeader.GetSequenceNumber ()
+ << " expected " << m_nextRxSequence
+ << " flags " << tcpHeader.GetFlags ());
+ }
+ // Now send a new ack packet acknowledging all received and delivered data
+ SendEmptyPacket (TcpHeader::ACK);
+}
+
+
+void TcpSocket::CommonNewAck (SequenceNumber ack, bool skipTimer)
+{ // CommonNewAck is called only for "New" (non-duplicate) acks
+ // and MUST be called by any subclass, from the NewAck function
+ // Always cancel any pending re-tx timer on new acknowledgement
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << ack << skipTimer);
+ //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl));
+ if (!skipTimer)
+ {
+ m_retxEvent.Cancel ();
+ }
+ uint32_t numberAck = ack - m_highestRxAck; // Number bytes ack'ed
+ NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack
+ << " numberAck " << numberAck);
+ m_highestRxAck = ack; // Note the highest recieved Ack
+ if (ack > m_nextTxSequence)
+ {
+ m_nextTxSequence = ack; // If advanced
+ }
+ // See if all pending ack'ed; if so we can delete the data
+ if (m_pendingData)
+ { // Data exists, see if can be deleted
+ if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0)
+ { // All pending acked, can be deleted
+ m_pendingData->Clear ();
+ delete m_pendingData;
+ m_pendingData = 0;
+ // Insure no re-tx timer
+ m_retxEvent.Cancel();
+ }
+ }
+ // Try to send more data
+ SendPendingData();
+}
+
+void TcpSocket::NewAck (SequenceNumber seq)
+{ // New acknowledgement up to sequence number "seq"
+ // Adjust congestion window in response to new ack's received
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << seq);
+ NS_LOG_LOGIC ("TcpSocket " << this << " NewAck "
+ << " seq " << seq
+ << " cWnd " << m_cWnd
+ << " ssThresh " << m_ssThresh);
+ if (m_cWnd < m_ssThresh)
+ { // Slow start mode, add one segSize to cWnd
+ m_cWnd += m_segmentSize;
+ NS_LOG_LOGIC ("TcpSocket " << this << " NewCWnd SlowStart, cWnd " << m_cWnd
+ << " sst " << m_ssThresh);
+ }
+ else
+ { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd
+ double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd;
+ if (adder < 1.0)
+ {
+ adder = 1.0;
+ }
+ m_cWnd += (uint32_t) adder;
+ NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd
+ << " sst " << m_ssThresh);
+ }
+ CommonNewAck (seq, false); // Complete newAck processing
+}
+
+void TcpSocket::DupAck (const TcpHeader& t, uint32_t count)
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this << "t " << count);
+ NS_LOG_LOGIC ("TcpSocket " << this << " DupAck " << t.GetAckNumber ()
+ << ", count " << count
+ << ", time " << Simulator::Now ());
+ if (count == 3)
+ { // Count of three indicates triple duplicate ack
+ m_ssThresh = Window () / 2; // Per RFC2581
+ m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+ NS_LOG_LOGIC("TcpSocket " << this << "Tahoe TDA, time " << Simulator::Now ()
+ << " seq " << t.GetAckNumber ()
+ << " in flight " << BytesInFlight ()
+ << " new ssthresh " << m_ssThresh);
+
+ m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart)
+ // For Tahoe, we also reset nextTxSeq
+ m_nextTxSequence = m_highestRxAck;
+ SendPendingData ();
+ }
+}
+
+void TcpSocket::ReTxTimeout ()
+{ // Retransmit timeout
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this);
+ m_ssThresh = Window () / 2; // Per RFC2581
+ m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize);
+ // Set cWnd to segSize on timeout, per rfc2581
+ // Collapse congestion window (re-enter slowstart)
+ m_cWnd = m_segmentSize;
+ m_nextTxSequence = m_highestRxAck; // Start from highest Ack
+ m_rtt->IncreaseMultiplier (); // Double timeout value for next retx timer
+ Retransmit (); // Retransmit the packet
+}
+
+void TcpSocket::LastAckTimeout ()
+{
+ m_lastAckEvent.Cancel ();
+ if (m_state == LAST_ACK)
+ {
+ Actions_t action = ProcessEvent (TIMEOUT);
+ ProcessAction (action);
+ }
+ if (!m_closeNotified)
+ {
+ m_closeNotified = true;
+ }
+}
+
+void TcpSocket::Retransmit ()
+{
+ NS_LOG_FUNCTION;
+ NS_LOG_PARAMS (this);
+ uint8_t flags = TcpHeader::NONE;
+ if (m_state == SYN_SENT)
+ {
+ if (m_cnCount > 0)
+ {
+ SendEmptyPacket (TcpHeader::SYN);
+ return;
+ }
+ else
+ {
+ NotifyConnectionFailed ();
+ return;
+ }
+ }
+ if (!m_pendingData)
+ {
+ if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2)
+ { // Must have lost FIN, re-send
+ SendEmptyPacket (TcpHeader::FIN);
+ }
+ return;
+ }
+ PendingData* d = m_pendingData->CopyFromSeq (m_segmentSize,
+ m_firstPendingSequence,
+ m_highestRxAck);
+ // Calculate remaining data for COE check
+ uint32_t remainingData =
+ m_pendingData->SizeFromSeq (m_firstPendingSequence,
+ m_nextTxSequence + SequenceNumber(d->Size ()));
+ if (m_closeOnEmpty && remainingData == 0)
+ { // Add the FIN flag
+ flags = flags | TcpHeader::FIN;
+ }
+ Ptr<Packet> p = Create<Packet> (d->data, d->Size());
+ NS_LOG_LOGIC ("TcpSocket " << this << " retxing seq " << m_highestRxAck);
+ if (m_retxEvent.IsExpired () )
+ {
+ Time rto = m_rtt->RetransmitTimeout ();
+ NS_LOG_LOGIC ("Schedule retransmission timeout at time "
+ << Simulator::Now ().GetSeconds () << " to expire at time "
+ << (Simulator::Now () + rto).GetSeconds ());
+ m_retxEvent = Simulator::Schedule (rto,&TcpSocket::ReTxTimeout,this);
+ }
+ m_rtt->SentSeq (m_highestRxAck,d->Size ());
+ // And send the packet
+ TcpHeader tcpHeader;
+ tcpHeader.SetSequenceNumber (m_nextTxSequence);
+ tcpHeader.SetAckNumber (m_nextRxSequence);
+ tcpHeader.SetSourcePort (m_endPoint->GetLocalPort());
+ tcpHeader.SetDestinationPort (m_defaultPort);
+ tcpHeader.SetFlags (flags);
+ tcpHeader.SetWindowSize (m_advertisedWindowSize);
+
+ m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
+ m_defaultAddress);
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-socket.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_SOCKET_H
+#define TCP_SOCKET_H
+
+#include <stdint.h>
+#include "ns3/callback.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/event-id.h"
+#include "tcp-typedefs.h"
+#include "pending-data.h"
+#include "sequence-number.h"
+#include "rtt-estimator.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class TcpL4Protocol;
+class TcpHeader;
+
+class TcpSocket : public Socket
+{
+public:
+ /**
+ * Create an unbound tcp socket.
+ */
+ TcpSocket (Ptr<Node> node, Ptr<TcpL4Protocol> tcp);
+ virtual ~TcpSocket ();
+
+ virtual enum SocketErrno GetErrno (void) const;
+ virtual Ptr<Node> GetNode (void) const;
+ virtual int Bind (void);
+ virtual int Bind (const Address &address);
+ virtual int Close (void);
+ virtual int ShutdownSend (void);
+ virtual int ShutdownRecv (void);
+ virtual int Connect(const Address &address);
+ virtual int Send (Ptr<Packet> p);
+ virtual int Send (const uint8_t* buf, uint32_t size);
+ virtual int SendTo(const Address &address, Ptr<Packet> p);
+ virtual int Listen(uint32_t queueLimit);
+
+private:
+ friend class Tcp;
+ // invoked by Tcp class
+ int FinishBind (void);
+ void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
+ void Destroy (void);
+ int DoSendTo (Ptr<Packet> p, const Address &daddr);
+ int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+ void SendEmptyPacket(uint8_t flags);
+ //methods for state
+ bool ProcessAction (Actions_t a);
+ bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader,
+ Ipv4Address saddr, Ipv4Address daddr);
+ bool ProcessPacketAction (Actions_t a, Ptr<Packet> p,
+ const TcpHeader& tcpHeader,
+ const Address& fromAddress);
+ Actions_t ProcessEvent (Events_t e);
+ bool SendPendingData(bool withAck = false);
+
+ //methods for window management
+ virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes
+ virtual uint32_t BytesInFlight(); // Return total bytes in flight
+ virtual uint32_t Window(); // Return window size (integer)
+ virtual uint32_t AvailableWindow();// Return unfilled portion of window
+
+ // Manage data tx/rx
+ void NewRx (Ptr<Packet>, const TcpHeader&, const Address&);
+ // XXX This should be virtual and overridden
+ void NewAck (SequenceNumber seq);
+ // XXX This should be virtual and overridden
+ void DupAck (const TcpHeader& t, uint32_t count);
+ void ReTxTimeout ();
+ void LastAckTimeout ();
+ void Retransmit ();
+ void CommonNewAck (SequenceNumber seq, bool skipTimer = false);
+
+ bool m_skipRetxResched;
+ uint32_t m_dupAckCount;
+ EventId m_retxEvent;
+ EventId m_lastAckEvent;
+
+ Ipv4EndPoint *m_endPoint;
+ Ptr<Node> m_node;
+ Ptr<TcpL4Protocol> m_tcp;
+ Ipv4Address m_defaultAddress;
+ uint16_t m_defaultPort;
+ Callback<void, Ptr<Socket>, uint32_t, const Address &> m_dummyRxCallback;
+ Callback<void, Ptr<Socket>, uint8_t const*, uint32_t, const Address &>
+ m_rxCallback;
+ enum SocketErrno m_errno;
+ bool m_shutdownSend;
+ bool m_shutdownRecv;
+ bool m_connected;
+
+ //manage the state infomation
+ States_t m_state;
+ bool m_closeNotified;
+ bool m_closeRequestNotified;
+ bool m_closeOnEmpty;
+ bool m_pendingClose;
+
+
+ //sequence info, sender side
+ SequenceNumber m_nextTxSequence;
+ SequenceNumber m_highTxMark;
+ SequenceNumber m_highestRxAck;
+ SequenceNumber m_lastRxAck;
+
+ //sequence info, reciever side
+ SequenceNumber m_nextRxSequence;
+ SequenceNumber m_nextAckSequence;
+
+ //history data
+ UnAckData_t m_bufferedData;
+ PendingData* m_pendingData;
+ SequenceNumber m_firstPendingSequence;
+
+ // Window management
+ uint32_t m_segmentSize; // SegmentSize
+ uint32_t m_rxWindowSize;
+ uint32_t m_advertisedWindowSize; // Window to advertise to peer
+ uint32_t m_cWnd; // Congestion window
+ uint32_t m_ssThresh; // Slow Start Threshold
+ uint32_t m_initialCWnd; // Initial (and reset) value for cWnd
+
+ // Round trip time estimation
+ Ptr<RttEstimator> m_rtt;
+ Time m_lastMeasuredRtt;
+
+ // Timer-related members
+ Time m_cnTimeout;
+ uint32_t m_cnCount;
+
+};
+
+}//namespace ns3
+
+#endif /* UDP_SOCKET_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/tcp-typedefs.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ * typedefs for tcp state machine
+ */
+
+#include <vector>
+#include <map>
+#include "sequence-number.h"
+
+#ifndef TCP_TYPEDEFS_H
+#define TCP_TYPEDEFS_H
+
+namespace ns3 {
+
+typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t; // Flags are 6 bits
+
+typedef enum {
+ CLOSED, // 0
+ LISTEN, // 1
+ SYN_SENT, // 2
+ SYN_RCVD, // 3
+ ESTABLISHED, // 4
+ CLOSE_WAIT, // 5
+ LAST_ACK, // 6
+ FIN_WAIT_1, // 7
+ FIN_WAIT_2, // 8
+ CLOSING, // 9
+ TIMED_WAIT, // 10
+ LAST_STATE } States_t;
+
+typedef enum {
+ APP_LISTEN, // 0
+ APP_CONNECT, // 1
+ APP_SEND, // 2
+ SEQ_RECV, // 3
+ APP_CLOSE, // 4
+ TIMEOUT, // 5
+ ACK_RX, // 6
+ SYN_RX, // 7
+ SYN_ACK_RX, // 8
+ FIN_RX, // 9
+ FIN_ACK_RX, // 10
+ RST_RX, // 11
+ BAD_FLAGS, // 12
+ LAST_EVENT } Events_t;
+
+typedef enum {
+ NO_ACT, // 0
+ ACK_TX, // 1
+ ACK_TX_1, // ACK response to syn
+ RST_TX, // 2
+ SYN_TX, // 3
+ SYN_ACK_TX, // 4
+ FIN_TX, // 5
+ FIN_ACK_TX, // 6
+ NEW_ACK, // 7
+ NEW_SEQ_RX, // 8
+ RETX, // 9
+ TX_DATA, // 10
+ PEER_CLOSE, // 11
+ APP_CLOSED, // 12
+ CANCEL_TM, // 13
+ APP_NOTIFY, // 14 - Notify app that connection failed
+ SERV_NOTIFY, // 15 - Notify server tcp that connection completed
+ LAST_ACTION } Actions_t;
+
+class SA // State/Action pair
+{
+public:
+ SA () : state (LAST_STATE), action (LAST_ACTION) { }
+ SA (States_t s, Actions_t a) : state (s), action (a) { }
+public:
+ States_t state;
+ Actions_t action;
+};
+typedef std::vector<SA> StateActionVec_t;
+typedef std::vector<StateActionVec_t> StateActions_t; // One per current state
+typedef std::vector<Events_t> EventVec_t; // For flag events lookup
+
+//type for managing buffered out of sequence data
+typedef std::map<SequenceNumber, Ptr<Packet> > UnAckData_t;
+
+class TcpStateMachine {
+ public:
+ TcpStateMachine ();
+ SA Lookup (States_t, Events_t);
+ Events_t FlagsEvent (uint8_t); // Lookup event from flags
+
+ public:
+ StateActions_t aT; // Action table
+ EventVec_t eV; // Flags event lookup
+};
+
+}//namespace ns3
+#endif //TCP_TYPEDEFS_H
--- a/src/internet-node/wscript Sat Jan 19 21:03:18 2008 -0800
+++ b/src/internet-node/wscript Fri Jan 25 13:57:38 2008 -0500
@@ -9,23 +9,30 @@
'ipv4-l4-protocol.cc',
'ipv4-header.cc',
'udp-header.cc',
+ 'tcp-header.cc',
'ipv4-checksum.cc',
'ipv4-interface.cc',
'ipv4-l3-protocol.cc',
'ipv4-static-routing.cc',
'ipv4-end-point.cc',
'udp-l4-protocol.cc',
+ 'tcp-l4-protocol.cc',
'arp-header.cc',
'arp-cache.cc',
'arp-ipv4-interface.cc',
'arp-l3-protocol.cc',
'ipv4-loopback-interface.cc',
'udp-socket.cc',
+ 'tcp-socket.cc',
'ipv4-end-point-demux.cc',
'ipv4-impl.cc',
'ascii-trace.cc',
'pcap-trace.cc',
'udp-impl.cc',
+ 'tcp-impl.cc',
+ 'pending-data.cc',
+ 'sequence-number.cc',
+ 'rtt-estimator.cc',
]
headers = bld.create_obj('ns3header')
@@ -35,4 +42,5 @@
'pcap-trace.h',
'ipv4-header.h',
'udp-header.h',
+ 'tcp-header.h',
]
--- a/src/node/socket.cc Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/socket.cc Fri Jan 25 13:57:38 2008 -0500
@@ -108,6 +108,12 @@
return SendTo (address,p);
}
+int Socket::Listen(uint32_t queueLimit)
+{
+ return 0; //XXX the base class version does nothing
+}
+
+
void
Socket::NotifyCloseCompleted (void)
{
--- a/src/node/socket.h Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/socket.h Fri Jan 25 13:57:38 2008 -0500
@@ -197,6 +197,13 @@
virtual int SendTo(const Address &address,Ptr<Packet> p) = 0;
/**
+ * \brief Listen for incoming connections.
+ * \param queueLimit maximum number of incoming request to queue
+ * \returns XXX an error code
+ */
+ virtual int Listen(uint32_t queueLimit);
+
+ /**
* \brief Send data to a specified peer.
* \param address IP Address of remote host
* \param buf A pointer to a raw byte buffer of some data to send. If this
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp.cc Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#include "tcp.h"
+
+namespace ns3 {
+
+NumericDefaultValue<uint32_t> Tcp::defaultSegSize
+("TcpDefaultSegmentSize",
+"Default TCP maximum segment size in bytes (may be adjusted based on MTU discovery)",
+536);
+
+NumericDefaultValue<uint32_t> Tcp::defaultAdvWin
+("TcpDefaultAdvertisedWindowSize",
+"Default TCP advertised window size (bytes)",
+0xffff);
+
+NumericDefaultValue<uint32_t> Tcp::defaultSSThresh
+("TcpDefaultSlowStartThreshold",
+"Default TCP slow start threshold (bytes)",
+0xffff);
+
+NumericDefaultValue<uint32_t> Tcp::defaultTxBuffer
+("TcpDefaultTxBufferSize",
+"Default TCP maximum transmit buffer size (bytes)",
+0xffffffffl);
+
+NumericDefaultValue<uint32_t> Tcp::defaultRxBuffer
+("TcpDefaultRxBufferSize",
+"Default TCP maximum receive buffer size (bytes)",
+0xffffffffl);
+
+NumericDefaultValue<uint32_t> Tcp::defaultInitialCWnd
+("TcpDefaultInitialCongestionWindowSize",
+"Default TCP initial congestion window size (segments)",
+1);
+
+NumericDefaultValue<uint32_t> Tcp::defaultConnTimeout
+("TcpDefaultConnTimeout",
+"Default TCP retransmission timeout when opening connection (seconds)",
+6);
+
+NumericDefaultValue<uint32_t> Tcp::defaultConnCount
+("TcpDefaultConnCount",
+"Default number of connection attempts (SYN retransmissions) before returning failure",
+3);
+
+const InterfaceId Tcp::iid = MakeInterfaceId ("Tcp", SocketFactory::iid);
+
+Tcp::Tcp ()
+{
+ SetInterfaceId (Tcp::iid);
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/tcp.h Fri Jan 25 13:57:38 2008 -0500
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ *
+ * 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: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+#ifndef TCP_H
+#define TCP_H
+
+#include "ns3/default-value.h"
+#include "socket-factory.h"
+
+namespace ns3 {
+
+class Socket;
+
+/**
+ * \brief API to create TCP socket instances
+ *
+ * This abstract class defines the API for TCP sockets.
+ * This class also holds the global default variables used to
+ * initialize newly created sockets, such as values that are
+ * set through the sysctl or proc interfaces in Linux.
+
+ * All TCP implementations must provide an implementation of CreateSocket
+ * below, and should make use of the default values configured below.
+ *
+ * \see TcpImpl
+ *
+ */
+class Tcp : public SocketFactory
+{
+public:
+ static const InterfaceId iid;
+
+ Tcp ();
+
+ virtual Ptr<Socket> CreateSocket (void) = 0;
+
+public:
+ static NumericDefaultValue<uint32_t> defaultSegSize;
+ static NumericDefaultValue<uint32_t> defaultAdvWin;
+ static NumericDefaultValue<uint32_t> defaultSSThresh;
+ static NumericDefaultValue<uint32_t> defaultTxBuffer;
+ static NumericDefaultValue<uint32_t> defaultRxBuffer;
+ static NumericDefaultValue<uint32_t> defaultInitialCWnd;
+ static NumericDefaultValue<uint32_t> defaultConnTimeout;
+ static NumericDefaultValue<uint32_t> defaultConnCount;
+
+};
+
+} // namespace ns3
+
+#endif /* UDP_H */
--- a/src/node/wscript Sat Jan 19 21:03:18 2008 -0800
+++ b/src/node/wscript Fri Jan 25 13:57:38 2008 -0500
@@ -25,6 +25,7 @@
'packet-socket-factory.cc',
'packet-socket.cc',
'udp.cc',
+ 'tcp.cc',
'ipv4.cc',
'application.cc',
]
@@ -52,6 +53,7 @@
'socket-factory.h',
'packet-socket-factory.h',
'udp.h',
+ 'tcp.h',
'ipv4.h',
'application.h',
]