Added in ns-3-tcp (second try)
This commit is contained in:
240
examples/tcp-large-transfer-errors.cc
Normal file
240
examples/tcp-large-transfer-errors.cc
Normal file
@@ -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 ();
|
||||
}
|
||||
225
examples/tcp-large-transfer.cc
Normal file
225
examples/tcp-large-transfer.cc
Normal file
@@ -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 ();
|
||||
}
|
||||
191
examples/tcp-nonlistening-server.cc
Normal file
191
examples/tcp-nonlistening-server.cc
Normal file
@@ -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 ();
|
||||
}
|
||||
222
examples/tcp-small-transfer-oneloss.cc
Normal file
222
examples/tcp-small-transfer-oneloss.cc
Normal file
@@ -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 ();
|
||||
}
|
||||
217
examples/tcp-small-transfer.cc
Normal file
217
examples/tcp-small-transfer.cc
Normal file
@@ -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 ();
|
||||
}
|
||||
@@ -45,3 +45,25 @@ def build(bld):
|
||||
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'
|
||||
|
||||
|
||||
|
||||
@@ -78,9 +78,14 @@ void PacketSink::StartApplication() // Called at time specified by Start
|
||||
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 @@ void PacketSink::Receive(Ptr<Socket> socket, Ptr<Packet> packet,
|
||||
m_rxTrace (packet, from);
|
||||
}
|
||||
|
||||
void PacketSink::CloseConnection (Ptr<Socket> socket)
|
||||
{
|
||||
socket->Close ();
|
||||
}
|
||||
|
||||
Ptr<TraceResolver>
|
||||
PacketSink::GetTraceResolver (void) const
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ private:
|
||||
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
|
||||
|
||||
@@ -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 @@ InternetNode::Construct (void)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
222
src/internet-node/pending-data.cc
Normal file
222
src/internet-node/pending-data.cc
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
73
src/internet-node/pending-data.h
Normal file
73
src/internet-node/pending-data.h
Normal file
@@ -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
|
||||
|
||||
233
src/internet-node/rtt-estimator.cc
Normal file
233
src/internet-node/rtt-estimator.cc
Normal file
@@ -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
|
||||
131
src/internet-node/rtt-estimator.h
Normal file
131
src/internet-node/rtt-estimator.h
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
66
src/internet-node/sequence-number.cc
Normal file
66
src/internet-node/sequence-number.cc
Normal file
@@ -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
|
||||
}
|
||||
|
||||
67
src/internet-node/sequence-number.h
Normal file
67
src/internet-node/sequence-number.h
Normal file
@@ -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
|
||||
|
||||
|
||||
187
src/internet-node/tcp-header.cc
Normal file
187
src/internet-node/tcp-header.cc
Normal file
@@ -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
|
||||
161
src/internet-node/tcp-header.h
Normal file
161
src/internet-node/tcp-header.h
Normal file
@@ -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 */
|
||||
48
src/internet-node/tcp-impl.cc
Normal file
48
src/internet-node/tcp-impl.cc
Normal file
@@ -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
|
||||
58
src/internet-node/tcp-impl.h
Normal file
58
src/internet-node/tcp-impl.h
Normal file
@@ -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 */
|
||||
485
src/internet-node/tcp-l4-protocol.cc
Normal file
485
src/internet-node/tcp-l4-protocol.cc
Normal file
@@ -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
|
||||
|
||||
111
src/internet-node/tcp-l4-protocol.h
Normal file
111
src/internet-node/tcp-l4-protocol.h
Normal file
@@ -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 */
|
||||
1077
src/internet-node/tcp-socket.cc
Normal file
1077
src/internet-node/tcp-socket.cc
Normal file
File diff suppressed because it is too large
Load Diff
161
src/internet-node/tcp-socket.h
Normal file
161
src/internet-node/tcp-socket.h
Normal file
@@ -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 */
|
||||
111
src/internet-node/tcp-typedefs.h
Normal file
111
src/internet-node/tcp-typedefs.h
Normal file
@@ -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
|
||||
@@ -9,23 +9,30 @@ def build(bld):
|
||||
'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 @@ def build(bld):
|
||||
'pcap-trace.h',
|
||||
'ipv4-header.h',
|
||||
'udp-header.h',
|
||||
'tcp-header.h',
|
||||
]
|
||||
|
||||
@@ -108,6 +108,12 @@ int Socket::SendTo (const Address &address, const uint8_t* buf, uint32_t size)
|
||||
return SendTo (address,p);
|
||||
}
|
||||
|
||||
int Socket::Listen(uint32_t queueLimit)
|
||||
{
|
||||
return 0; //XXX the base class version does nothing
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Socket::NotifyCloseCompleted (void)
|
||||
{
|
||||
|
||||
@@ -196,6 +196,13 @@ public:
|
||||
*/
|
||||
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
|
||||
|
||||
71
src/node/tcp.cc
Normal file
71
src/node/tcp.cc
Normal file
@@ -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
|
||||
67
src/node/tcp.h
Normal file
67
src/node/tcp.h
Normal file
@@ -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 */
|
||||
@@ -25,6 +25,7 @@ def build(bld):
|
||||
'packet-socket-factory.cc',
|
||||
'packet-socket.cc',
|
||||
'udp.cc',
|
||||
'tcp.cc',
|
||||
'ipv4.cc',
|
||||
'application.cc',
|
||||
]
|
||||
@@ -52,6 +53,7 @@ def build(bld):
|
||||
'socket-factory.h',
|
||||
'packet-socket-factory.h',
|
||||
'udp.h',
|
||||
'tcp.h',
|
||||
'ipv4.h',
|
||||
'application.h',
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user