Tracing Cwnd inside the Application

921 views
Skip to first unread message

Oileca

unread,
Jul 26, 2009, 8:02:25 PM7/26/09
to ns-3-users
Hello, can someone help me how to trace the congestion window of a
socket in a class of application?

I can view the trace when the socket is instantiated inside the main
method (based on example tcp-large-transfer.cc), but I can't if the
socket is instantiated inside the class of my application. The socket
is an attribute of my class of application.

Example:

class Ap : public Application
{
public:
Ap();
Ptr<Socket> socket;
...

void Ap::StartApplication (void)
{
socket = Socket::CreateSocket (no, tid);
...
socket->Connect (ip, port);
...
}

...
}


static void CwndTracer (uint32_t oldval, uint32_t newval)
{
std::cout << "oldval - newval" << std::endl;
}

int main (int argc, char *argv[])
{
...
//I'm using:

Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/
$ns3::TcpL4Protocol/SocketList/*/CongestionWindow", MakeCallback
(&CwndTracer));

//What the problem ?
...
}


Thanks! =)

cra...@ee.washington.edu

unread,
Jul 26, 2009, 9:01:05 PM7/26/09
to ns-3-...@googlegroups.com

> Hello, can someone help me how to trace the congestion window of a
> socket in a class of application?
>
> I can view the trace when the socket is instantiated inside the main
> method (based on example tcp-large-transfer.cc), but I can't if the
> socket is instantiated inside the class of my application. The socket
> is an attribute of my class of application.

It will probably help to explain how the config connect in
tcp-large-transfer works. There you will find the call,

Config::ConnectWithoutContext (
"/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
MakeCallback (&CwndTracer));

The config path provided is parsed by stepping through each segment of that
path and performing an action defined by the segment.

1) The node-list code registers the NodeListPriv object as a root namespace
with a "NodeList" attribute. This attribute turns out to be a vector of
Object, so when the parser sees "/NodeList/0" it translates this into an
Object Ptr. This Object is really a Ptr<Node>.

2) The next segment begins with a "$" so a GetObject is performed on the
specified Object by TypeId. The code for this operation does something
equivalent to,

TypeId tid = TypeId::LookupByName ("ns3::TcpL4Protocol");
Ptr<Object> object = root->GetObject<Object> (tid);

The string "ns3::TcpL4Protocol" is used to find the type-id of the
corresponding concrete class and a GetObject is done on the Ptr<Node> to
find the TCP L4 Protocol object that was previously aggregated to the node.
See src/core/config.cc:356 for the real code.

3) The parser now has a Ptr<TcpL4Protocol> that it is working with. The
next segment is an attribute called "SocketList" so you can look in
src/internet-stack/tcp-l4-protocol.cc and find the attribute at line 340.
In the same way that "NodeList/0" referred to the zeroth Ptr<Node>,
"SocketList/0" refers to the zeroth TcpSocketImpl in the list of sockets
held in the TcpL4Protocol. At this point, the parser has a
Ptr<TcpSocketImpl> which points to the zeroth socket in the TcpL4Protocol
object aggregated to the zeroth node in the NodeList.

4) The next segment in the path is the attribute "CongestionWindow" so if
you look in src/internet-stack/tcp-socket-impl.cc you will find this
attribute at line 53.

So you have got to understand how you are referencing the congestion window
attribute through a chain of pointers and attributes that exist in the
running topology in order to understand how to create a path.

>
> Example:
>
> class Ap : public Application
> {
> public:
> Ap();
> Ptr<Socket> socket;
> ...
>
> void Ap::StartApplication (void)
> {
> socket = Socket::CreateSocket (no, tid);
> ...
> socket->Connect (ip, port);
> ...
> }
>
> ...
> }
>

[ ... ]


> Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/
> $ns3::TcpL4Protocol/SocketList/*/CongestionWindow", MakeCallback
> (&CwndTracer));
>
> //What the problem ?

Step through the config path segment by segment and think about what is
being asked ...

You are looking for "/NodeList/*" which will match all Ptr<Object> in the
node list. Good so far.

