Multiple TCP sockets - writing traces to files

177 views
Skip to first unread message

Mahesh

unread,
Apr 10, 2018, 1:22:03 AM4/10/18
to ns-3-users
Hi all,

So I am opening multiple TCP sockets and running applications on them (similar to fifth.cc tutorial). I am trying to trace various TCP stats like CWND, RTT, RTO etc. I'm writing the results to separate files for each node. However, only the last node's data is being written to the files. Files corresponding to other nodes are empty.

Attached is the part of code which is relevant to my problem. Kindly direct me where I'm going wrong.

ApplicationContainer ac_sinkTcp[m_numSources];              // m_numSources is the number of sources
ApplicationContainer sourceApp[m_numSources];

int source_nodes[m_numSources] = {0, 1, 2};
int dest_interfaces[m_numSources] = {3, 7, 11};

Ptr<Socket> ns3TcpSocket[m_numSources];
Ptr<TestApp> app[m_numSources];
Address sinkAddress[m_numSources];

for (int i = 0; i < m_numSources; i++)
{
 
if (i == 0)
    ac_sinkTcp
[i] = sinkTcp0.Install (nc_wireless.Get(12));

 
if (i == 1)
    ac_sinkTcp
[i] = sinkTcp1.Install (nc_wireless.Get(12));

 
if (i == 2)
    ac_sinkTcp
[i] = sinkTcp2.Install (nc_wireless.Get(12));

  ac_sinkTcp
[i].Start (Seconds (0.1 + i * 0.1));
  ac_sinkTcp
[i].Stop (Seconds (m_totalTime));

  ns3TcpSocket
[i] = Socket::CreateSocket(nc_wireless.Get(source_nodes[i]), TcpSocketFactory::GetTypeId());
  sinkAddress
[i] = InetSocketAddress (if_wireless.GetAddress (dest_interfaces[i]), i+9);
  app
[i] = CreateObject<TestApp> ();
  app
[i]->Setup(ns3TcpSocket[i], sinkAddress[i], 1448, 5000, DataRate (m_txAppRate));
  nc_wireless
.Get(source_nodes[i])->AddApplication(app[i]);
  app
[i]->SetStartTime(Seconds(0.5 + i * 0.1));
  app
[i]->SetStopTime(Seconds(m_totalTime));

 
if(CwndTracerEnable)
 
{
     
AsciiTraceHelper ascii;
      std
::string filename = "cwnd-" + std::to_string(i) + ".data";
      cWndStream
= ascii.CreateFileStream (filename);
      ns3TcpSocket
[i]->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));
 
}
}


For m_numSources = 3, cwnd-0.data, cwnd-1.data and cwnd-2.data are being created. But only cwnd-2.data file has congestion window values. The other two files are empty. Why is it happening?

Thanks,
Mahesh

Rediet

unread,
Apr 10, 2018, 2:29:28 AM4/10/18
to ns-3-users
Hello,

It seems that you only have one cWndStream stream. You'll end up overwriting the callbacks. Try using a vector.

Rediet

Mahesh

unread,
Apr 10, 2018, 10:47:08 AM4/10/18
to ns-3-users
I am unable to create a vector for Ptr<OutputStreamWrapper> cWndStream. I have this snippet of code:

static void
CwndTracer (uint32_t oldval, uint32_t newval)
{
 
if (firstCwnd)
   
{
     
*cWndStream->GetStream () << "0.0 " << oldval << std::endl;
      firstCwnd
= false;
   
}
 
*cWndStream->GetStream () << Simulator::Now ().GetSeconds () << " " << newval << std::endl;
  cWndValue
= newval;

 
if (!firstSshThr)
   
{
     
*ssThreshStream->GetStream () << Simulator::Now ().GetSeconds () << " " << ssThreshValue << std::endl;
   
}
}

The following code calls the above function:
if(CwndTracerEnable)
     
{
         
AsciiTraceHelper ascii;
          std
::string filename = "/home/mahesh/ns3/ns-allinone-3.26/ns-3.26/test-output/cwnd-" + std::to_string(i) + ".data";
         
//cWndStream = ascii.CreateFileStream ("/home/mahesh/ns3/ns-allinone-3.26/ns-3.26/test-output/cwnd.data");

          cWndStream
= ascii.CreateFileStream (filename);
          ns3TcpSocket
[i]->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndTracer));
     
}

How do I pass the value of index variable "i" to the MakeCallback and access it in the CwndTracer function so that there is cWndStream for each source? I can't find a way.

Thanks,
Mahesh

Mahesh

unread,
Apr 11, 2018, 5:59:09 AM4/11/18
to ns-3-users
Hi all,

So I used MakeBoundCallback to pass the index variable "i" to CwndTracer function. However, it is giving a segmentation fault with the following error:
Program received signal SIGSEGV, Segmentation fault.
0x00007fffeca6d5d9 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6

Can you please let me know where I am going wrong. Have attached my script. Relevant lines are from 53 to 100 and 827 to 838.

Also, I had a side query: when I use the following line of code:
app[i]->Setup(ns3TcpSocket[i], sinkAddress[i], 1448, 10000, DataRate (m_txAppRate));

10000 packets are not sent from source to destination, even if I run the simulation for long time. Around less than half of 10000 packets are sent. Why is this so? Please guide.

Thanks,
Mahesh
my-script.cc

pdbarnes

unread,
Apr 12, 2018, 3:57:08 PM4/12/18
to ns-3-users
Hello Mahesh,

Please post to the users' list (rather than sending private emails) so others can learn from the discussion.

I'm not an expert on tracing, but after a quick look at your code I suggest you try using Config::ConnectWithContext(). IIRC your various tracing functions will need a new argument to pass the context, which will tell you which node is invoking the Callback. To get that to work you'll have to hook the actual trace sources, rather than scheduling a global function. Your global function isn't associated with a Node, so has no context, whereas the trace sources do.

Peter

On Apr 12, 2018, at 6:01 AM, Mahesh wrote:
Hello Peter,
I'm tracing TCP stats like CWND, RTT etc. In my scenario, I am varying the number of sources from nodes 1 to 24 except for node 12 which is the sink. Static routing is being used.
There are 3 flows in the code:
Flow 1: Node 0 to Node 12
Flow 2: Node 1 to Node 12
Flow 3: Node 2 to Node 12
I have to capture the TCP traces for each of these 3 flows. Only one flow's traces are being written to files. I know I have to make use of vectors but I don't know how to proceed.
Please help me out. Expecting your kind reply at the earliest.
Thanks,
Mahesh
<test.cc>
Reply all
Reply to author
Forward
0 new messages