From ddfd9131e831abcd5d22743623a4f95fca3202d8 Mon Sep 17 00:00:00 2001 From: Sascha Alexander Jopen Date: Thu, 7 Feb 2013 10:47:31 +0100 Subject: [PATCH] Allow Click defines to be handled from ns-3 --- src/click/examples/nsclick-defines.cc | 66 +++++++++++++++++++ src/click/examples/nsclick-defines.click | 9 +++ src/click/examples/wscript | 4 ++ .../helper/click-internet-stack-helper.cc | 22 +++++++ .../helper/click-internet-stack-helper.h | 19 ++++++ src/click/model/ipv4-click-routing.cc | 65 ++++++++++++++++-- src/click/model/ipv4-click-routing.h | 13 ++++ 7 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 src/click/examples/nsclick-defines.cc create mode 100644 src/click/examples/nsclick-defines.click diff --git a/src/click/examples/nsclick-defines.cc b/src/click/examples/nsclick-defines.cc new file mode 100644 index 000000000..37127ddb9 --- /dev/null +++ b/src/click/examples/nsclick-defines.cc @@ -0,0 +1,66 @@ +/* -*- 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 + * + * Authors: Sascha Jopen + */ + + +#include "ns3/core-module.h" +#include "ns3/ipv4-click-routing.h" +#include "ns3/click-internet-stack-helper.h" +#include + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("NsclickRouting"); + +int +main (int argc, char *argv[]) +{ +#ifdef NS3_CLICK + +// +// Explicitly create the nodes required by the topology (shown above). +// + NS_LOG_INFO ("Create a node."); + NodeContainer n; + n.Create (1); + +// +// Install Click on the nodes +// + std::map defines; +// Strings, especially with blanks in it, have to be enclosed in quotation +// marks, like in click configuration files. + defines["OUTPUT"] = "\"Hello World!\""; + + ClickInternetStackHelper clickinternet; + clickinternet.SetClickFile (n, "src/click/examples/nsclick-defines.click"); + clickinternet.SetRoutingTableElement (n, "rt"); + clickinternet.SetDefines(n, defines); + clickinternet.Install (n); + +// +// Now, do the actual simulation. +// + NS_LOG_INFO ("Run Simulation."); + Simulator::Stop (Seconds (20.0)); + Simulator::Run (); + Simulator::Destroy (); + NS_LOG_INFO ("Done."); +#else + NS_FATAL_ERROR ("Can't use ns-3-click without NSCLICK compiled in"); +#endif +} diff --git a/src/click/examples/nsclick-defines.click b/src/click/examples/nsclick-defines.click new file mode 100644 index 000000000..b973cef44 --- /dev/null +++ b/src/click/examples/nsclick-defines.click @@ -0,0 +1,9 @@ +define($OUTPUT "This is a default value for OUTPUT"); +define($UNDEFINED "UNDEFINED is an undefined variable"); + +// It is mandatory to use an IPRouteTable element with ns-3-click +rt :: LinearIPLookup (); +Idle -> rt; + +output :: Message($OUTPUT); +undefined :: Message($UNDEFINED); diff --git a/src/click/examples/wscript b/src/click/examples/wscript index 6157f1dc3..2c674be6f 100644 --- a/src/click/examples/wscript +++ b/src/click/examples/wscript @@ -20,3 +20,7 @@ def build(bld): obj = bld.create_ns3_program('nsclick-routing', ['click', 'csma', 'internet', 'applications']) obj.source = 'nsclick-routing.cc' + + obj = bld.create_ns3_program('nsclick-defines', + ['click']) + obj.source = 'nsclick-defines.cc' diff --git a/src/click/helper/click-internet-stack-helper.cc b/src/click/helper/click-internet-stack-helper.cc index 045c843a9..7de4d7498 100644 --- a/src/click/helper/click-internet-stack-helper.cc +++ b/src/click/helper/click-internet-stack-helper.cc @@ -124,6 +124,21 @@ ClickInternetStackHelper::SetClickFile (Ptr node, std::string clickfile) m_nodeToClickFileMap.insert (std::make_pair (node, clickfile)); } +void +ClickInternetStackHelper::SetDefines (NodeContainer c, std::map defines) +{ + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + SetDefines (*i, defines); + } +} + +void +ClickInternetStackHelper::SetDefines (Ptr node, std::map defines) +{ + m_nodeToDefinesMap.insert (std::make_pair (node, defines)); +} + void ClickInternetStackHelper::SetRoutingTableElement (NodeContainer c, std::string rt) { @@ -193,6 +208,13 @@ ClickInternetStackHelper::Install (Ptr node) const ipv4Routing->SetClickFile (it->second); } + std::map, std::map >::const_iterator definesIt; + definesIt = m_nodeToDefinesMap.find (node); + if (definesIt != m_nodeToDefinesMap.end ()) + { + ipv4Routing->SetDefines (definesIt->second); + } + it = m_nodeToRoutingTableElementMap.find (node); if (it != m_nodeToRoutingTableElementMap.end ()) { diff --git a/src/click/helper/click-internet-stack-helper.h b/src/click/helper/click-internet-stack-helper.h index e1da930e8..19335f368 100644 --- a/src/click/helper/click-internet-stack-helper.h +++ b/src/click/helper/click-internet-stack-helper.h @@ -142,6 +142,20 @@ public: */ void SetClickFile (Ptr node, std::string clickfile); + /** + * \brief Set defines to be used for a group of nodes. + * \param c NodeContainer of nodes + * \param defines Defines mapping to be used + */ + void SetDefines (NodeContainer c, std::map defines); + + /** + * \brief Set defines to be used for a node. + * \param node Node for which the defines are to be set + * \param defines Defines mapping to be used + */ + void SetDefines (Ptr node, std::map defines); + /** * \brief Set a Click routing table element for a group of nodes. * \param c NodeContainer of nodes @@ -218,6 +232,11 @@ private: */ std::map < Ptr, std::string > m_nodeToClickFileMap; + /** + * \brief Node to Click defines mapping + */ + std::map < Ptr, std::map > m_nodeToDefinesMap; + /** * \brief Node to Routing Table Element mapping */ diff --git a/src/click/model/ipv4-click-routing.cc b/src/click/model/ipv4-click-routing.cc index 417a3ba8a..5913f1f36 100644 --- a/src/click/model/ipv4-click-routing.cc +++ b/src/click/model/ipv4-click-routing.cc @@ -65,6 +65,10 @@ Ipv4ClickRouting::Ipv4ClickRouting () m_ipv4 (0) { m_random = CreateObject (); + m_simNode = new simclick_node_t; + timerclear (&m_simNode->curtime); + + AddSimNodeToClickMapping (); } Ipv4ClickRouting::~Ipv4ClickRouting () @@ -83,11 +87,6 @@ Ipv4ClickRouting::DoStart () m_nodeName = name.str (); } - m_simNode = new simclick_node_t; - timerclear (&m_simNode->curtime); - - AddSimNodeToClickMapping (); - NS_ASSERT (m_clickFile.length () > 0); // Even though simclick_click_create() will halt programme execution @@ -137,6 +136,18 @@ Ipv4ClickRouting::SetClickFile (std::string clickfile) m_clickFile = clickfile; } +void +Ipv4ClickRouting::SetDefines (std::map defines) +{ + m_defines = defines; +} + +std::map +Ipv4ClickRouting::GetDefines (void) +{ + return m_defines; +} + void Ipv4ClickRouting::SetClickRoutingTableElement (std::string name) { @@ -614,7 +625,7 @@ int simclick_sim_command (simclick_node_t *simnode, int cmd, ...) case SIMCLICK_SUPPORTS: { int othercmd = va_arg (val, int); - retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_RANDOM_INT); + retval = (othercmd >= SIMCLICK_VERSION && othercmd <= SIMCLICK_GET_DEFINES); break; } @@ -757,6 +768,48 @@ int simclick_sim_command (simclick_node_t *simnode, int cmd, ...) NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_RANDOM: " << *randomValue << " " << maxValue << " " << ns3::Simulator::Now ()); break; } + + case SIMCLICK_GET_DEFINES: + { + char *buf = va_arg (val, char *); + size_t *size = va_arg (val, size_t *); + uint32_t required = 0; + + // Try to fill the buffer with up to size bytes. + // If this is not enough space, write the required buffer size into + // the size variable and return an error code. + // Otherwise return the bytes actually writte into the buffer in size. + + // Append key/value pair, seperated by \0. + std::map defines = clickInstance->GetDefines (); + std::map::const_iterator it = defines.begin (); + while (it != defines.end ()) + { + size_t available = *size - required; + if (it->first.length() + it->second.length() + 2 <= available) + { + simstrlcpy(buf + required, available, it->first); + required += it->first.length() + 1; + available -= it->first.length() + 1; + simstrlcpy(buf + required, available, it->second); + required += it->second.length() + 1; + } + else + { + required += it->first.length() + it->second.length() + 2; + } + it++; + } + if (required > *size) + { + retval = -1; + } + else + { + retval = 0; + } + *size = required; + } } return retval; } diff --git a/src/click/model/ipv4-click-routing.h b/src/click/model/ipv4-click-routing.h index 292ce9b45..c3295389d 100644 --- a/src/click/model/ipv4-click-routing.h +++ b/src/click/model/ipv4-click-routing.h @@ -78,6 +78,12 @@ public: */ void SetClickFile (std::string clickfile); + /** + * \brief Click defines to be used by the node's Click Instance. + * \param defines mapping of defines for .click configuration file parsing + */ + void SetDefines (std::map defines); + /** * \brief Name of the node as to be used by Click. Required for Click Dumps. * \param name Name to be assigned to the node. @@ -131,6 +137,12 @@ public: static Ptr GetClickInstanceFromSimNode (simclick_node_t *simnode); public: + /** + * \brief Provides for SIMCLICK_GET_DEFINES + * \return The defines mapping for .click configuration file parsing + */ + std::map GetDefines (void); + /** * \brief Provides for SIMCLICK_IFID_FROM_NAME * \param ifname The name of the interface @@ -247,6 +259,7 @@ public: private: std::string m_clickFile; + std::map < std::string, std::string > m_defines; std::string m_nodeName; std::string m_clickRoutingTableElement;