Difference between Config::Connect and Config::ConnectwithoutContext

1,788 views
Skip to first unread message

Antti Mäkelä

unread,
Jul 6, 2009, 7:08:45 AM7/6/09
to ns-3-users
Hey - if I want to do traces of internal status of an application,
it's clear from tutorial that I'm supposed to connect a tracing source
to a tracing sink.

However, I couldn't find any pertinent documentation on how this all
fits together.

Taking a look at examples/csma-ping.cc, it has, near the end

------
// then, print what the packet sink receives.
Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/
0/$ns3::PacketSink/Rx",
MakeCallback (&SinkRx));
// finally, print the ping rtts.
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt",
MakeCallback (&PingRtt));
------

Why is the first one called without context, and the latter one is?

Second, the callback functions...

static void SinkRx (Ptr<const Packet> p, const Address &ad)
static void PingRtt (std::string context, Time rtt)

fine, I think that this gives some sort of clue that "context" is
some sort of std::string that gets passed to the PingRtt - however,
what are the contents?

Furthermore, where can I get these parameters that are being passed?

packet-sink.cc has the following:

.AddTraceSource ("Rx", "A packet has been received",
MakeTraceSourceAccessor (&PacketSink::m_rxTrace))

but I'm sort of baffled how this could mean two parameters.

Other example is examples/tcp-large-transfer.cc - has

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

and the function is

static void
CwndTracer (uint32_t oldval, uint32_t newval)
{
NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
}

Now, how am I supposed to find out what are the parameters here? tcp-
socket-impl.cc again only has

.AddTraceSource ("CongestionWindow",
"The TCP connection's congestion window",
MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))

which doesn't exacly suggest that both the old and new value get
passed at same time.

http://www.nsnam.org/doxygen/group___trace_source_list.html doesn't
help here, either.

Thanks for all tips...

Mathieu Lacage

unread,
Jul 6, 2009, 7:27:48 AM7/6/09
to ns-3-...@googlegroups.com
On Mon, 2009-07-06 at 04:08 -0700, Antti Mäkelä wrote:

> ------
> // then, print what the packet sink receives.
> Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/
> 0/$ns3::PacketSink/Rx",
> MakeCallback (&SinkRx));
> // finally, print the ping rtts.
> Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt",
> MakeCallback (&PingRtt));
> ------
>
> Why is the first one called without context, and the latter one is?
>
> Second, the callback functions...
>
> static void SinkRx (Ptr<const Packet> p, const Address &ad)
> static void PingRtt (std::string context, Time rtt)
>
> fine, I think that this gives some sort of clue that "context" is
> some sort of std::string that gets passed to the PingRtt - however,
> what are the contents?

If you print it, you will see what it looks like and it should be fairly
self-explanatory. i.e., it's roughly a fully-resolved version of the
connection path you gave to ::Connect. It will tell you exactly which
object the event is coming from.

>
> Furthermore, where can I get these parameters that are being passed?
>
> packet-sink.cc has the following:
>
> .AddTraceSource ("Rx", "A packet has been received",
> MakeTraceSourceAccessor (&PacketSink::m_rxTrace))
>
> but I'm sort of baffled how this could mean two parameters.

In packet-sink.h:
TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace;

i.e., first argument is a Ptr<const Packet> and second argument is a
const Address &.


>
> Other example is examples/tcp-large-transfer.cc - has
>
> Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/
> SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
>
> and the function is
>
> static void
> CwndTracer (uint32_t oldval, uint32_t newval)
> {
> NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
> }
>
> Now, how am I supposed to find out what are the parameters here? tcp-
> socket-impl.cc again only has
>
> .AddTraceSource ("CongestionWindow",
> "The TCP connection's congestion window",
> MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))

in tcp-socket-impl.h:

TracedValue<uint32_t> m_cWnd;

and, yes, this does not tell you much, even the doxygen for
ns3::TracedValue is not obvious, but you found out the answer yourself
below.

> which doesn't exacly suggest that both the old and new value get
> passed at same time.

both the old and new values are given to trace sinks of trace sources of
type TracedValue<T> and the type of both arguments is T.

Patches to improve the documentation are more than welcome :)

Mathieu

Antti Mäkelä

unread,
Jul 6, 2009, 8:47:35 AM7/6/09
to ns-3-users
On Jul 6, 2:27 pm, Mathieu Lacage <mathieu.lac...@sophia.inria.fr>
wrote:
>   Now, how am I supposed to find out what are the parameters here? tcp-
> > socket-impl.cc again only has
>
> >     .AddTraceSource ("CongestionWindow",
> >                      "The TCP connection's congestion window",
> >                      MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
>
> in tcp-socket-impl.h:
>
>   TracedValue<uint32_t>          m_cWnd;  
>
> and, yes, this does not tell you much, even the doxygen for
> ns3::TracedValue is not obvious, but you found out the answer yourself
> below.

Ah, I didn't follow the trail that far - thought m_cWnd was just
your regular uint32_t.

>both the old and new values are given to trace sinks of trace sources of
>type TracedValue<T> and the type of both arguments is T.

Can you point out where in sources does this happen? I'm struggling
to understand all the template built on templates...

I mean, first you call
MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))

