comparing with http://code.nsnam.org/ns-3-dev searching for changes changeset: 4111:d45e62c78504 user: Craig Dowell date: Tue Jan 20 15:47:14 2009 -0800 summary: add an object name service diff -r 04170734fa8b -r d45e62c78504 examples/names.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/names.cc Tue Jan 20 15:47:14 2009 -0800 @@ -0,0 +1,142 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +// Network topology +// +// n0 n1 n2 n3 +// | | | | +// ================= +// LAN +// + +#include +#include "ns3/core-module.h" +#include "ns3/simulator-module.h" +#include "ns3/helper-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("NamesExample"); + +void +RxEvent (std::string context, Ptr packet) +{ + NS_LOG_INFO (context << " packet " << packet); +} + +int +main (int argc, char *argv[]) +{ + // + // Users may find it convenient to turn on explicit debugging + // for selected modules; the below lines suggest how to do this + // +#if 1 + LogComponentEnable ("NamesExample", LOG_LEVEL_INFO); +#endif + + // + // Allow the user to override any of the defaults and the above Bind() at + // run-time, via command-line arguments + // + CommandLine cmd; + cmd.Parse (argc, argv); + + // + // Explicitly create the nodes required by the topology (shown above). + // + NS_LOG_INFO ("Create nodes."); + NodeContainer n; + n.Create (4); + + // + // We're going to use the zeroth node in the container as the client, and + // the first node as the server. Add some "human readable" names for these + // nodes. The first parameter specifies the root of the "/Names" name space + // as the destination, so these will go into the name system as "/Names/client" + // and "/Names/server". + // + Names::Add ("/Names", "client", n.Get (0)); + Names::Add ("/Names", "server", n.Get (1)); + + InternetStackHelper internet; + internet.Install (n); + + NS_LOG_INFO ("Create devices."); + CsmaHelper csma; + csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000))); + csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2))); + csma.SetDeviceAttribute ("Mtu", UintegerValue (1400)); + NetDeviceContainer d = csma.Install (n); + + // + // Add some human readable names for the devices we'll be interested in. + // We add the names to the name space "under" the nodes we created above. + // This has the effect of making "/Names/client/eth0" and "/Names/server/eth0" + // Note that the first parameter must reference a previously named object, + // and we have, in fact, already named objects "/Names/client" and + // "/Names/server" + // + Names::Add ("/Names/client", "eth0", d.Get (0)); + Names::Add ("/Names/server", "eth0", d.Get (1)); + + Ipv4AddressHelper ipv4; + + // + // We've got the "hardware" in place. Now we need to add IP addresses. + // + NS_LOG_INFO ("Assign IP Addresses."); + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer i = ipv4.Assign (d); + + NS_LOG_INFO ("Create Applications."); + + // + // Create a UdpEchoServer application on the server node. Note that we + // reference the server node by name in the Install method below. + // + uint16_t port = 9; // well-known echo port number + UdpEchoServerHelper server (port); + ApplicationContainer apps = server.Install (Names::Find ("/Names/server")); + apps.Start (Seconds (1.0)); + apps.Stop (Seconds (10.0)); + + // + // Create a UdpEchoClient application to send UDP datagrams from node zero to + // node one. Notice that we reference the client node by name in the Install + // method below. + // + uint32_t packetSize = 1024; + uint32_t maxPacketCount = 1; + Time interPacketInterval = Seconds (1.); + UdpEchoClientHelper client (i.GetAddress (1), port); + client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount)); + client.SetAttribute ("Interval", TimeValue (interPacketInterval)); + client.SetAttribute ("PacketSize", UintegerValue (packetSize)); + apps = client.Install (Names::Find ("/Names/client")); + apps.Start (Seconds (2.0)); + apps.Stop (Seconds (10.0)); + + Config::Connect ("/Names/client/eth0/Rx", MakeCallback (&RxEvent)); + + // + // Now, do the actual simulation. + // + NS_LOG_INFO ("Run Simulation."); + Simulator::Run (); + Simulator::Destroy (); + NS_LOG_INFO ("Done."); +} diff -r 04170734fa8b -r d45e62c78504 examples/wscript --- a/examples/wscript Sun Jan 18 22:47:25 2009 +0000 +++ b/examples/wscript Tue Jan 20 15:47:14 2009 -0800 @@ -15,6 +15,10 @@ def build(bld): obj = bld.create_ns3_program('third', ['core', 'simulator', 'point-to-point', 'csma', 'wifi', 'internet-stack']) obj.source = 'third.cc' + + obj = bld.create_ns3_program('names', + ['core', 'simulator', 'csma', 'internet-stack']) + obj.source = 'names.cc' obj = bld.create_ns3_program('mixed-wireless', ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-stack']) diff -r 04170734fa8b -r d45e62c78504 src/core/config.cc --- a/src/core/config.cc Sun Jan 18 22:47:25 2009 +0000 +++ b/src/core/config.cc Tue Jan 20 15:47:14 2009 -0800 @@ -22,6 +22,7 @@ #include "object.h" #include "global-value.h" #include "object-vector.h" +#include "object-names.h" #include "pointer.h" #include "log.h" #include @@ -294,6 +295,45 @@ Resolver::DoResolve (std::string path, P std::string item = path.substr (1, next-1); std::string pathLeft = path.substr (next, path.size ()-next); + // + // If root is zero, we're beginning to see if we can use the object name + // service to resolve this path. In this case, we must see the name space + // "/Names" on the front of this path. There is no object associated with + // the root of the "/Names" namespace, so we just ignore it and move on to + // the next segment. + // + if (root == 0) + { + std::string::size_type offset = path.find ("/Names"); + if (offset == 0) + { + m_workStack.push_back (item); + DoResolve (pathLeft, root); + m_workStack.pop_back (); + return; + } + } + + // + // We have an item (possibly a segment of a namespace path. Check to see if + // we can determine that this segment refers to a named object. If root is + // zero, this means to look in the root of the "/Names" name space, otherwise + // it refers to a name space context (level). + // + Ptr namedObject = Names::FindObjectFromShortName (root, item); + if (namedObject) + { + NS_LOG_DEBUG ("Name system resolved item = " << item << " to " << namedObject); + m_workStack.push_back (item); + DoResolve (pathLeft, namedObject); + m_workStack.pop_back (); + return; + } + + // + // We're done with the object name service hooks, so proceed down the path + // of types and attributes. + // std::string::size_type dollarPos = item.find ("$"); if (dollarPos == 0) { @@ -480,6 +520,14 @@ ConfigImpl::LookupMatches (std::string p { resolver.Resolve (*i); } + + // + // See if we can do something with the object name service. Starting with + // the root pointer zeroed indicates to the resolver that it should start + // looking at the root of the "/Names" namespace during this go. + // + resolver.Resolve (0); + return Config::MatchContainer (resolver.m_objects, resolver.m_contexts, path); } diff -r 04170734fa8b -r d45e62c78504 src/core/object-names.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/object-names.cc Tue Jan 20 15:47:14 2009 -0800 @@ -0,0 +1,624 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include "ns3/object.h" +#include "ns3/log.h" +#include "ns3/assert.h" +#include "ns3/abort.h" +#include "ns3/simulator.h" +#include "object-names.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("Names"); + +class NameNode +{ +public: + NameNode (); + NameNode (const NameNode &nameNode); + NameNode (NameNode *parent, std::string name, Ptr object); + NameNode &operator = (const NameNode &rhs); + + ~NameNode (); + + NameNode *m_parent; + std::string m_name; + Ptr m_object; + + std::map m_nameMap; +}; + +NameNode::NameNode () + : m_parent (0), m_name (""), m_object (0) +{ +} + +NameNode::NameNode (const NameNode &nameNode) +{ + m_parent = nameNode.m_parent; + m_name = nameNode.m_name; + m_object = nameNode.m_object; + m_nameMap = nameNode.m_nameMap; +} + +NameNode & +NameNode::operator = (const NameNode &rhs) +{ + m_parent = rhs.m_parent; + m_name = rhs.m_name; + m_object = rhs.m_object; + m_nameMap = rhs.m_nameMap; + return *this; +} + +NameNode::NameNode (NameNode *parent, std::string name, Ptr object) + : m_parent (parent), m_name (name), m_object (object) +{ +} + +NameNode::~NameNode () +{ +} + +class NamesPriv +{ +public: + NamesPriv (); + ~NamesPriv (); + + bool Add (std::string name, Ptr obj); + bool Add (Ptr context, std::string name, Ptr object); + bool Add (std::string context, std::string name, Ptr object); + std::string FindShortName (Ptr object); + std::string FindFullName (Ptr object); + Ptr FindObjectFromFullName (std::string name); + Ptr FindObjectFromShortName (Ptr context, std::string name); + + static NamesPriv *Get (void); + +private: + static NamesPriv **DoGet (void); + static void Delete (void); + + NameNode *IsNamed (Ptr); + bool IsDuplicateName (NameNode *node, std::string name); + + NameNode m_root; + std::map, NameNode *> m_objectMap; +}; + +NamesPriv * +NamesPriv::Get (void) +{ + return *(DoGet ()); +} + +NamesPriv ** +NamesPriv::DoGet (void) +{ + static NamesPriv *ptr = 0; + + if (ptr == 0) + { + ptr = new NamesPriv; + Simulator::ScheduleDestroy (&NamesPriv::Delete); + } + + return &ptr; +} + +void +NamesPriv::Delete (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + NamesPriv **ptr = DoGet (); + delete *ptr; + *ptr = 0; +} + +NamesPriv::NamesPriv () +{ + NS_LOG_FUNCTION_NOARGS (); + + m_root.m_parent = 0; + m_root.m_name = "Names"; + m_root.m_object = 0; +} + +NamesPriv::~NamesPriv () +{ + NS_LOG_FUNCTION_NOARGS (); + + // + // Every name is associated with an object in the object map, so freeing the + // NameNodes in this map will free all of the memory allocated for the NameNodes + // + for (std::map, NameNode *>::iterator i = m_objectMap.begin (); i != m_objectMap.end (); ++i) + { + delete i->second; + i->second = 0; + } +} + +bool +NamesPriv::Add (std::string name, Ptr object) +{ + return Add (Ptr (0, false), name, object); +} + +bool +NamesPriv::Add (Ptr context, std::string name, Ptr object) +{ + NS_LOG_FUNCTION (context << name << object); + + if (IsNamed (object)) + { + NS_LOG_LOGIC ("Object is already named"); + return false; + } + + NameNode *node = 0; + if (context) + { + node = IsNamed (context); + NS_ASSERT_MSG (node, "NamesPriv::Name(): context must point to a previously named node"); + } + else + { + node = &m_root; + } + + if (IsDuplicateName (node, name)) + { + NS_LOG_LOGIC ("Name is already taken"); + return false; + } + + NameNode *newNode = new NameNode(node, name, object); + node->m_nameMap[name] = newNode; + m_objectMap[object] = newNode; + + return true; +} + +bool +NamesPriv::Add (std::string context, std::string name, Ptr object) +{ + if (context == "/Names") + { + return Add (name, object); + } + return Add (FindObjectFromFullName (context), name, object); +} + +std::string +NamesPriv::FindShortName (Ptr object) +{ + NS_LOG_FUNCTION (object); + + std::map, NameNode *>::iterator i = m_objectMap.find (object); + if (i == m_objectMap.end ()) + { + NS_LOG_LOGIC ("Object does not exist in object map"); + return ""; + } + else + { + NS_LOG_LOGIC ("Object exists in object map"); + return i->second->m_name; + } +} + +std::string +NamesPriv::FindFullName (Ptr object) +{ + NS_LOG_FUNCTION (object); + + std::map, NameNode *>::iterator i = m_objectMap.find (object); + if (i == m_objectMap.end ()) + { + NS_LOG_LOGIC ("Object does not exist in object map"); + return ""; + } + + NameNode *p = i->second; + NS_ASSERT_MSG (p, "NamesPriv::FindFullName(): Internal error: Invalid NameNode pointer from map"); + + std::string fullname; + + do + { + fullname = "/" + p->m_name + fullname; + NS_LOG_LOGIC ("fullname is " << fullname); + } + while ((p = p->m_parent) != 0); + + return fullname; +} + + +Ptr +NamesPriv::FindObjectFromFullName (std::string name) +{ + std::string namespaceName = "/Names/"; + std::string::size_type offset = name.find (namespaceName); + if (offset == std::string::npos) + { + NS_LOG_LOGIC (name << " is not in the " << namespaceName << " name space"); + return 0; + } + + std::string remaining = name.substr (namespaceName.size ()); + NameNode *node = &m_root; + + // + // remaining is now composed entirely of path segments in the /Names name space. + // and we have eaten the leading slash. e.g., remaining = "ClientNode/eth0" + // The start of the search is at the root of the name space. + // + for (;;) + { + NS_LOG_LOGIC ("Looking for the object of name " << remaining); + offset = remaining.find ("/"); + if (offset == std::string::npos) + { + // + // There are no remaining slashes so this is the last segment of the + // specified name. We're done when we find it + // + std::map::iterator i = node->m_nameMap.find (remaining); + if (i == node->m_nameMap.end ()) + { + NS_LOG_LOGIC ("Name does not exist in name map"); + return 0; + } + else + { + NS_LOG_LOGIC ("Name parsed, found object"); + return i->second->m_object; + } + } + else + { + // + // There are more slashes so this is an intermediate segment of the + // specified name. We need to "recurse" when we find this segment. + // + offset = remaining.find ("/"); + std::string segment = remaining.substr(0, offset); + + std::map::iterator i = node->m_nameMap.find (segment); + if (i == node->m_nameMap.end ()) + { + NS_LOG_LOGIC ("Name does not exist in name map"); + return 0; + } + else + { + node = i->second; + remaining = remaining.substr (offset + 1); + NS_LOG_LOGIC ("Intermediate segment parsed"); + continue; + } + } + } + + NS_ASSERT_MSG (node, "NamesPriv::FindObjectFromFullName(): Internal error: this can't happen"); + return 0; +} + +Ptr +NamesPriv::FindObjectFromShortName (Ptr context, std::string name) +{ + NS_LOG_FUNCTION (context << name); + + NameNode *node = 0; + + if (context == 0) + { + NS_LOG_LOGIC ("Zero context implies root NameNode"); + node = &m_root; + } + else + { + node = IsNamed (context); + if (node == 0) + { + NS_LOG_LOGIC ("Context does not point to a previously named node"); + return 0; + } + } + + std::map::iterator i = node->m_nameMap.find (name); + if (i == node->m_nameMap.end ()) + { + NS_LOG_LOGIC ("Name does not exist in name map"); + return 0; + } + else + { + NS_LOG_LOGIC ("Name exists in name map"); + return i->second->m_object; + } +} + +NameNode * +NamesPriv::IsNamed (Ptr object) +{ + NS_LOG_FUNCTION (object); + + std::map, NameNode *>::iterator i = m_objectMap.find (object); + if (i == m_objectMap.end ()) + { + NS_LOG_LOGIC ("Object does not exist in object map, returning NameNode 0"); + return 0; + } + else + { + NS_LOG_LOGIC ("Object exists in object map, returning NameNode " << &i->second); + return i->second; + } +} + +bool +NamesPriv::IsDuplicateName (NameNode *node, std::string name) +{ + NS_LOG_FUNCTION (node << name); + + std::map::iterator i = node->m_nameMap.find (name); + if (i == node->m_nameMap.end ()) + { + NS_LOG_LOGIC ("Name does not exist in name map"); + return false; + } + else + { + NS_LOG_LOGIC ("Name exists in name map"); + return true; + } +} + +bool +Names::Add (std::string name, Ptr object) +{ + return NamesPriv::Get ()->Add (name, object); +} + +bool +Names::Add (Ptr context, std::string name, Ptr object) +{ + return NamesPriv::Get ()->Add (context, name, object); +} + +bool +Names::Add (std::string context, std::string name, Ptr object) +{ + return NamesPriv::Get ()->Add (context, name, object); +} + +std::string +Names::FindShortName (Ptr object) +{ + return NamesPriv::Get ()->FindShortName (object); +} + +std::string +Names::FindFullName (Ptr object) +{ + return NamesPriv::Get ()->FindFullName (object); +} + +Ptr +Names::FindObjectFromFullNameInternal (std::string name) +{ + return NamesPriv::Get ()->FindObjectFromFullName (name); +} + +Ptr +Names::FindObjectFromShortNameInternal (Ptr context, std::string name) +{ + return NamesPriv::Get ()->FindObjectFromShortName (context, name); +} + +} //namespace ns3 + +#ifdef RUN_SELF_TESTS + +#include "test.h" +#include "object-factory.h" + +namespace ns3 { + +class TestObject : public Object +{ +public: + static TypeId GetTypeId (void) + { + static TypeId tid = TypeId ("TestObject") + .SetParent (Object::GetTypeId ()) + .HideFromDocumentation () + .AddConstructor (); + return tid; + } + TestObject () {} + virtual void Dispose (void) {} +}; + +class NamesTest : public Test +{ +public: + NamesTest (); + virtual bool RunTests (void); +}; + +NamesTest::NamesTest () + : Test ("Names") +{ +} + +bool +NamesTest::RunTests (void) +{ + bool result = true; + + // + // Name a couple of objects at the root level + // + Ptr client = CreateObject (); + result = Names::Add ("Client", client); + NS_TEST_ASSERT_EQUAL (result, true); + + Ptr server = CreateObject (); + result = Names::Add ("Server", server); + NS_TEST_ASSERT_EQUAL (result, true); + + // + // We shouldn't be able to add another name to a previously named object + // + result = Names::Add ("Not Client", client); + NS_TEST_ASSERT_EQUAL (result, false); + + // + // We shouldn't be able to duplicate a name at the root level. + // + Ptr secondClient = CreateObject (); + result = Names::Add ("Client", secondClient); + NS_TEST_ASSERT_EQUAL (result, false); + + // + // We should be able to add a new name in the first object's context + // + Ptr clientEth0 = CreateObject (); + result = Names::Add (client, "eth0", clientEth0); + NS_TEST_ASSERT_EQUAL (result, true); + + // + // We shouldn't be able to duplicate a name in that context. + // + Ptr secondClientEth0 = CreateObject (); + result = Names::Add (client, "eth0", secondClientEth0); + NS_TEST_ASSERT_EQUAL (result, false); + + // + // We should be able to add the same name in the second object's context + // + Ptr serverEth0 = CreateObject (); + result = Names::Add (server, "eth0", serverEth0); + NS_TEST_ASSERT_EQUAL (result, true); + + // + // We should be able to find the short names for the objects we created + // + std::string found; + + found = Names::FindShortName (client); + NS_TEST_ASSERT_EQUAL (found, "Client"); + + found = Names::FindShortName (server); + NS_TEST_ASSERT_EQUAL (found, "Server"); + + found = Names::FindShortName (clientEth0); + NS_TEST_ASSERT_EQUAL (found, "eth0"); + + found = Names::FindShortName (serverEth0); + NS_TEST_ASSERT_EQUAL (found, "eth0"); + + // + // We should be able to find the full names for the objects we created + // + found = Names::FindFullName (client); + NS_TEST_ASSERT_EQUAL (found, "/Names/Client"); + + found = Names::FindFullName (server); + NS_TEST_ASSERT_EQUAL (found, "/Names/Server"); + + found = Names::FindFullName (clientEth0); + NS_TEST_ASSERT_EQUAL (found, "/Names/Client/eth0"); + + found = Names::FindFullName (serverEth0); + NS_TEST_ASSERT_EQUAL (found, "/Names/Server/eth0"); + + // + // We should be able to find the objects from the short names + // + Ptr foundObject; + + foundObject = Names::FindObjectFromShortName (0, "Client"); + NS_TEST_ASSERT_EQUAL (foundObject, client); + + foundObject = Names::FindObjectFromShortName (0, "Server"); + NS_TEST_ASSERT_EQUAL (foundObject, server); + + foundObject = Names::FindObjectFromShortName (client, "eth0"); + NS_TEST_ASSERT_EQUAL (foundObject, clientEth0); + + foundObject = Names::FindObjectFromShortName (server, "eth0"); + NS_TEST_ASSERT_EQUAL (foundObject, serverEth0); + + // + // We should be able to find the objects from their full names + // + foundObject = Names::Find ("/Names/Client"); + NS_TEST_ASSERT_EQUAL (foundObject, client); + + foundObject = Names::Find ("/Names/Server"); + NS_TEST_ASSERT_EQUAL (foundObject, server); + + foundObject = Names::Find ("/Names/Client/eth0"); + NS_TEST_ASSERT_EQUAL (foundObject, clientEth0); + + foundObject = Names::Find ("/Names/Server/eth0"); + NS_TEST_ASSERT_EQUAL (foundObject, serverEth0); + + // + // We also have some syntactical sugary methods, so make sure they do what + // they should as well. + // + Ptr bridge = CreateObject (); + result = Names::Add ("/Names", "Bridge", client); + NS_TEST_ASSERT_EQUAL (result, true); + + Ptr bridgeEth0 = CreateObject (); + result = Names::Add ("/Names/Bridge", "eth0", bridgeEth0); + NS_TEST_ASSERT_EQUAL (result, true); + + foundObject = Names::Find ("/Names/Bridge"); + NS_TEST_ASSERT_EQUAL (foundObject, bridge); + + foundObject = Names::Find ("/Names/Bridge/eth0"); + NS_TEST_ASSERT_EQUAL (foundObject, bridgeEth0); + + // + // Run the simulator and destroy it to get the Destroy method called on the + // private implementation object. We depend on seeing a valgrind-clean run of + // the unit tests to really determine if the clean up was really successful. + // + Simulator::Run (); + Simulator::Destroy (); + + return true; +} + +static NamesTest g_namesTests; + +} // namespace ns3 + +#endif /* RUN_SELF_TESTS */ diff -r 04170734fa8b -r d45e62c78504 src/core/object-names.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/object-names.h Tue Jan 20 15:47:14 2009 -0800 @@ -0,0 +1,245 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef OBJECT_NAMES_H +#define OBJECT_NAMES_H + +#include "ns3/ptr.h" +#include "ns3/object.h" + +namespace ns3 { + +/** + * \brief A directory of name and Ptr associations that allows us to + * give any ns3 Object a name. + */ +class Names +{ +public: + + /** + * Add the association between the string "name" and the Ptr obj + * at the root of the "/Names" name space. This can be seen as equivalent + * to adding a Pointer Attribute called "name" to the to the root name + * space object and then assigning the value obj to that attribute. The + * config facility will see it that way. + * + * \param name The name of the object you want to associate. + * \param obj A smart pointer to the object itself. + */ + static bool Add (std::string name, Ptr obj); + + /** + * Add the association between the string "name" and the Ptr obj + * in the object context given by the Ptr context. This can be + * seen as equivalent to adding a Pointer Attribute called "name" to the + * object given by "context" and then assigning the value obj to that + * attribute. The config facility will see it that way. + * + * \param context A spart pointer to an object under which you want this + * name to be defined. + * \param name The name of the object you want to associate. + * \param obj A smart pointer to the object itself. + */ + static bool Add (Ptr context, std::string name, Ptr object); + + /** + * Syntactic sugar around the Object context Name method. Allows you to + * specify the context with a string instead of the pointer. If the first + * parameter (context) is "/Names" this turns into a call into Name at the + * root of the name space. Otherwise it does a FindObjectFromFullNameInternal + * on the context and adds the name to a subspace. + * + * \param context A fully qualified name describing a previously named object. + * under which you want this name to be defined. + * \param name The name of the object you want to associate. + * \param obj A smart pointer to the object itself. + */ + static bool Add (std::string context, std::string name, Ptr object); + + /** + * Given a pointer to an object, look to see if that object has a name + * associated with it and return the shortname for the object. + * + * The fullname of an object is a fully qualified namespace name, for example + * if you have a device that you have previously named "eth0" under a node + * you have named "client", the fullname of the device will then be + * "/Names/client/eth0". + * + * The shortname of an object is the name of the object in its parent name + * space. Using the example above, asking for the shortname of the device + * will result in "eth0" being returned. + * + * \param object A spart pointer to an object for which you want to find + * its shortname. + */ + static std::string FindShortName (Ptr object); + + /** + * Given a pointer to an object, look to see if that object has a name + * associated with it and return the fully qualified namespace name + * for the object. + * + * The fullname of an object is a fully qualified namespace name, for example + * if you have a device that you have previously named "eth0" under a node + * you have named "client", the fullname of the device will then be + * "/Names/client/eth0". + * + * The shortname of an object is the name of the object in its parent name + * space. Using the example above, asking for the shortname of the device + * will result in "eth0" being returned. + * + * \param object A spart pointer to an object for which you want to find + * its fullname. + */ + static std::string FindFullName (Ptr object); + + /** + * Given a fullname string, look to see if there's an object in the system + * with a that associated with it. If there is, do a QueryObject on the + * resulting object to convert it to the requested typename. + * + * The fullname of an object is a fully qualified namespace name, for example + * if you have a device that you have previously named "eth0" under a node + * you have named "client", the fullname of the device will then be + * "/Names/client/eth0". + * + * \param name A string containing a fully qualified name space name + * used to locate the object. + */ + template + static Ptr FindObjectFromFullName (std::string name); + + /** + * Given a fullname string, look to see if there's an object in the system + * with a that associated with it. If there is, do a QueryObject on the + * resulting object to convert it to the requested typename. + * + * The fullname of an object is a fully qualified namespace name, for example + * if you have a device that you have previously named "eth0" under a node + * you have named "client", the fullname of the device will then be + * "/Names/client/eth0". + * + * \param name A string containing a fully qualified name space name + * used to locate the object. + * + * @comment This method is identical to FindObjectFromFullName, but has a + * short signature since it is a common use and we want it to be easy to + * type. + */ + template + static Ptr Find (std::string name); + + /** + * Given an object context and a shortname string, look through the names + * associated with the namespace defined by the context object to see if + * there's an object there with the given shortname. + * + * The fullname of an object is a fully qualified namespace name, for example + * if you have a device that you have previously named "eth0" under a node + * you have named "client", the fullname of the device will then be + * "/Names/client/eth0". + * + * The shortname of an object is the name of the object in its parent name + * space. Using the example above, asking for the shortname of the device + * will result in "eth0" being returned. + * + * The context object provides a namespace context, in the case of the example + * it would be the "client" object under which we look for the short name. + * In the example above, the context pointer would be the Ptr to the + * client node, and the name would be the shortname "eth0" + * + * \param context A spart pointer to an object under which you want to look + * for the provided name. + * \param name A string containing a shortname to look for. + */ + template + static Ptr FindObjectFromShortName (Ptr context, std::string name); + +private: + + /** + * \internal + * + * \brief Non-templated internal version of FindObjectFromLongName + * + * \param name A string containing a longname to look for. + */ + static Ptr FindObjectFromFullNameInternal (std::string name); + + /** + * \internal + * + * \brief Non-templated internal version of FindObjectFromShortName + * + * \param context A spart pointer to an object under which you want to look + * for the provided name. + * \param name A string containing a shortname to look for. + */ + static Ptr FindObjectFromShortNameInternal (Ptr context, std::string name); +}; + +/** + * \brief Template definition of corresponding template declaration found in class Names. + */ +template +Ptr +Names::Find (std::string name) +{ + return FindObjectFromFullName (name); +} + +/** + * \brief Template definition of corresponding template declaration found in class Names. + */ +template +Ptr +Names::FindObjectFromFullName (std::string name) +{ + Ptr obj = FindObjectFromFullNameInternal (name); + if (obj) + { + return obj->GetObject (); + } + else + { + return 0; + } +} + +/** + * \brief Template definition of corresponding template declaration found in class Names. + */ +template +Ptr +Names::FindObjectFromShortName (Ptr context, std::string name) +{ + Ptr obj = FindObjectFromShortNameInternal (context, name); + if (obj) + { + return obj->GetObject (); + } + else + { + return 0; + } +} + +}//namespace ns3 + +#endif /* OBJECT_NAMES_H */ diff -r 04170734fa8b -r d45e62c78504 src/core/wscript --- a/src/core/wscript Sun Jan 18 22:47:25 2009 +0000 +++ b/src/core/wscript Tue Jan 20 15:47:14 2009 -0800 @@ -53,6 +53,7 @@ def build(bld): 'trace-source-accessor.cc', 'config.cc', 'callback.cc', + 'object-names.cc', ] core.uselib = 'RT' @@ -98,6 +99,7 @@ def build(bld): 'object-vector.h', 'deprecated.h', 'abort.h', + 'object-names.h', ] if sys.platform == 'win32': changeset: 4112:6bbf05bf4826 user: Craig Dowell date: Tue Jan 20 17:39:18 2009 -0800 summary: Brute force all of the helpers to use object name service diff -r d45e62c78504 -r 6bbf05bf4826 examples/names.cc --- a/examples/names.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/examples/names.cc Tue Jan 20 17:39:18 2009 -0800 @@ -22,7 +22,6 @@ // LAN // -#include #include "ns3/core-module.h" #include "ns3/simulator-module.h" #include "ns3/helper-module.h" @@ -40,25 +39,13 @@ int int main (int argc, char *argv[]) { - // - // Users may find it convenient to turn on explicit debugging - // for selected modules; the below lines suggest how to do this - // #if 1 LogComponentEnable ("NamesExample", LOG_LEVEL_INFO); #endif - // - // Allow the user to override any of the defaults and the above Bind() at - // run-time, via command-line arguments - // CommandLine cmd; cmd.Parse (argc, argv); - // - // Explicitly create the nodes required by the topology (shown above). - // - NS_LOG_INFO ("Create nodes."); NodeContainer n; n.Create (4); @@ -75,7 +62,6 @@ main (int argc, char *argv[]) InternetStackHelper internet; internet.Install (n); - NS_LOG_INFO ("Create devices."); CsmaHelper csma; csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000))); csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2))); @@ -94,31 +80,19 @@ main (int argc, char *argv[]) Names::Add ("/Names/server", "eth0", d.Get (1)); Ipv4AddressHelper ipv4; - - // - // We've got the "hardware" in place. Now we need to add IP addresses. - // - NS_LOG_INFO ("Assign IP Addresses."); ipv4.SetBase ("10.1.1.0", "255.255.255.0"); Ipv4InterfaceContainer i = ipv4.Assign (d); - NS_LOG_INFO ("Create Applications."); - + uint16_t port = 9; + UdpEchoServerHelper server (port); // - // Create a UdpEchoServer application on the server node. Note that we - // reference the server node by name in the Install method below. + // Install the UdpEchoServer application on the server node using its name + // directly. // - uint16_t port = 9; // well-known echo port number - UdpEchoServerHelper server (port); - ApplicationContainer apps = server.Install (Names::Find ("/Names/server")); + ApplicationContainer apps = server.Install ("/Names/server"); apps.Start (Seconds (1.0)); apps.Stop (Seconds (10.0)); - // - // Create a UdpEchoClient application to send UDP datagrams from node zero to - // node one. Notice that we reference the client node by name in the Install - // method below. - // uint32_t packetSize = 1024; uint32_t maxPacketCount = 1; Time interPacketInterval = Seconds (1.); @@ -126,17 +100,20 @@ main (int argc, char *argv[]) client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount)); client.SetAttribute ("Interval", TimeValue (interPacketInterval)); client.SetAttribute ("PacketSize", UintegerValue (packetSize)); - apps = client.Install (Names::Find ("/Names/client")); + // + // Install the UdpEchoClient application on the server node using its name + // directly. + // + apps = client.Install ("/Names/client"); apps.Start (Seconds (2.0)); apps.Stop (Seconds (10.0)); + // + // Use the config system to connect a trace source using the object name + // system to specify the path. + // Config::Connect ("/Names/client/eth0/Rx", MakeCallback (&RxEvent)); - // - // Now, do the actual simulation. - // - NS_LOG_INFO ("Run Simulation."); Simulator::Run (); Simulator::Destroy (); - NS_LOG_INFO ("Done."); } diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/application-container.cc --- a/src/helper/application-container.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/application-container.cc Tue Jan 20 17:39:18 2009 -0800 @@ -17,6 +17,8 @@ * * Author: Mathieu Lacage */ + +#include "ns3/object-names.h" #include "application-container.h" namespace ns3 { @@ -28,6 +30,13 @@ ApplicationContainer::ApplicationContain { m_applications.push_back (app); } + +ApplicationContainer::ApplicationContainer (std::string name) +{ + Ptr app = Names::Find (name); + m_applications.push_back (app); +} + ApplicationContainer::Iterator ApplicationContainer::Begin (void) const @@ -63,6 +72,12 @@ ApplicationContainer::Add (Ptr application = Names::Find (name); + m_applications.push_back (application); +} void ApplicationContainer::Start (Time start) diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/application-container.h --- a/src/helper/application-container.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/application-container.h Tue Jan 20 17:39:18 2009 -0800 @@ -17,6 +17,7 @@ * * Author: Mathieu Lacage */ + #ifndef APPLICATION_CONTAINER_H #define APPLICATION_CONTAINER_H @@ -45,6 +46,13 @@ public: */ ApplicationContainer (Ptr application); + /** + * Create an ApplicationContainer with exactly one application + * + * \param name The name of the application object to add to the container + */ + ApplicationContainer (std::string name); + typedef std::vector >::const_iterator Iterator; /** @@ -57,27 +65,33 @@ public: Iterator End (void) const; /** - * \returns the number of netdevice pointers stored in this container. + * \returns the number of application pointers stored in this container. */ uint32_t GetN (void) const; /** - * \param i the index of the requested netdevice pointer. - * \returns the requested netdevice pointer. + * \param i the index of the requested application pointer. + * \returns the requested application pointer. */ Ptr Get (uint32_t i) const; /** - * \param other another netdevice container + * Append to the end of this container the other input container. * - * Append to the end of this container the other input container. + * \param other another application container */ void Add (ApplicationContainer other); /** + * Append to the end of this container the input application pointer. + * * \param application another netdevice pointer. - * - * Append to the end of this container the input netdevice pointer. */ void Add (Ptr application); + /** + * Append to the end of this container the application specified by the name. + * + * \param name The name of the application object to add to the container. + */ + void Add (std::string name); void Start (Time start); void Stop (Time stop); diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/bridge-helper.cc --- a/src/helper/bridge-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/bridge-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -20,6 +20,7 @@ #include "ns3/log.h" #include "ns3/bridge-net-device.h" #include "ns3/node.h" +#include "ns3/object-names.h" NS_LOG_COMPONENT_DEFINE ("BridgeHelper"); @@ -57,4 +58,12 @@ BridgeHelper::Install (Ptr node, N return devs; } +NetDeviceContainer +BridgeHelper::Install (std::string nodeName, NetDeviceContainer c) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr node = Names::Find (nodeName); + return Install (node, c); +} + } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/bridge-helper.h --- a/src/helper/bridge-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/bridge-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -16,6 +16,7 @@ public: BridgeHelper (); void SetDeviceAttribute (std::string n1, const AttributeValue &v1); NetDeviceContainer Install (Ptr node, NetDeviceContainer c); + NetDeviceContainer Install (std::string nodeName, NetDeviceContainer c); private: ObjectFactory m_deviceFactory; }; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/csma-helper.cc --- a/src/helper/csma-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/csma-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -26,6 +26,7 @@ #include "ns3/pcap-writer.h" #include "ns3/config.h" #include "ns3/packet.h" +#include "ns3/object-names.h" #include namespace ns3 { @@ -181,8 +182,37 @@ CsmaHelper::Install (Ptr node) con } NetDeviceContainer +CsmaHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + return Install (node); +} + +NetDeviceContainer CsmaHelper::Install (Ptr node, Ptr channel) const { + return NetDeviceContainer (InstallPriv (node, channel)); +} + +NetDeviceContainer +CsmaHelper::Install (Ptr node, std::string channelName) const +{ + Ptr channel = Names::Find (channelName); + return NetDeviceContainer (InstallPriv (node, channel)); +} + +NetDeviceContainer +CsmaHelper::Install (std::string nodeName, Ptr channel) const +{ + Ptr node = Names::Find (nodeName); + return NetDeviceContainer (InstallPriv (node, channel)); +} + +NetDeviceContainer +CsmaHelper::Install (std::string nodeName, std::string channelName) const +{ + Ptr node = Names::Find (nodeName); + Ptr channel = Names::Find (channelName); return NetDeviceContainer (InstallPriv (node, channel)); } @@ -205,6 +235,13 @@ CsmaHelper::Install (const NodeContainer } return devs; +} + +NetDeviceContainer +CsmaHelper::Install (const NodeContainer &c, std::string channelName) const +{ + Ptr channel = Names::Find (channelName); + return Install (c, channel); } Ptr @@ -231,6 +268,14 @@ CsmaHelper::InstallStar (Ptr hub, hubDevices.Add (nd.Get (0)); spokeDevices.Add (nd.Get (1)); } +} + +void +CsmaHelper::InstallStar (std::string hubName, NodeContainer spokes, + NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices) +{ + Ptr hub = Names::Find (hubName); + InstallStar (hub, spokes, hubDevices, spokeDevices); } void diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/csma-helper.h --- a/src/helper/csma-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/csma-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -172,15 +172,59 @@ public: NetDeviceContainer Install (Ptr node) const; /** + * This method creates an ns3::CsmaChannel with the attributes configured by + * CsmaHelper::SetChannelAttribute, an ns3::CsmaNetDevice with the attributes + * configured by CsmaHelper::SetDeviceAttribute and then adds the device + * to the node and attaches the channel to the device. + * + * \param name The name of the node to install the device in + * \returns A containter holding the added net device. + */ + NetDeviceContainer Install (std::string name) const; + + /** * This method creates an ns3::CsmaNetDevice with the attributes configured by * CsmaHelper::SetDeviceAttribute and then adds the device to the node and * attaches the provided channel to the device. * * \param node The node to install the device in + * \param channel The channel to attach to the device. + * \returns A containter holding the added net device. + */ + NetDeviceContainer Install (Ptr node, Ptr channel) const; + + /** + * This method creates an ns3::CsmaNetDevice with the attributes configured by + * CsmaHelper::SetDeviceAttribute and then adds the device to the node and + * attaches the provided channel to the device. + * + * \param node The node to install the device in + * \param channelName The name of the channel to attach to the device. + * \returns A containter holding the added net device. + */ + NetDeviceContainer Install (Ptr node, std::string channelName) const; + + /** + * This method creates an ns3::CsmaNetDevice with the attributes configured by + * CsmaHelper::SetDeviceAttribute and then adds the device to the node and + * attaches the provided channel to the device. + * + * \param nodeName The name of the node to install the device in * \param channel The chanel to attach to the device. * \returns A containter holding the added net device. */ - NetDeviceContainer Install (Ptr node, Ptr channel) const; + NetDeviceContainer Install (std::string nodeName, Ptr channel) const; + + /** + * This method creates an ns3::CsmaNetDevice with the attributes configured by + * CsmaHelper::SetDeviceAttribute and then adds the device to the node and + * attaches the provided channel to the device. + * + * \param nodeName The name of the node to install the device in + * \param channelName The name of the chanel to attach to the device. + * \returns A containter holding the added net device. + */ + NetDeviceContainer Install (std::string nodeName, std::string channelName) const; /** * This method creates an ns3::CsmaChannel with the attributes configured by @@ -205,6 +249,18 @@ public: * \returns A containter holding the added net devices. */ NetDeviceContainer Install (const NodeContainer &c, Ptr channel) const; + + /** + * For each Ptr in the provided container, this method creates an + * ns3::CsmaNetDevice (with the attributes configured by + * CsmaHelper::SetDeviceAttribute); adds the device to the node; and attaches + * the provided channel to the device. + * + * \param c The NodeContainer holding the nodes to be changed. + * \param channelName The name of the channel to attach to the devices. + * \returns A containter holding the added net devices. + */ + NetDeviceContainer Install (const NodeContainer &c, std::string channelName) const; /** * \brief Make a star network topology. @@ -239,6 +295,39 @@ public: void InstallStar (Ptr hub, NodeContainer spokes, NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices); + /** + * \brief Make a star network topology. + * + * Given a pointer to a node that will become the hub of the star, and a + * NodeContainer containing pointers to the nodes that will become the + * spokes; we construct CSMA net devices on the hub (corresponding to the + * spokes) and store them in the hubDevices NetDeviceContainer. We add a + * net device to each spoke node and store them in the spokeDevices + * NetDeviceContainer. A CSMA is created for each spoke. + * + * Usually when one thinks of a star network, one thinks of point-to-point + * links. We're just using a single pair of devices on a multi-point-to-point + * network "drops" as the link. You are free to add any number of other + * devices on the link if you want. + * + * The ordering of the devices in the hubDevices container is according to + * the order of the spokes container -- that is, hubDevices[0] will be the + * net device used on the hub that talks to spokes[0]. the container entry + * spokeDevices[0] will have the device that hubDevices[0] talks to -- those + * two devices are the ones that connect hub to spokes[0]. + * + * \param hubName The name of the central node of the star network + * \param spokes A NodeContainer of the nodes that will be the spoke (leaf) + * nodes + * \param hubDevices A NetDeviceContainer that will be filled with pointers + * to the point-to-point net devices created on the hub. + * \param spokeDevices A NetDeviceContainer that will be filled with pointers + * to the point-to-point net devices created on each of + * the spokes. + */ + void InstallStar (std::string hubName, NodeContainer spokes, + NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices); + private: Ptr InstallPriv (Ptr node, Ptr channel) const; @@ -253,7 +342,6 @@ private: ObjectFactory m_channelFactory; }; - } // namespace ns3 #endif /* CSMA_HELPER_H */ diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/emu-helper.cc --- a/src/helper/emu-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/emu-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -21,6 +21,7 @@ #include "ns3/log.h" #include "ns3/simulator.h" #include "ns3/object-factory.h" +#include "ns3/object-names.h" #include "ns3/queue.h" #include "ns3/emu-net-device.h" #include "ns3/pcap-writer.h" @@ -194,6 +195,13 @@ EmuHelper::Install (Ptr node) cons return NetDeviceContainer (InstallPriv (node)); } +NetDeviceContainer +EmuHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + return NetDeviceContainer (InstallPriv (node)); +} + NetDeviceContainer EmuHelper::Install (const NodeContainer &c) const { diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/emu-helper.h --- a/src/helper/emu-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/emu-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -164,6 +164,15 @@ public: NetDeviceContainer Install (Ptr node) const; /** + * This method creates an ns3::EmuNetDevice with the attributes configured by + * EmuHelper::SetDeviceAttribute and then adds the device to the node. + * + * \param nodeName The name of the node to install the device in + * \returns A containter holding the added net device. + */ + NetDeviceContainer Install (std::string nodeName) const; + + /** * For each Ptr in the provided container this method creates an * ns3::EmuNetDevice (with the attributes configured by * EmuHelper::SetDeviceAttribute); adds the device to the node. diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/internet-stack-helper.cc --- a/src/helper/internet-stack-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/internet-stack-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -21,6 +21,7 @@ #include "ns3/assert.h" #include "ns3/log.h" #include "ns3/object.h" +#include "ns3/object-names.h" #include "ns3/ipv4.h" #include "internet-stack-helper.h" #include "ns3/internet-stack.h" @@ -91,6 +92,12 @@ InternetStackHelper::Install (Ptr node->AggregateObject (factory); } +void +InternetStackHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); +} void InternetStackHelper::EnableAscii (std::ostream &os, NodeContainer n) { diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/internet-stack-helper.h --- a/src/helper/internet-stack-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/internet-stack-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -35,6 +35,15 @@ class InternetStackHelper { public: InternetStackHelper(void); + + /** + * Aggregate implementations of the ns3::Ipv4, ns3::Udp, and ns3::Tcp classes + * onto the provided node. This method will assert if called on a node that + * already has an Ipv4 object aggregated to it. + * + * \param nodeName The name of the node on which to install the stack. + */ + void Install (std::string nodeName) const; /** * Aggregate implementations of the ns3::Ipv4, ns3::Udp, and ns3::Tcp classes diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/ipv4-interface-container.cc --- a/src/helper/ipv4-interface-container.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/ipv4-interface-container.cc Tue Jan 20 17:39:18 2009 -0800 @@ -1,5 +1,6 @@ #include "ipv4-interface-container.h" #include "ns3/node-list.h" +#include "ns3/object-names.h" namespace ns3 { @@ -40,5 +41,11 @@ Ipv4InterfaceContainer::Add (Ptr i { m_interfaces.push_back (std::make_pair (ipv4, interface)); } +void +Ipv4InterfaceContainer::Add (std::string ipv4Name, uint32_t interface) +{ + Ptr ipv4 = Names::Find (ipv4Name); + m_interfaces.push_back (std::make_pair (ipv4, interface)); +} } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/ipv4-interface-container.h --- a/src/helper/ipv4-interface-container.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/ipv4-interface-container.h Tue Jan 20 17:39:18 2009 -0800 @@ -34,6 +34,7 @@ public: void SetMetric (uint32_t i, uint16_t metric); void Add (Ptr ipv4, uint32_t interface); + void Add (std::string ipv4Name, uint32_t interface); private: diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/mobility-helper.cc --- a/src/helper/mobility-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/mobility-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -25,6 +25,7 @@ #include "ns3/pointer.h" #include "ns3/config.h" #include "ns3/simulator.h" +#include "ns3/object-names.h" #include namespace ns3 { @@ -43,6 +44,12 @@ void void MobilityHelper::SetPositionAllocator (Ptr allocator) { + m_position = allocator; +} +void +MobilityHelper::SetPositionAllocator (std::string allocatorName) +{ + Ptr allocator = Names::Find (allocatorName); m_position = allocator; } void @@ -101,6 +108,14 @@ MobilityHelper::PushReferenceMobilityMod Ptr mobility = reference->GetObject (); m_mobilityStack.push_back (mobility); } + +void +MobilityHelper::PushReferenceMobilityModel (std::string referenceName) +{ + Ptr mobility = Names::Find (referenceName); + m_mobilityStack.push_back (mobility); +} + void MobilityHelper::PopReferenceMobilityModel (void) { @@ -147,6 +162,12 @@ MobilityHelper::Install (Ptr node) model->SetPosition (position); } +void +MobilityHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); +} void MobilityHelper::Install (NodeContainer c) const { diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/mobility-helper.h --- a/src/helper/mobility-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/mobility-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -50,6 +50,13 @@ public: * \param allocator allocate initial node positions */ void SetPositionAllocator (Ptr allocator); + /** + * Set the position allocator which will be used to allocate the initial + * position of every node initialized during MobilityModel::Install. + * + * \param allocator allocate initial node positions + */ + void SetPositionAllocator (std::string allocatorName); /** * \param type the type of mobility model to use. @@ -138,6 +145,25 @@ public: */ void PushReferenceMobilityModel (Ptr reference); /** + * \param reference item to push. + * + * Push an item on the top of the stack of "reference mobility models". + * The input item should be a node instance to which a mobility model + * has already been aggregated (usually by a call to Install). + * + * If this this stack is not empty when MobilityHelper::Install + * is called, the model from the top of the stack is used + * to create a ns3::HierarchicalMobilityModel to make the + * newly-created models define their positions relative to that + * of the parent mobility model. + * + * This method is typically used to create hierarchical mobility + * patterns and positions by starting with the large-scale mobility + * features, and, then, defining the smaller-scale movements relative + * to a few reference points in the large-scale model. + */ + void PushReferenceMobilityModel (std::string referenceName); + /** * Remove the top item from the top of the stack of * "reference mobility models". */ @@ -161,6 +187,18 @@ public: * \param node The node to "layout." */ void Install (Ptr node) const; + /** + * \brief "Layout" a single node according to the current position allocator + * type. + * + * This method creates an instance of a ns3::MobilityModel subclass (the + * type of which was set with MobilityHelper::SetMobilityModel), aggregates + * it to the provided node, and sets an initial position based on the current + * position allocator (set through MobilityHelper::SetPositionAllocator). + * + * \param nodeName The name of the node to "layout." + */ + void Install (std::string nodeName) const; /** * \brief Layout a collection of nodes according to the current position allocator diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/net-device-container.cc --- a/src/helper/net-device-container.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/net-device-container.cc Tue Jan 20 17:39:18 2009 -0800 @@ -17,7 +17,9 @@ * * Author: Mathieu Lacage */ + #include "net-device-container.h" +#include "ns3/object-names.h" namespace ns3 { @@ -25,6 +27,11 @@ NetDeviceContainer::NetDeviceContainer ( {} NetDeviceContainer::NetDeviceContainer (Ptr dev) { + m_devices.push_back (dev); +} +NetDeviceContainer::NetDeviceContainer (std::string devName) +{ + Ptr dev = Names::Find (devName); m_devices.push_back (dev); } NetDeviceContainer::NetDeviceContainer (const NetDeviceContainer &a, const NetDeviceContainer &b) @@ -68,5 +75,11 @@ NetDeviceContainer::Add (Ptr { m_devices.push_back (device); } +void +NetDeviceContainer::Add (std::string deviceName) +{ + Ptr device = Names::Find (deviceName); + m_devices.push_back (device); +} } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/net-device-container.h --- a/src/helper/net-device-container.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/net-device-container.h Tue Jan 20 17:39:18 2009 -0800 @@ -46,6 +46,12 @@ public: */ NetDeviceContainer (Ptr dev); /** + * \param devName The name of a device to add to the container + * + * Create a NetDeviceContainer with exactly one device + */ + NetDeviceContainer (std::string devName); + /** * \param a a device container * \param b another device container * @@ -93,6 +99,12 @@ public: * Append to the end of this container the input netdevice pointer. */ void Add (Ptr device); + /** + * \param deviceName The name of another netdevice to add. + * + * Append to the end of this container the input netdevice pointer. + */ + void Add (std::string deviceName); private: std::vector > m_devices; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/node-container.cc --- a/src/helper/node-container.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/node-container.cc Tue Jan 20 17:39:18 2009 -0800 @@ -19,6 +19,7 @@ */ #include "node-container.h" #include "ns3/node-list.h" +#include "ns3/object-names.h" namespace ns3 { @@ -27,6 +28,11 @@ NodeContainer::NodeContainer () NodeContainer::NodeContainer (Ptr node) { + m_nodes.push_back (node); +} +NodeContainer::NodeContainer (std::string nodeName) +{ + Ptr node = Names::Find (nodeName); m_nodes.push_back (node); } NodeContainer::NodeContainer (const NodeContainer &a, const NodeContainer &b) @@ -103,6 +109,12 @@ NodeContainer::Add (Ptr node) { m_nodes.push_back (node); } +void +NodeContainer::Add (std::string nodeName) +{ + Ptr node = Names::Find (nodeName); + m_nodes.push_back (node); +} NodeContainer NodeContainer::GetGlobal (void) diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/node-container.h --- a/src/helper/node-container.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/node-container.h Tue Jan 20 17:39:18 2009 -0800 @@ -45,6 +45,12 @@ public: * Create a NodeContainer with exactly one node. */ NodeContainer (Ptr node); + /** + * \param nodeName The name of a node to add to the container + * + * Create a NodeContainer with exactly one node. + */ + NodeContainer (std::string nodeName); /** * \param a a node container * \param b another node container @@ -105,6 +111,12 @@ public: * Append the input node pointer at the end of this NodeContainer. */ void Add (Ptr node); + /** + * \param nodeName The name of a node + * + * Append the input node pointer at the end of this NodeContainer. + */ + void Add (std::string nodeName); /** * \returns a container which contains a list of _all_ nodes diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/olsr-helper.cc --- a/src/helper/olsr-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/olsr-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -20,6 +20,7 @@ #include "olsr-helper.h" #include "ns3/olsr-agent.h" #include "ns3/node-list.h" +#include "ns3/object-names.h" namespace ns3 { @@ -74,6 +75,12 @@ OlsrHelper::Install (Ptr node) agent->Start (); } void +OlsrHelper::Install (std::string nodeName) +{ + Ptr node = Names::Find (nodeName); + Install (node); +} +void OlsrHelper::InstallAll (void) { Install (NodeContainer::GetGlobal ()); diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/olsr-helper.h --- a/src/helper/olsr-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/olsr-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -56,6 +56,10 @@ public: */ void Install (Ptr node); /** + * \brief Enable OLSR routing for a single node + */ + void Install (std::string nodeName); + /** * \brief Enable OLSR routing for all nodes */ void InstallAll (void); diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/on-off-helper.cc --- a/src/helper/on-off-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/on-off-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -21,6 +21,7 @@ #include "ns3/inet-socket-address.h" #include "ns3/packet-socket-address.h" #include "ns3/string.h" +#include "ns3/object-names.h" namespace ns3 { @@ -40,6 +41,13 @@ ApplicationContainer ApplicationContainer OnOffHelper::Install (Ptr node) const { + return ApplicationContainer (InstallPriv (node)); +} + +ApplicationContainer +OnOffHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); return ApplicationContainer (InstallPriv (node)); } diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/on-off-helper.h --- a/src/helper/on-off-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/on-off-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -72,6 +72,15 @@ public: */ ApplicationContainer Install (Ptr node) const; + /** + * Install an ns3::OnOffApplication on the node configured with all the + * attributes set with SetAttribute. + * + * \param node The node on which an OnOffApplication will be installed. + * \returns Container of Ptr to the applications installed. + */ + ApplicationContainer Install (std::string nodeName) const; + private: /** * Install an ns3::OnOffApplication on the node configured with all the diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/packet-sink-helper.cc --- a/src/helper/packet-sink-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/packet-sink-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -21,6 +21,7 @@ #include "packet-sink-helper.h" #include "ns3/string.h" #include "ns3/inet-socket-address.h" +#include "ns3/object-names.h" namespace ns3 { @@ -56,6 +57,13 @@ ApplicationContainer ApplicationContainer PacketSinkHelper::Install (Ptr node) const { + return ApplicationContainer (InstallPriv (node)); +} + +ApplicationContainer +PacketSinkHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); return ApplicationContainer (InstallPriv (node)); } diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/packet-sink-helper.h --- a/src/helper/packet-sink-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/packet-sink-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -47,9 +47,16 @@ public: * Install an ns3::PacketSinkApplication on each node of the input container * configured with all the attributes set with SetAttribute. * - * \param c The node on which a PacketSinkApplication will be installed. + * \param node The node on which a PacketSinkApplication will be installed. */ ApplicationContainer Install (Ptr node) const; + /** + * Install an ns3::PacketSinkApplication on each node of the input container + * configured with all the attributes set with SetAttribute. + * + * \param nodeName The name of the node on which a PacketSinkApplication will be installed. + */ + ApplicationContainer Install (std::string nodeName) const; private: Ptr InstallPriv (Ptr node) const; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/packet-socket-helper.cc --- a/src/helper/packet-socket-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/packet-socket-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -20,6 +20,7 @@ #include "packet-socket-helper.h" #include "ns3/packet-socket-factory.h" +#include "ns3/object-names.h" namespace ns3 { @@ -35,8 +36,15 @@ void void PacketSocketHelper::Install (Ptr node) const { - Ptr factory = CreateObject (); - node->AggregateObject (factory); + Ptr factory = CreateObject (); + node->AggregateObject (factory); +} + +void +PacketSocketHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + Install (node); } } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/packet-socket-helper.h --- a/src/helper/packet-socket-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/packet-socket-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -40,6 +40,14 @@ public: void Install (Ptr node) const; /** + * Aggregate an instance of a ns3::PacketSocketFactory onto the provided + * node. + * + * \param nodeName The name of the node on which to aggregate the ns3::PacketSocketFactory. + */ + void Install (std::string nodeName) const; + + /** * For each node in the provided container, aggregate an instance of a * ns3::PacketSocketFactory. * diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/point-to-point-helper.cc --- a/src/helper/point-to-point-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/point-to-point-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -25,7 +25,7 @@ #include "ns3/pcap-writer.h" #include "ns3/config.h" #include "ns3/packet.h" - +#include "ns3/object-names.h" namespace ns3 { @@ -204,6 +204,28 @@ PointToPointHelper::Install (Ptr a return container; } +NetDeviceContainer +PointToPointHelper::Install (Ptr a, std::string bName) +{ + Ptr b = Names::Find (bName); + return Install (a, b); +} + +NetDeviceContainer +PointToPointHelper::Install (std::string aName, Ptr b) +{ + Ptr a = Names::Find (aName); + return Install (a, b); +} + +NetDeviceContainer +PointToPointHelper::Install (std::string aName, std::string bName) +{ + Ptr a = Names::Find (aName); + Ptr b = Names::Find (bName); + return Install (a, b); +} + void PointToPointHelper::InstallStar (Ptr hub, NodeContainer spokes, NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices) @@ -214,6 +236,14 @@ PointToPointHelper::InstallStar (Ptr hub = Names::Find (hubName); + InstallStar (hub, spokes, hubDevices, spokeDevices); } void diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/point-to-point-helper.h --- a/src/helper/point-to-point-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/point-to-point-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -180,6 +180,30 @@ public: NetDeviceContainer Install (Ptr a, Ptr b); /** + * \param a first node + * \param bName name of second node + * + * Saves you from having to construct a temporary NodeContainer. + */ + NetDeviceContainer Install (Ptr a, std::string bName); + + /** + * \param aName Name of first node + * \param b second node + * + * Saves you from having to construct a temporary NodeContainer. + */ + NetDeviceContainer Install (std::string aName, Ptr b); + + /** + * \param aName Name of first node + * \param bName Name of second node + * + * Saves you from having to construct a temporary NodeContainer. + */ + NetDeviceContainer Install (std::string aNode, std::string bNode); + + /** * \brief Make a star network topology. * * Given a pointer to a node that will become the hub of the star, and a @@ -207,6 +231,34 @@ public: void InstallStar (Ptr hub, NodeContainer spokes, NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices); + /** + * \brief Make a star network topology. + * + * Given a pointer to a node that will become the hub of the star, and a + * NodeContainer containing pointers to the nodes that will become the + * spokes; we construct point to point net devices on the hub (corresponding + * to the spokes) and store them in the hubDevices NetDeviceContainer. We + * add a net device to each spoke node and store them in the spokeDevices + * NetDeviceContainer. A point-to-point channel is created for each spoke. + * + * The ordering of the devices in the hubDevices container is according to + * the order of the spokes container -- that is, hubDevices[0] will be the + * net device used on the hub that talks to spokes[0]. the container entry + * spokeDevices[0] will have the device that hubDevices[0] talks to -- those + * two devices are the ones that connect hub to spokes[0]. + * + * \param hubName The name of the central node of the star network + * \param spokes A NodeContainer of the nodes that will be the spoke (leaf) + * nodes + * \param hubDevices A NetDeviceContainer that will be filled with pointers + * to the point-to-point net devices created on the hub. + * \param spokeDevices A NetDeviceContainer that will be filled with pointers + * to the point-to-point net devices created on each of + * the spokes. + */ + void InstallStar (std::string hubName, NodeContainer spokes, + NetDeviceContainer& hubDevices, NetDeviceContainer& spokeDevices); + private: void EnablePcap (Ptr node, Ptr device, Ptr queue); void EnableAscii (Ptr node, Ptr device); diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/static-multicast-route-helper.cc --- a/src/helper/static-multicast-route-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/static-multicast-route-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -23,6 +23,7 @@ #include "ns3/assert.h" #include "ns3/ipv4-address.h" #include "ns3/ipv4.h" +#include "ns3/object-names.h" #include "static-multicast-route-helper.h" namespace ns3 { @@ -53,6 +54,43 @@ StaticMulticastRouteHelper::AddMulticast ipv4->AddMulticastRoute (source, group, iifIndex, outputInterfaces); } +void +StaticMulticastRouteHelper::AddMulticastRoute ( + Ptr n, + Ipv4Address source, + Ipv4Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + AddMulticastRoute (n, source, group, input, output); +} + +void +StaticMulticastRouteHelper::AddMulticastRoute ( + std::string nName, + Ipv4Address source, + Ipv4Address group, + Ptr input, + NetDeviceContainer output) +{ + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + +void +StaticMulticastRouteHelper::AddMulticastRoute ( + std::string nName, + Ipv4Address source, + Ipv4Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + void StaticMulticastRouteHelper::SetDefaultMulticastRoute ( Ptr n, @@ -61,6 +99,34 @@ StaticMulticastRouteHelper::SetDefaultMu Ptr ipv4 = n->GetObject (); uint32_t ifIndexSrc = ipv4->FindInterfaceForDevice (nd); ipv4->SetDefaultMulticastRoute (ifIndexSrc); +} + +void +StaticMulticastRouteHelper::SetDefaultMulticastRoute ( + Ptr n, + std::string ndName) +{ + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); +} + +void +StaticMulticastRouteHelper::SetDefaultMulticastRoute ( + std::string nName, + Ptr nd) +{ + Ptr n = Names::Find (nName); + SetDefaultMulticastRoute (n, nd); +} + +void +StaticMulticastRouteHelper::SetDefaultMulticastRoute ( + std::string nName, + std::string ndName) +{ + Ptr n = Names::Find (nName); + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); } void @@ -73,5 +139,15 @@ StaticMulticastRouteHelper::JoinMulticas ipv4->JoinMulticastGroup (source, group); } +void +StaticMulticastRouteHelper::JoinMulticastGroup ( + std::string nName, + Ipv4Address source, + Ipv4Address group) +{ + Ptr n = Names::Find (nName); + JoinMulticastGroup (n, source, group); +} + } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/static-multicast-route-helper.h --- a/src/helper/static-multicast-route-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/static-multicast-route-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -34,13 +34,22 @@ public: public: StaticMulticastRouteHelper (); - void AddMulticastRoute (Ptr, Ipv4Address source, Ipv4Address group, + void AddMulticastRoute (Ptr n, Ipv4Address source, Ipv4Address group, Ptr input, NetDeviceContainer output); + void AddMulticastRoute (std::string n, Ipv4Address source, Ipv4Address group, + Ptr input, NetDeviceContainer output); + void AddMulticastRoute (Ptr n, Ipv4Address source, Ipv4Address group, + std::string inputName, NetDeviceContainer output); + void AddMulticastRoute (std::string nName, Ipv4Address source, Ipv4Address group, + std::string inputName, NetDeviceContainer output); void SetDefaultMulticastRoute (Ptr n, Ptr nd); + void SetDefaultMulticastRoute (Ptr n, std::string ndName); + void SetDefaultMulticastRoute (std::string nName, Ptr nd); + void SetDefaultMulticastRoute (std::string nName, std::string ndName); void JoinMulticastGroup (Ptr n, Ipv4Address source, Ipv4Address group); - + void JoinMulticastGroup (std::string nName, Ipv4Address source, Ipv4Address group); }; } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/udp-echo-helper.cc --- a/src/helper/udp-echo-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/udp-echo-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -21,6 +21,7 @@ #include "ns3/udp-echo-server.h" #include "ns3/udp-echo-client.h" #include "ns3/uinteger.h" +#include "ns3/object-names.h" namespace ns3 { @@ -41,6 +42,13 @@ ApplicationContainer ApplicationContainer UdpEchoServerHelper::Install (Ptr node) const { + return ApplicationContainer (InstallPriv (node)); +} + +ApplicationContainer +UdpEchoServerHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); return ApplicationContainer (InstallPriv (node)); } @@ -87,6 +95,13 @@ UdpEchoClientHelper::Install (Ptr } ApplicationContainer +UdpEchoClientHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + return ApplicationContainer (InstallPriv (node)); +} + +ApplicationContainer UdpEchoClientHelper::Install (NodeContainer c) const { ApplicationContainer apps; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/udp-echo-helper.h --- a/src/helper/udp-echo-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/udp-echo-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -36,6 +36,7 @@ public: void SetAttribute (std::string name, const AttributeValue &value); ApplicationContainer Install (Ptr node) const; + ApplicationContainer Install (std::string nodeName) const; ApplicationContainer Install (NodeContainer c) const; private: @@ -52,6 +53,7 @@ public: void SetAttribute (std::string name, const AttributeValue &value); ApplicationContainer Install (Ptr node) const; + ApplicationContainer Install (std::string nodeName) const; ApplicationContainer Install (NodeContainer c) const; private: diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/v4ping-helper.cc --- a/src/helper/v4ping-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/v4ping-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -1,5 +1,26 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + #include "v4ping-helper.h" #include "ns3/v4ping.h" +#include "ns3/object-names.h" namespace ns3 { @@ -18,6 +39,13 @@ ApplicationContainer ApplicationContainer V4PingHelper::Install (Ptr node) const { + return ApplicationContainer (InstallPriv (node)); +} + +ApplicationContainer +V4PingHelper::Install (std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); return ApplicationContainer (InstallPriv (node)); } diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/v4ping-helper.h --- a/src/helper/v4ping-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/v4ping-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -16,6 +16,7 @@ public: ApplicationContainer Install (NodeContainer nodes) const; ApplicationContainer Install (Ptr node) const; + ApplicationContainer Install (std::string nodeName) const; private: Ptr InstallPriv (Ptr node) const; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/wifi-helper.cc --- a/src/helper/wifi-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/wifi-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -31,8 +31,7 @@ #include "ns3/pcap-writer.h" #include "ns3/config.h" #include "ns3/simulator.h" - - +#include "ns3/object-names.h" NS_LOG_COMPONENT_DEFINE ("WifiHelper"); @@ -126,6 +125,11 @@ WifiHelper::Install (const WifiPhyHelper { return Install (phy, NodeContainer (node)); } - +NetDeviceContainer +WifiHelper::Install (const WifiPhyHelper &phy, std::string nodeName) const +{ + Ptr node = Names::Find (nodeName); + return Install (phy, NodeContainer (node)); +} } // namespace ns3 diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/wifi-helper.h --- a/src/helper/wifi-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/wifi-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -153,6 +153,12 @@ public: * \returns a device container which contains all the devices created by this method. */ NetDeviceContainer Install (const WifiPhyHelper &phy, Ptr node) const; + /** + * \param phy the PHY helper to create PHY objects + * \param nodeName the name of node on which a wifi device must be created + * \returns a device container which contains all the devices created by this method. + */ + NetDeviceContainer Install (const WifiPhyHelper &phy, std::string nodeName) const; private: ObjectFactory m_stationManager; diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/yans-wifi-helper.cc --- a/src/helper/yans-wifi-helper.cc Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/yans-wifi-helper.cc Tue Jan 20 17:39:18 2009 -0800 @@ -27,6 +27,7 @@ #include "ns3/pcap-writer.h" #include "ns3/simulator.h" #include "ns3/config.h" +#include "ns3/object-names.h" namespace ns3 { @@ -164,6 +165,12 @@ YansWifiPhyHelper::SetChannel (Ptr channel = Names::Find (channelName); + m_channel = channel; +} +void YansWifiPhyHelper::Set (std::string name, const AttributeValue &v) { m_phy.Set (name, v); @@ -191,7 +198,6 @@ YansWifiPhyHelper::SetErrorRateModel (st m_errorRateModel.Set (n6, v6); m_errorRateModel.Set (n7, v7); } - Ptr YansWifiPhyHelper::Create (Ptr node, Ptr device) const diff -r d45e62c78504 -r 6bbf05bf4826 src/helper/yans-wifi-helper.h --- a/src/helper/yans-wifi-helper.h Tue Jan 20 15:47:14 2009 -0800 +++ b/src/helper/yans-wifi-helper.h Tue Jan 20 17:39:18 2009 -0800 @@ -155,6 +155,12 @@ public: */ void SetChannel (Ptr channel); /** + * \param channelName The name of the channel to associate to this helper + * + * Every PHY created by a call to Install is associated to this channel. + */ + void SetChannel (std::string channelName); + /** * \param name the name of the attribute to set * \param v the value of the attribute * changeset: 4113:3f7f08d9daad user: Craig Dowell date: Tue Jan 20 18:29:06 2009 -0800 summary: make simple version of Names:Add even simpler. Use that in examples/names.cc diff -r 6bbf05bf4826 -r 3f7f08d9daad examples/names.cc --- a/examples/names.cc Tue Jan 20 17:39:18 2009 -0800 +++ b/examples/names.cc Tue Jan 20 18:29:06 2009 -0800 @@ -56,8 +56,8 @@ main (int argc, char *argv[]) // as the destination, so these will go into the name system as "/Names/client" // and "/Names/server". // - Names::Add ("/Names", "client", n.Get (0)); - Names::Add ("/Names", "server", n.Get (1)); + Names::Add ("/Names/client", n.Get (0)); + Names::Add ("/Names/server", n.Get (1)); InternetStackHelper internet; internet.Install (n); @@ -72,12 +72,12 @@ main (int argc, char *argv[]) // Add some human readable names for the devices we'll be interested in. // We add the names to the name space "under" the nodes we created above. // This has the effect of making "/Names/client/eth0" and "/Names/server/eth0" - // Note that the first parameter must reference a previously named object, + // Note that the first part of the path must reference a previously named object, // and we have, in fact, already named objects "/Names/client" and // "/Names/server" // - Names::Add ("/Names/client", "eth0", d.Get (0)); - Names::Add ("/Names/server", "eth0", d.Get (1)); + Names::Add ("/Names/client/eth0", d.Get (0)); + Names::Add ("/Names/server/eth0", d.Get (1)); Ipv4AddressHelper ipv4; ipv4.SetBase ("10.1.1.0", "255.255.255.0"); diff -r 6bbf05bf4826 -r 3f7f08d9daad src/core/object-names.cc --- a/src/core/object-names.cc Tue Jan 20 17:39:18 2009 -0800 +++ b/src/core/object-names.cc Tue Jan 20 18:29:06 2009 -0800 @@ -161,7 +161,55 @@ bool bool NamesPriv::Add (std::string name, Ptr object) { - return Add (Ptr (0, false), name, object); + NS_LOG_FUNCTION (name << object); + // + // This is the simple, easy to use version of Add, so we want it to be flexible. + // + // If we are provided a name that doesn't begin with "/Names", we assume + // that the caller has given us a shortname that she wants added to the root + // namespace. This results in a call to the "real" Add with context set to + // zero, indicating what we want to do. + // + // If we are given a name that begins with "/Names/" we assume that this is a + // fullname to the object we want to create. We split the fullname into a + // context string and and a final segment and then call the "Real" Add. + // + std::string namespaceName = "/Names"; + std::string::size_type offset = name.find (namespaceName); + if (offset == 0) + { + // + // This must be a fully qualified longname. All fully qualified names begin + // with "/Names". We have to split off the final segment which will become + // the shortname of the object. + // + std::string::size_type i = name.rfind ("/"); + NS_ASSERT_MSG (i != std::string::npos, "NamesPriv::Add(): Internal error. Can't find '/' in name"); + + // + // The slash we found cannot be the slash at the start of the namespaceName. + // This would indicate there is no shortname in the path at all. + // + NS_ASSERT_MSG (i != 0, "NamesPriv::Add(): Can't find a shortname in the name string"); + + // + // We now know where the context string starts and ends, and where the + // shortname starts and ends. All we have to do is to call our available + // function for creating addubg a shortname under a context string. + // + return Add (name.substr (0, i), name.substr (i + 1), object); + } + else + { + // + // This must be a shortname. Shortnames can't have ANY '/' characters in + // them since they are interpreted as a final segment of a fullname. A + // shortname in this context means creating a name in the root namespace. + // We indicate this by passing a zero context to the "real" add. + // + NS_ASSERT_MSG (offset == std::string::npos, "NamesPriv::Add(): Unexpected '/' in shortname"); + return Add (Ptr (0, false), name, object); + } } bool @@ -204,7 +252,7 @@ NamesPriv::Add (std::string context, std { if (context == "/Names") { - return Add (name, object); + return Add (Ptr (0, false), name, object); } return Add (FindObjectFromFullName (context), name, object); } @@ -589,11 +637,11 @@ NamesTest::RunTests (void) NS_TEST_ASSERT_EQUAL (foundObject, serverEth0); // - // We also have some syntactical sugary methods, so make sure they do what + // We also have some syntactically sugary methods, so make sure they do what // they should as well. // Ptr bridge = CreateObject (); - result = Names::Add ("/Names", "Bridge", client); + result = Names::Add ("/Names", "Bridge", bridge); NS_TEST_ASSERT_EQUAL (result, true); Ptr bridgeEth0 = CreateObject (); @@ -605,6 +653,20 @@ NamesTest::RunTests (void) foundObject = Names::Find ("/Names/Bridge/eth0"); NS_TEST_ASSERT_EQUAL (foundObject, bridgeEth0); + + Ptr wireless = CreateObject (); + result = Names::Add ("/Names/Wireless", wireless); + NS_TEST_ASSERT_EQUAL (result, true); + + Ptr wirelessAth0 = CreateObject (); + result = Names::Add ("/Names/Wireless/ath0", wirelessAth0); + NS_TEST_ASSERT_EQUAL (result, true); + + foundObject = Names::Find ("/Names/Wireless"); + NS_TEST_ASSERT_EQUAL (foundObject, wireless); + + foundObject = Names::Find ("/Names/Wireless/ath0"); + NS_TEST_ASSERT_EQUAL (foundObject, wirelessAth0); // // Run the simulator and destroy it to get the Destroy method called on the changeset: 4114:59f784af5db6 user: Craig Dowell date: Tue Jan 20 18:56:33 2009 -0800 summary: fix crasher in config diff -r 3f7f08d9daad -r 59f784af5db6 src/core/config.cc --- a/src/core/config.cc Tue Jan 20 18:29:06 2009 -0800 +++ b/src/core/config.cc Tue Jan 20 18:56:33 2009 -0800 @@ -332,8 +332,15 @@ Resolver::DoResolve (std::string path, P // // We're done with the object name service hooks, so proceed down the path - // of types and attributes. + // of types and attributes; but only if root is nonzero. If root is zero + // and we find ourselves here, we are trying to check in the namespace for + // a path that is not in the "/Names" namespace. We will have previously + // found any matches, so we just bail out. // + if (root == 0) + { + return; + } std::string::size_type dollarPos = item.find ("$"); if (dollarPos == 0) { changeset: 4115:7f7823a31f77 user: Craig Dowell date: Tue Jan 20 21:16:52 2009 -0800 summary: fix crasher in config unit tests diff -r 59f784af5db6 -r 7f7823a31f77 src/core/config.cc --- a/src/core/config.cc Tue Jan 20 18:56:33 2009 -0800 +++ b/src/core/config.cc Tue Jan 20 21:16:52 2009 -0800 @@ -287,9 +287,21 @@ Resolver::DoResolve (std::string path, P tmp = path.find ("/"); NS_ASSERT (tmp == 0); std::string::size_type next = path.find ("/", 1); + if (next == std::string::npos) { - DoResolveOne (root); + // + // If root is zero, we're beginning to see if we can use the object name + // service to resolve this path. It is impossible to have a object name + // associated with the root of the object name service since that root + // is not an object. This path must be referring to something in another + // namespace and it will have been found already since the name service + // is always consulted last. + // + if (root) + { + DoResolveOne (root); + } return; } std::string item = path.substr (1, next-1); changeset: 4116:c59fdf82869b user: Craig Dowell date: Tue Jan 20 21:55:04 2009 -0800 summary: add examples of Config::Set to example names.cc diff -r 7f7823a31f77 -r c59fdf82869b examples/names.cc --- a/examples/names.cc Tue Jan 20 21:16:52 2009 -0800 +++ b/examples/names.cc Tue Jan 20 21:55:04 2009 -0800 @@ -79,6 +79,23 @@ main (int argc, char *argv[]) Names::Add ("/Names/client/eth0", d.Get (0)); Names::Add ("/Names/server/eth0", d.Get (1)); + // + // You can use the object names that you've assigned in calls to the Config + // system to set Object Attributes. For example, you can set the Mtu + // Attribute of a Csma devices using the object naming service. + // + Config::Set ("/Names/client/eth0/Mtu", UintegerValue (1234)); + + // + // You can mix and match names and Attributes in calls to the Config system. + // For example, if "eth0" is a named object, you can get to its parent through + // a different namespace. For example, you could use the NodeList namespace + // to get to the server node, and then continue seamlessly adding named objects + // in the path. This is not nearly as readable as the previous version, but it + // illustrates how you can mix and match object names and Attribute names. + // + Config::Set ("/NodeList/1/eth0/Mtu", UintegerValue (1234)); + Ipv4AddressHelper ipv4; ipv4.SetBase ("10.1.1.0", "255.255.255.0"); Ipv4InterfaceContainer i = ipv4.Assign (d); @@ -109,8 +126,8 @@ main (int argc, char *argv[]) apps.Stop (Seconds (10.0)); // - // Use the config system to connect a trace source using the object name - // system to specify the path. + // Use the Config system to connect a trace source using the object name + // service to specify the path. // Config::Connect ("/Names/client/eth0/Rx", MakeCallback (&RxEvent)); changeset: 4117:bb930262e55c user: Craig Dowell date: Tue Jan 20 22:42:11 2009 -0800 summary: add NamesPriv cleanup for code that doesn't use simulator -- for valgrind-clean runs diff -r c59fdf82869b -r bb930262e55c src/core/config.cc --- a/src/core/config.cc Tue Jan 20 21:55:04 2009 -0800 +++ b/src/core/config.cc Tue Jan 20 22:42:11 2009 -0800 @@ -931,7 +931,12 @@ ConfigTest::RunTests (void) d1->SetAttribute ("Source", IntegerValue (-4)); NS_TEST_ASSERT_EQUAL (m_traceNotification, 0); - + // + // The Config system is intertwined with the Names system. In the process + // of parsing the paths above, we also created a NamesPriv singleton. In + // order to get a valgrind-clean run we need to clean up that singleton. + // + Names::Delete (); return result; } diff -r c59fdf82869b -r bb930262e55c src/core/object-names.cc --- a/src/core/object-names.cc Tue Jan 20 21:55:04 2009 -0800 +++ b/src/core/object-names.cc Tue Jan 20 22:42:11 2009 -0800 @@ -17,12 +17,12 @@ */ #include -#include "ns3/object.h" -#include "ns3/log.h" -#include "ns3/assert.h" -#include "ns3/abort.h" +#include "object.h" +#include "log.h" +#include "assert.h" +#include "abort.h" +#include "object-names.h" #include "ns3/simulator.h" -#include "object-names.h" namespace ns3 { @@ -92,10 +92,9 @@ public: Ptr FindObjectFromShortName (Ptr context, std::string name); static NamesPriv *Get (void); - + static void Delete (void); private: static NamesPriv **DoGet (void); - static void Delete (void); NameNode *IsNamed (Ptr); bool IsDuplicateName (NameNode *node, std::string name); @@ -156,6 +155,10 @@ NamesPriv::~NamesPriv () delete i->second; i->second = 0; } + + m_root.m_parent = 0; + m_root.m_name = ""; + m_root.m_object = 0; } bool @@ -442,6 +445,12 @@ NamesPriv::IsDuplicateName (NameNode *no NS_LOG_LOGIC ("Name exists in name map"); return true; } +} + +void +Names::Delete (void) +{ + NamesPriv::Delete (); } bool diff -r c59fdf82869b -r bb930262e55c src/core/object-names.h --- a/src/core/object-names.h Tue Jan 20 21:55:04 2009 -0800 +++ b/src/core/object-names.h Tue Jan 20 22:42:11 2009 -0800 @@ -171,8 +171,14 @@ public: template static Ptr FindObjectFromShortName (Ptr context, std::string name); + /** + * Clean up all of the data structures of the implementation and delete the + * underlying singleton. Used to get valgrind-clean runs if the simulator + * is not run. Normally singleton cleanup is scheduled on Simulator::Destroy. + */ + static void Delete (void); + private: - /** * \internal * changeset: 4118:805af0f9ddd9 tag: tip user: Craig Dowell date: Wed Jan 21 00:28:47 2009 -0800 summary: a little more doxygen for object-names.h diff -r bb930262e55c -r 805af0f9ddd9 src/core/object-names.h --- a/src/core/object-names.h Tue Jan 20 22:42:11 2009 -0800 +++ b/src/core/object-names.h Wed Jan 21 00:28:47 2009 -0800 @@ -55,6 +55,8 @@ public: * name to be defined. * \param name The name of the object you want to associate. * \param obj A smart pointer to the object itself. + * + * \returns true if the association was successfully completed, false otherwise */ static bool Add (Ptr context, std::string name, Ptr object); @@ -69,6 +71,8 @@ public: * under which you want this name to be defined. * \param name The name of the object you want to associate. * \param obj A smart pointer to the object itself. + * + * \returns true if the association was successfully completed, false otherwise */ static bool Add (std::string context, std::string name, Ptr object); @@ -87,6 +91,8 @@ public: * * \param object A spart pointer to an object for which you want to find * its shortname. + * + * \returns a string containing the shortname of the object. */ static std::string FindShortName (Ptr object); @@ -106,6 +112,8 @@ public: * * \param object A spart pointer to an object for which you want to find * its fullname. + * + * \returns a string containing the fullname of the object. */ static std::string FindFullName (Ptr object); @@ -121,6 +129,9 @@ public: * * \param name A string containing a fully qualified name space name * used to locate the object. + * + * \returns a smart pointer to the named object converted to the requested + * type. */ template static Ptr FindObjectFromFullName (std::string name); @@ -137,6 +148,10 @@ public: * * \param name A string containing a fully qualified name space name * used to locate the object. + * + * + * \returns a smart pointer to the named object converted to the requested + * type. * * @comment This method is identical to FindObjectFromFullName, but has a * short signature since it is a common use and we want it to be easy to @@ -167,6 +182,9 @@ public: * \param context A spart pointer to an object under which you want to look * for the provided name. * \param name A string containing a shortname to look for. + * + * \returns a smart pointer to the named object converted to the requested + * type. */ template static Ptr FindObjectFromShortName (Ptr context, std::string name); @@ -185,6 +203,8 @@ private: * \brief Non-templated internal version of FindObjectFromLongName * * \param name A string containing a longname to look for. + * + * \returns a smart pointer to the named object. */ static Ptr FindObjectFromFullNameInternal (std::string name); @@ -196,6 +216,8 @@ private: * \param context A spart pointer to an object under which you want to look * for the provided name. * \param name A string containing a shortname to look for. + * + * \returns a smart pointer to the named object. */ static Ptr FindObjectFromShortNameInternal (Ptr context, std::string name); };