Allow Click defines to be handled from ns-3
authorSascha Alexander Jopen <jopen@informatik.uni-bonn.de>
Thu, 07 Feb 2013 10:47:31 +0100
changeset 9231 20d3a3dce7cf
parent 9230 01be79275088
child 9232 0958cf37fa89
Allow Click defines to be handled from ns-3
src/click/examples/nsclick-defines.cc
src/click/examples/nsclick-defines.click
src/click/examples/wscript
src/click/helper/click-internet-stack-helper.cc
src/click/helper/click-internet-stack-helper.h
src/click/model/ipv4-click-routing.cc
src/click/model/ipv4-click-routing.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/click/examples/nsclick-defines.cc	Thu Feb 07 10:47:31 2013 +0100
@@ -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 <jopen@cs.uni-bonn.de>
+ */
+
+
+#include "ns3/core-module.h"
+#include "ns3/ipv4-click-routing.h"
+#include "ns3/click-internet-stack-helper.h"
+#include <map>
+
+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<std::string, std::string> 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
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/click/examples/nsclick-defines.click	Thu Feb 07 10:47:31 2013 +0100
@@ -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);
--- a/src/click/examples/wscript	Thu Feb 07 10:47:08 2013 +0100
+++ b/src/click/examples/wscript	Thu Feb 07 10:47:31 2013 +0100
@@ -20,3 +20,7 @@
    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'
--- a/src/click/helper/click-internet-stack-helper.cc	Thu Feb 07 10:47:08 2013 +0100
+++ b/src/click/helper/click-internet-stack-helper.cc	Thu Feb 07 10:47:31 2013 +0100
@@ -125,6 +125,21 @@
 }
 
 void
+ClickInternetStackHelper::SetDefines (NodeContainer c, std::map<std::string, std::string> defines)
+{
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+	  SetDefines (*i, defines);
+    }
+}
+
+void
+ClickInternetStackHelper::SetDefines (Ptr<Node> node, std::map<std::string, std::string> defines)
+{
+  m_nodeToDefinesMap.insert (std::make_pair (node, defines));
+}
+
+void
 ClickInternetStackHelper::SetRoutingTableElement (NodeContainer c, std::string rt)
 {
   for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
@@ -193,6 +208,13 @@
           ipv4Routing->SetClickFile (it->second);
         }
 
+      std::map<Ptr<Node>, std::map<std::string, std::string> >::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 ())
         {
--- a/src/click/helper/click-internet-stack-helper.h	Thu Feb 07 10:47:08 2013 +0100
+++ b/src/click/helper/click-internet-stack-helper.h	Thu Feb 07 10:47:31 2013 +0100
@@ -143,6 +143,20 @@
   void SetClickFile (Ptr<Node> 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<std::string, std::string> 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> node, std::map<std::string, std::string> defines);
+
+  /**
    * \brief Set a Click routing table element for a group of nodes.
    * \param c NodeContainer of nodes
    * \param rt Click Routing Table element name
@@ -219,6 +233,11 @@
   std::map < Ptr<Node>, std::string  > m_nodeToClickFileMap;
 
   /**
+   * \brief Node to Click defines mapping
+   */
+  std::map < Ptr<Node>, std::map<std::string, std::string>  > m_nodeToDefinesMap;
+
+  /**
    * \brief Node to Routing Table Element mapping
    */
   std::map < Ptr<Node>, std::string  > m_nodeToRoutingTableElementMap;
--- a/src/click/model/ipv4-click-routing.cc	Thu Feb 07 10:47:08 2013 +0100
+++ b/src/click/model/ipv4-click-routing.cc	Thu Feb 07 10:47:31 2013 +0100
@@ -65,6 +65,10 @@
     m_ipv4 (0)
 {
   m_random = CreateObject<UniformRandomVariable> ();
+  m_simNode = new simclick_node_t;
+  timerclear (&m_simNode->curtime);
+
+  AddSimNodeToClickMapping ();
 }
 
 Ipv4ClickRouting::~Ipv4ClickRouting ()
@@ -83,11 +87,6 @@
       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
@@ -138,6 +137,18 @@
 }
 
 void
+Ipv4ClickRouting::SetDefines (std::map<std::string, std::string> defines)
+{
+  m_defines = defines;
+}
+
+std::map<std::string, std::string>
+Ipv4ClickRouting::GetDefines (void)
+{
+  return m_defines;
+}
+
+void
 Ipv4ClickRouting::SetClickRoutingTableElement (std::string name)
 {
   m_clickRoutingTableElement = name;
@@ -614,7 +625,7 @@
     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 @@
         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<std::string, std::string> defines = clickInstance->GetDefines ();
+        std::map<std::string, std::string>::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;
 }
--- a/src/click/model/ipv4-click-routing.h	Thu Feb 07 10:47:08 2013 +0100
+++ b/src/click/model/ipv4-click-routing.h	Thu Feb 07 10:47:31 2013 +0100
@@ -79,6 +79,12 @@
   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<std::string, std::string> 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.
    */
@@ -132,6 +138,12 @@
 
 public:
   /**
+   * \brief Provides for SIMCLICK_GET_DEFINES
+   * \return The defines mapping for .click configuration file parsing
+   */
+  std::map<std::string, std::string> GetDefines (void);
+
+  /**
    * \brief Provides for SIMCLICK_IFID_FROM_NAME
    * \param ifname The name of the interface
    * \return The interface ID which corresponds to ifname
@@ -247,6 +259,7 @@
 
 private:
   std::string m_clickFile;
+  std::map < std::string, std::string > m_defines;
   std::string m_nodeName;
   std::string m_clickRoutingTableElement;