which is

template <typename T>
Ptr<const TraceSourceAccessor> MakeTraceSourceAccessor (T a)
{
return DoMakeTraceSourceAccessor (a);
}

so effectively nothing happens here, and I'm with you so far (in
this case the type is TracedValue<uint32_t>). But the trail for me
stops there, DoMakeTraceSourceAccessor doesn't really make any sense
for me.

The virtual bool ConnectWithoutContext has
(p->*m_source).ConnectWithoutContext (cb);

which I guess does the actual connection.

I thought callbacks were basically templates where you have the
reference to function and parameters you wish to pass for it, but I
still can't find any sign that both old and new value get passed - or
even the single one. Anyway, I couldn't find anyplace to indicate
where both old and new val are passed, and I tried to check

traced-callback.cc
traced-value.h and .cc
trace-source-accessor.h and .cc

Anyway, thanks..feeling like I'm falling down a rabbit hole here.
Can't write a documentation patch since I still fail to understand the
code. Mostly I don't want to generalize - if it always passes both new
and old val, it's ok, but it's clear that in the csma-ping-example
only the current value is passed.

Mathieu Lacage

unread,
Jul 6, 2009, 9:11:37 AM7/6/09
to ns-3-...@googlegroups.com
On Mon, 2009-07-06 at 05:47 -0700, Antti Mäkelä wrote:
> > in tcp-socket-impl.h:
> >
> > TracedValue<uint32_t> m_cWnd;
> >
> > and, yes, this does not tell you much, even the doxygen for
> > ns3::TracedValue is not obvious, but you found out the answer yourself
> > below.
>
> Ah, I didn't follow the trail that far - thought m_cWnd was just
> your regular uint32_t.
>
> >both the old and new values are given to trace sinks of trace sources of
> >type TracedValue<T> and the type of both arguments is T.

in traced-value.h:

T m_v;
TracedCallback<T,T> m_cb;

in the same file, Set does the actual invocation of your sink ('v' is
new value, 'm_v' is old value):

void Set (const T &v) {
if (m_v != v)
{
m_cb (m_v, v);
m_v = v;
}
}

and the connection happens in Connect:
void Connect (const CallbackBase &cb, std::string path) {
m_cb.Connect (cb, path);
}

Now, m_cb is a TracedCallback (traced-callback.h):

typedef std::list<Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> >
CallbackList;
CallbackList m_callbackList;

and Connect:

void
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Connect (const CallbackBase &
callback, std::string path)
{
Callback<void,std::string,T1,T2,T3,T4,T5,T6,T7,T8> cb;
cb.Assign (callback);
Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> realCb = cb.Bind (path);
m_callbackList.push_back (realCb);
}

>
> Can you point out where in sources does this happen? I'm struggling
> to understand all the template built on templates...
>
> I mean, first you call
> MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd))
>
> which is
>
> template <typename T>
> Ptr<const TraceSourceAccessor> MakeTraceSourceAccessor (T a)
> {
> return DoMakeTraceSourceAccessor (a);
> }
>
> so effectively nothing happens here, and I'm with you so far (in
> this case the type is TracedValue<uint32_t>). But the trail for me
> stops there, DoMakeTraceSourceAccessor doesn't really make any sense
> for me.
>
> The virtual bool ConnectWithoutContext has
> (p->*m_source).ConnectWithoutContext (cb);
>
> which I guess does the actual connection.

Here, you are calling TracedValue<T>::ConnectWithoutContext which is
calling TracedCallback<T,T>::ConnectWithoutContext which is adding
another callback in the list of callbacks to invoke when
TracedCallback<>::operator () is called.

> I thought callbacks were basically templates where you have the
> reference to function and parameters you wish to pass for it, but I
> still can't find any sign that both old and new value get passed - or
> even the single one. Anyway, I couldn't find anyplace to indicate
> where both old and new val are passed, and I tried to check
>
> traced-callback.cc
> traced-value.h and .cc
> trace-source-accessor.h and .cc
>
> Anyway, thanks..feeling like I'm falling down a rabbit hole here.
> Can't write a documentation patch since I still fail to understand the
> code. Mostly I don't want to generalize - if it always passes both new
> and old val, it's ok, but it's clear that in the csma-ping-example

TracedValue<T> always passes old and new.

> only the current value is passed.

I am afraid that this piece of code is slightly tricky...

Mathieu

Reply all
Reply to author
Forward
0 new messages