The code given below is based on the examples/tcp/tcp-large-
transfer.cc file in ns-3.7 tree. I am using this code to study the
evolution of the congestion window. The congestion window size is
dumped when the NS_LOG is set to tcp-unsat and the lines containing
internet.SetTcp are commented. However, if I un-comment one of the two
SetTcp commands then I am unable to see the congestion window.
I would like to know the way in which I can monitor the congestion
window when the ns3::NscTcpL4Protocol library is liblinux2.6.26.so.
Regards,
Ashwin
-------------
#include "ns3/core-module.h"
#include "ns3/helper-module.h"
#include "ns3/node-module.h"
#include "ns3/simulator-module.h"
// N0 ------link--------- N1
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("tcp-unsat");
// The number of bytes to send in this simulation.
static const uint32_t totalTxBytes = 1024*100; // 100 kB file transfer
static uint32_t currentTxBytes = 0;
static const uint32_t writeSize = 1024; // 1 kB
uint8_t data[writeSize];
void StartFlow(Ptr<Socket>, Ipv4Address, uint16_t);
void WriteBuffer (Ptr<Socket>);
static void CwndTracer (uint32_t oldval, uint32_t newval);
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
int servPort = 11000;
int maxStopTime = 100;
// Here, we will explicitly create two nodes. The container
contains
// nodes 0 and 1 from the diagram above.
// This reflects the channel connectivity, and will be used to
// install the network interfaces and connect them with a channel.
NodeContainer n0n1;
n0n1.Create (2);
// We create the channels first without any IP addressing
information
// First make and configure the helper, so that it will put the
appropriate
// attributes on the network interfaces and channels we are about to
install
PointToPointHelper p2p;
p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate
(10000000))); // infinity for 10 kB/s
p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(5))); //
negligible latency
// And then install devices and channels connecting our topology.
NetDeviceContainer dev0 = p2p.Install (n0n1);
// Now add ip/tcp stack to all nodes.
InternetStackHelper internet;
// internet.SetTcp ("ns3::NscTcpL4Protocol","Library", StringValue
("liblinux2.6.26.so"));
// internet.SetTcp ("ns3::NscTcpL4Protocol","Library", StringValue
("liblinux2.6.18.so"));
internet.InstallAll ();
// Add IP addresses and assign it to devices in container dev0
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer ipInterfs = ipv4.Assign (dev0);
// and setup ip routing tables to get total ip-level connectivity.
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
// Create a packet sink to receive these packets on n1...
PacketSinkHelper sink ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (),
servPort));
ApplicationContainer apps = sink.Install (n0n1.Get (1));
apps.Start (Seconds (0.0));
apps.Stop (Seconds (maxStopTime + 3.0));
// Create a source to send packets from n0.
Ptr<Socket> localSocket =
Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId
());
localSocket->Bind ();
Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/
SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
Simulator::ScheduleNow (&StartFlow, localSocket,
ipInterfs.GetAddress (1), servPort);
// Traces for the simulation. Support of ns2 type ascii and pcap
traces.
std::ofstream ascii;
ascii.open ("tcp-unsat.tr");
PointToPointHelper::EnableAsciiAll (ascii);
PointToPointHelper::EnablePcapAll ("tcp-unsat");
/// Stop after 100 seconds
Simulator::Stop (Seconds(maxStopTime));
Simulator::Run ();
Simulator::Destroy ();
}
static void
CwndTracer (uint32_t oldval, uint32_t newval)
{
NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
}
void
StartFlow(Ptr<Socket> localSocket, Ipv4Address servAddress,
uint16_t servPort)
{
NS_LOG_LOGIC("Starting flow at time " << Simulator::Now
().GetSeconds ());
localSocket->Connect (InetSocketAddress (servAddress, servPort));//
connect
// tell the tcp implementation to call WriteUntilBufferFull again
// if no buffer space available, the WriteUntilBufferFull function
// returns and waits till it is called again
// An event based approach, rather than polling tcp periodically
WriteBuffer (localSocket);
}
void
WriteBuffer (Ptr<Socket> localSocket)
{
// unsaturated behavior
int amountSent = localSocket->Send (data, writeSize, 0);
if (amountSent >= 0)
{
currentTxBytes += amountSent;
}
if (currentTxBytes <= totalTxBytes)
{
NS_LOG_INFO ("Transmit " << amountSent << " " <<
currentTxBytes);
Simulator::Schedule (Seconds (0.1), &WriteBuffer, localSocket);
return;
}
localSocket->Close ();
return;
}
You presently cannot, and I don't know what kind of surgery to NSC would
be needed to support tracing such as that. the variable tp->snd_cwnd
in linux (NSC) is not exposed to ns-3.
As Tom pointed out, you cannot trace the TCP sending window if you're
using NSC. I had the same problem a few months ago and with the help
of Mathieu Lacage, Florian Westphal and Sam Jansen, I was able to find
the following solution: modify SoftInterrupt in
nsc-tcp-l4-protocol.cc so that it polls all the NSC TCP sockets and it
updates some state variable (including the sending window). NSC
already has a function (UpdateTcpVars or something like that) that can
be used to obtain the value of several TCP variables. The
SoftInterrupt is scheduled x times per second, where x depends on the
value of the variable hz so this solution checks the value of these
variable x times per second (if I recall correctly hz is set to 1000).
For my purposes this is more than enough.
Be warned that if you're using NSC and TCP there is another issue as
the SendCallback does not work. See bug 708
http://www.nsnam.org/bugzilla/show_bug.cgi?id=708 FYI I've been using
the solution described in comment #2 and it seems to be working OK.