You are then looking for the "ApplicationList/*" Attribute which will match
all of the applications on all of the nodes. Note that these are going to
be Ptr<Application>.

Then you tell the config parser to look for "$ns3::TcpL4Protocol" which
translates into a GetObject on each Ptr<Application> looking for an
aggregated TcpL4Protocol. This cannot succeed since the TcpL4Protocol
objects are aggregated to Nodes not Applications.

That is your problem.

I believe you can use the same config path as was used in tcp-large-transfer
since the list of TCP sockets is known to the TcpL4Protocol independent of
which piece of code creates the sockets. For example,

Config::ConnectWithoutContext (
"/NodeList/*/$ns3::TcpL4Protocol/SocketList/*/CongestionWindow",
MakeCallback (&CwndTracer));

should connect all congestion change events of all TCP sockets to CwndTracer
even if you create the sockets in an Application. You will have problems
deciphering which event comes from where unless you ask for a context or
only connect to a specific socket.

You could alternatively make the socket in your Application into an
Attribute itself, say "MyAppsSocket", and then access it through the
ApplicationList,

Config::ConnectWithoutContext (
"/NodeList/*/ApplicationList/*/$ns3::Ap/MyAppsSocket/CongestionWindow",
MakeCallback (&CwndTracer));

There are a number of ways to make this work. The easiest is probably just
to figure out which node and which socket you are interested in and do
something like,

Config::ConnectWithoutContext (
"/NodeList/<the right number>/$ns3::TcpL4Protocol/SocketList/<the right
number>/CongestionWindow",
MakeCallback (&CwndTracer));

With <the right number> hardcoded according to the node number and socket
number you're interested in. Less hack-ful solutions require more work.

Regards,

-- Craig


Acélio

unread,
Jul 27, 2009, 8:59:26 PM7/27/09
to ns-3-users

Craig, thank you very much.

I tried all suggestions, but had no success.


> You could alternatively make the socket in your Application into an
> Attribute itself, say "MyAppsSocket", and then access it through the
> ApplicationList,
>
>   Config::ConnectWithoutContext (
>     "/NodeList/*/ApplicationList/*/$ns3::Ap/MyAppsSocket/CongestionWindow",
>     MakeCallback (&CwndTracer));
>

That your suggestion seems to apply exactly the case of my
application.
I made several attempts, the only difference that I have is that the
socket of my application is of type Ptr<Socket> and not
Ptr<TcpSocketImpl>. That makes a difference?

Thanks.

cra...@ee.washington.edu

unread,
Jul 27, 2009, 9:12:08 PM7/27/09
to ns-3-...@googlegroups.com

You tried

Config::ConnectWithoutContext (
"/NodeList/<the right number>/$ns3::TcpL4Protocol/SocketList/<the right
number>/CongestionWindow",
MakeCallback (&CwndTracer));

And you don't see any events? Are you sure your applications are actually
doing something, like sending data? Have you turned on log messages to see
what is happening in your simulation? Do you know about
http://www.nsnam.org/wiki/index.php/HOWTO_use_NS_LOG_to_find_a_problem

You could turn on TcpL4Protocol and TcpSocketImpl and look and see what is
happening.

If you can't make progress, you should supply all of your code so one of us
can try it out in our copious spare time :-)

It would be easiest if you could provide a mercurial repository we could
just clone and build. Do you know about http://freehg.org?

-- Craig


C Facchini

unread,
Sep 17, 2009, 10:50:15 AM9/17/09
to ns-3-users
I have a similar problem.

