[Ns-developers] [ns3] topology API

Gustavo Carneiro gjcarneiro at gmail.com
Fri Jan 18 03:57:38 PST 2008


On 17/01/2008, craigdo at ee.washington.edu <craigdo at ee.washington.edu> wrote:
>
> Okay, since nobody wants any preliminaries, I'll just present a framework
> approach to the current problem.
>
> First, at the client level, you would see something like the following in
> simple.cc:
>
> //
> // inherit from the basic wireless cluster framework that does the
> // grunt work (technically, implements the frozen spots).  We're
> // going to override the pieces of the framework that we want to
> // modify.  Here, we want to control how the net device is put
> // together and what applications are run on the nodes.
> //
> class MyWirelessClusterFramework : public WirelessClusterFramework
> {
> public:
>   MyWirelessClusterFramework ();
>   virtual ~MyWirelessClusterFramework ();
>
> protected:
>   virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch);
>   virtual void CreateApplications (Ptr<Node> n);
> }
>
> //
> // Here's the method that's used to create the net devices.  Using
> // inversion of control, it's brought up from the "bowels of the system"
> // into the client space so we can control what happens directly.
> //
> // This is the case where Mathieu wanted to create another kind of rate
> // control object that took different construction parameters.
> //
> // Using this approach, they're right here in front of the client's face
> // to change however she wants.  There would be a default implementation
> // of this method that would use the default rate control object so if
> // you don't want to change that, you don't have to re-implement this
> // method.
> //
>   Ptr<NetDevice>
> MyWirelessClusterFramework::CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch)
> {
>   Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> (n);
>
>   Ptr<CraigsWierdRateControl> rate =
>     CreateObject<CraigsWierdRateControl> (param1, param2, param3);
>
>   nd->SetRateControl (rate);
>
>   return nd;
> }
>
> //
> // Here's the method that's used to create the applications.  Using
> // inversion of control, it's brought up from the "bowels of the system"
> // into the client space so we can control what happens directly.
> //
> // The default method would create no applications or possibly if you
> // almost always want something there, it could create it by default.
> // You could add to the default set here as well (as is illustrated)
> //
>   void
> MyWirelessClusterFramework::CreateApplications (Ptr<Node> n)
> {
>   WirelessClusterFramework::CreateApplications (n);
>   Ptr<OnOffApplication> app = CreateObject<OnOffApplication> (n);
>   return;
> }
>
> //
> // Now the client uses the framework simply by asking it to Build some
> // number of nodes.  She gets back a TopologySet that includes a channel
> // and contains all of the nodes "connected" to the channel.
> //
> int
> main (int argc, char *argv[])
> {
>   MyWirelessClusterFramework fw;
>   Ptr<TopologySet> topo = fw.Build (100);
> //
> // Run IP address assigner, router, etc.
> //
>   Simulator::Run ();
>   Simulator::Destroy ();
> }
>
> Now the framework code is implemented in some other file somewhere.  I
> would
> expect that there are a number of frameworks for different basic
> topologies,
> but here's how they might look for this problem.
>
> There's a base class that has a frozen spot called Build that runs the for
>
> loop and has hot spots for the creation functions that will likely be
> changed ...
>
> class TopologyFramework : public Object
> {
> public:
>   TopologyFramework ();
>   virtual ~TopologyFramework ();
>
>   Ptr<TopologySet> Build (unit32_t n);  // frozen spot
>
> protected:
>   virtual Ptr<Channel> CreateChannel (void) = 0;
>   virtual Ptr<Node> CreateNode (void) = 0;
>   virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch) =
> 0;
>   virtual void CreateApplications (Ptr<Node> n) = 0;
> };
>
> The frozen spot code just creates a channel and connects up a bunch of
> nodes, net devices and applications.  This code calls into the hot spots
> wich can be refined by a client to do the dirty work.  Presumably this
> won't
> change (much).
>
>   Ptr<TopologySet>
> TopologyFramework::Build (uint32_t n)
> {
>   Ptr<TopologySet> topo = Create<TopologySet> ();
>
>   Ptr<Channel> ch = CreateChannel ();
>   topo->SetChannel (ch);
>
>   for (uint32_t i = 0; i < n; ++i)
>     {
>       Ptr<Node> n = CreateNode ();
>       Ptr<NetDevice> nd = CreateNetDevice (n, ch);
>          CreateApplications (n);
>       topo->AddNode (n);
>       ch->AddNode (n);
>     }
> }
>
> It's nice to have a default version that does useful work without having
> to
> override/redefine anything, so there should be another class that looks
> something like the following:
>
> This would create a generic wireless cluster with the standard rate
> control
> algorithm Mathieu spoke of.
>
> class WirelessClusterFramework : public TopologyFramework
> {
> public:
>   WirelessClusterFramework ();
>   virtual ~VirtualClusterFramework ();
>
> protected:
>   virtual Ptr<Channel> CreateChannel (void);
>   virtual Ptr<Node> CreateNode (void);
>   virtual Ptr<NetDevice> CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch);
>   virtual Ptr<NetDevice> CreateApplications (Ptr<Node> n);
> };
>
>   Ptr<Channel>
> WirelessClusterFramework::CreateChannel (void)
> {
>   return Create<WifiChannel>;
> }
>
>   Ptr<Node>
> WirelessClusterFramework::CreateNode (void)
> {
>   Ptr<Node> n = CreateObject<Node>;
>   n->AddIpStack ();
>   n->AddUdpStack ();
>   n->AddTcpStack ();
> }
>
>   Ptr<NetDevice>
> WirelessClusterFramework::CreateNetDevice (Ptr<Node> n, Ptr<Channel> ch)
> {
>   Ptr<WifiNetDevice> nd = CreateObject<WifiNetDevice> (n);
>   Ptr<RateControl> rate = CreateObject<RateControl> ();
>
>   nd->SetRateControl (rate);
>
>   return nd;
> }
>
> So, there is really no need to implement any Parameters plumbing through
> the
> system if we just take to heart what Mathieu said about exposing the
> control
> flow to the user.
>
> I think this is quite easy to understand and is more flexible than trying
> to
> plumb Parameters down into the system.  Like Mathieu said, expose the area
> on which you want to tweak directly to the user, don't force him to try
> and
> execute his wishes by "remote control" by describing it via data.
>
> Thoughts?


Honestly I don't see the point od TopologyFramework::Build (uint32_t n).
It's not like a for-loop is _that_ complex, even in C++.  And I think
TopologyFramework::Build just obscures the simple for loop.  And if you
start making examples with TopologyFramework::Build then some people will
think that TopologyFramework::Build does some kind of special magic to make
it happen and will forever be afraid to do a simple for loop.

I like the idea of container/group much better; at least a container does
something useful: keep a list of nodes.  I don't think inversion of control
is beneficial in this case because it only automates a simple for loop.  And
if a new API is not beneficial it ends up being harmful because you have to
learn it anyway.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert


More information about the Ns-developers mailing list