I have two simulation files, both based on examples/tcp-large-
transfer.cc (they were adjusted to simulate an ad hoc wireless
scenario).
One file, just like the original file, "uses sockets directly and
registers some socket callbacks as a sending 'Application'".
The other one "uses 'Application' directly" (here it is, for
reference: http://pastebin.com/m79e8b619 ).

In the former I am able to trace the congestion window.
In the latter I am not.
Even if I use the most general path, nothing gets traced:
Config::ConnectWithoutContext (
"/NodeList/*/$ns3::TcpL4Protocol/SocketList/*/CongestionWindow",
MakeCallback (&CwndTracer));

> And you don't see any events? Are you sure your applications are actually
> doing something, like sending data? Have you turned on log messages to see
> what is happening in your simulation? Do you know abouthttp://www.nsnam.org/wiki/index.php/HOWTO_use_NS_LOG_to_find_a_problem
>
> You could turn on TcpL4Protocol and TcpSocketImpl and look and see what is
> happening.
Packets actually are exchanged (as .pcap traces testify); plus, I can
monitor the cwnd by turning on logging:
LogComponentEnable("TcpSocketImpl", LOG_LEVEL_ALL);

This thread raised a doubt in me: can I trace down sockets if I make
use of 'Applications'?

Regards,
Christian

cra...@ee.washington.edu

unread,
Sep 17, 2009, 3:15:24 PM9/17/09
to ns-3-...@googlegroups.com

You can use the tracing code wherever you want, whenever you want, for
whatever reason you want. It has no connection to applications at all.

One important thing to remember is that the socket in the SocketList must
exist when you do the connect. Often, when you use an application, your
socket isn't created until some specific application start time when the
simulation is running. The natural tendency, I think, is to try and hook
the socket in the main program -- that is at configuration time. The socket
you try to hook doesn't exist yet, so there is nothing in SocketList/*/ to
connect to.

I think you may find that one of the examples creates the socket at
configuration time and then hooks a trace to that existing socket. The
other probably tries to hook a socket that doesn't exist yet.

-- Craig


C Facchini

unread,
Sep 17, 2009, 3:42:48 PM9/17/09
to ns-3-users
> One important thing to remember is that the socket in the SocketList must
> exist when you do the connect.  Often, when you use an application, your
> socket isn't created until some specific application start time when the
> simulation is running.  The natural tendency, I think, is to try and hook
> the socket in the main program -- that is at configuration time.  The socket
> you try to hook doesn't exist yet, so there is nothing in SocketList/*/ to
> connect to.
So it silently fails. That was the missing piece of the puzzle. Thank
you, once again.

The only solution I can come up with is to defer the Connect via
Simulator::Schedule, that is (given that the application starts at 1
second):
Simulator::Schedule (Seconds (1),
Config::ConnectWithoutContext,
"/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
MakeBoundCallback (&CwndChangeWriter, writer));

It works, but somehow I doubt it is the Good (TM) way of doing it.
Would it be possible to do it another way?
Also, since I don't have a pointer to the socket and (since I think it
is not possible to get one starting from the Application class) is
there a way to check when the socket has been created? (or is it safe
to schedule both the Application and the Connect simultaneously?)

Mathieu Lacage

unread,
Sep 18, 2009, 5:11:50 AM9/18/09
to ns-3-...@googlegroups.com
On Thu, Sep 17, 2009 at 9:42 PM, C Facchini <c.fac...@gmail.com> wrote:

> The only solution I can come up with is to defer the Connect via
> Simulator::Schedule, that is (given that the application starts at 1
> second):
>  Simulator::Schedule (Seconds (1),
>    Config::ConnectWithoutContext,
>    "/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow",
> MakeBoundCallback (&CwndChangeWriter, writer));
>
> It works, but somehow I doubt it is the Good (TM) way of doing it.

I think that it's fine.

> Would it be possible to do it another way?

Well, you really need to wait until the socket is created so, either
you connect from within the application itself or you schedule a
separate event to connect like you did.


> Also, since I don't have a pointer to the socket and (since I think it
> is not possible to get one starting from the Application class) is
> there a way to check when the socket has been created? (or is it safe
> to schedule both the Application and the Connect simultaneously?)

I suspect that it should be possible to add a TcpL4Protocol trace hook
which is invoked whenever a socket is created so that you can start by
connecting to this hook and, then, you could connect to the socket
from this hook. Actually, I like this quite a bit.

Mathieu
--
Mathieu Lacage <mathieu...@gmail.com>

Reply all
Reply to author
Forward
0 new messages