plugins/topology: Adding ability for AnnotatedTopologyReader to save topology in .dot format

Also, RocketfuelWeightsReader now supports SetDefaultBandwidth and
SetDefaultQueue parameters, which are necessary if the topology needs to
be converted into AnnotatedTopologyReader format
diff --git a/plugins/topology/annotated-topology-reader.cc b/plugins/topology/annotated-topology-reader.cc
index 257de33..c227507 100644
--- a/plugins/topology/annotated-topology-reader.cc
+++ b/plugins/topology/annotated-topology-reader.cc
@@ -49,6 +49,9 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/tokenizer.hpp>
 
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/graphviz.hpp>
+
 #include <set>
 
 #ifdef NS3_MPI
@@ -195,7 +198,7 @@
 
   if (topgen.eof ())
     {
-      NS_FATAL_ERROR ("Topology file " << GetFileName () << " does not have \"link\" section");
+      NS_LOG_ERROR ("Topology file " << GetFileName () << " does not have \"link\" section");
       return m_nodes;
     }
 
@@ -408,7 +411,7 @@
 }
 
 void
-AnnotatedTopologyReader::SaveTopology (const std::string &file) const
+AnnotatedTopologyReader::SaveTopology (const std::string &file)
 {
   ofstream os (file.c_str (), ios::trunc);
   os << "# any empty lines and lines starting with '#' symbol is ignored\n"
@@ -480,4 +483,72 @@
     }
 }
 
+
+template <class Names>
+class name_writer {
+public:
+  name_writer(Names _names) : names(_names) {}
+
+  template <class VertexOrEdge>
+  void operator()(std::ostream& out, const VertexOrEdge& v) const {
+    // out << "[label=\"" << names[v] << "\",style=filled,fillcolor=\"" << colors[v] << "\"]";
+    out << "[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"green\"]";
+  }
+private:
+  Names names;
+};
+
+template <class Names>
+inline name_writer<Names>
+make_name_writer(Names n) {
+  return name_writer<Names>(n);
+}
+
+
+void
+AnnotatedTopologyReader::SaveGraphviz (const std::string &file)
+{
+  typedef boost::adjacency_list_traits<boost::setS, boost::setS, boost::undirectedS> Traits;
+
+  typedef boost::property< boost::vertex_name_t, std::string, boost::property
+                           < boost::vertex_index_t, uint32_t > > nodeProperty;
+
+  typedef boost::no_property edgeProperty;
+
+  typedef boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS,
+                                 nodeProperty, edgeProperty > Graph;
+
+  typedef map<string, Traits::vertex_descriptor> node_map_t;
+  node_map_t graphNodes;
+  Graph      graph;
+
+  for (NodeContainer::Iterator node = m_nodes.Begin ();
+       node != m_nodes.End ();
+       node++)
+    {
+       std::pair<node_map_t::iterator, bool>
+         retval = graphNodes.insert (make_pair (Names::FindName (*node),
+                                                add_vertex (nodeProperty (Names::FindName (*node)), graph)));
+       // NS_ASSERT (ok == true);
+
+       put (boost::vertex_index, graph, retval.first->second, (*node)->GetId ());
+    }
+
+  for (std::list<Link>::const_iterator link = m_linksList.begin ();
+       link != m_linksList.end ();
+       link ++)
+    {
+      node_map_t::iterator from = graphNodes.find (Names::FindName (link->GetFromNode ()));
+      node_map_t::iterator to   = graphNodes.find (Names::FindName (link->GetToNode ()));
+
+      // add_edge (node->second, otherNode->second, m_graph);
+      boost::add_edge (from->second, to->second, graph);
+    }
+  
+  ofstream of (file.c_str ());
+  boost::property_map<Graph, boost::vertex_name_t>::type names = get (boost::vertex_name, graph);
+  write_graphviz (of, graph, make_name_writer (names));
+}
+
+
 }
diff --git a/plugins/topology/annotated-topology-reader.h b/plugins/topology/annotated-topology-reader.h
index a840919..27815fa 100644
--- a/plugins/topology/annotated-topology-reader.h
+++ b/plugins/topology/annotated-topology-reader.h
@@ -59,13 +59,13 @@
   /**
    * \brief Get nodes read by the reader
    */
-  NodeContainer
+  virtual NodeContainer
   GetNodes () const;
     
   /**
    * \brief Get links read by the reader
    */  
-  const std::list<Link>&
+  virtual const std::list<Link>&
   GetLinks () const;
   
   /**
@@ -77,7 +77,7 @@
    *
    * \param base Starting IPv4 address (second link will have base+256)
    */
-  void
+  virtual void
   AssignIpv4Addresses (Ipv4Address base);
 
   /**
@@ -87,27 +87,34 @@
    * \param lrx Lower right x coordinate
    * \param lry Lower right y coordinate
    */
-  void
+  virtual void
   SetBoundingBox (double ulx, double uly, double lrx, double lry);
 
   /**
    * \brief Set mobility model to be used on nodes
    * \param model class name of the model
    */
-  void
+  virtual void
   SetMobilityModel (const std::string &model);
 
   /**
    * \brief Apply OSPF metric on Ipv4 (if exists) and Ccnx (if exists) stacks
    */
-  void ApplyOspfMetric ();
+  virtual void
+  ApplyOspfMetric ();
 
   /**
    * \brief Save positions (e.g., after manual modification using visualizer)
    */
-  void
-  SaveTopology (const std::string &file) const;
+  virtual void
+  SaveTopology (const std::string &file);
 
+  /**
+   * \brief Save topology in graphviz format (.dot file)
+   */
+  virtual void
+  SaveGraphviz (const std::string &file);
+  
 protected:
   Ptr<Node>
   CreateNode (const std::string name, uint32_t systemId);
diff --git a/plugins/topology/rocketfuel-map-reader.h b/plugins/topology/rocketfuel-map-reader.h
index 34677d2..7b357b8 100644
--- a/plugins/topology/rocketfuel-map-reader.h
+++ b/plugins/topology/rocketfuel-map-reader.h
@@ -116,10 +116,10 @@
   const NodeContainer&
   GetCustomerRouters() const;
 
-  void
+  virtual void
   SaveTopology (const std::string &file);
 
-  void
+  virtual void
   SaveGraphviz (const std::string &file);
 
 private:
diff --git a/plugins/topology/rocketfuel-weights-reader.cc b/plugins/topology/rocketfuel-weights-reader.cc
index e5fb035..2047d69 100644
--- a/plugins/topology/rocketfuel-weights-reader.cc
+++ b/plugins/topology/rocketfuel-weights-reader.cc
@@ -57,6 +57,7 @@
     
 RocketfuelWeightsReader::RocketfuelWeightsReader (const std::string &path/*=""*/, double scale/*=1.0*/)
   : AnnotatedTopologyReader (path, scale)
+  , m_defaultBandwidth ("100Mbps")
 {
   NS_LOG_FUNCTION (this);
 
@@ -162,7 +163,12 @@
           if (attribute == "")
             attribute = "1";
             
+          link->SetAttribute ("DataRate", m_defaultBandwidth);
           link->SetAttribute ("Delay", attribute+"ms");
+          if (!m_queue.empty ())
+            {
+              link->SetAttribute ("MaxPackets", m_queue);
+            }
           break;
         default:
           ; //
diff --git a/plugins/topology/rocketfuel-weights-reader.h b/plugins/topology/rocketfuel-weights-reader.h
index e2f80d4..126c039 100644
--- a/plugins/topology/rocketfuel-weights-reader.h
+++ b/plugins/topology/rocketfuel-weights-reader.h
@@ -68,6 +68,18 @@
       LATENCIES,
       POSITIONS
     };
+
+  inline void
+  SetDefaultBandwidth (const std::string &bw);
+
+  inline std::string
+  GetDefaultBandwidth () const;
+
+  inline void
+  SetDefaultQueue (const std::string &queue);
+
+  inline std::string
+  GetDefaultQueue () const;
   
 private:
   RocketfuelWeightsReader (const RocketfuelWeightsReader&);
@@ -75,9 +87,36 @@
   
 private:
   uint8_t m_inputType;
+  std::string m_defaultBandwidth; // since the topology files don't provide bandwidth parameter
+  std::string m_queue;
   
 }; // end class RocketfuelWeightsReader
 
+inline void
+RocketfuelWeightsReader::SetDefaultBandwidth (const std::string &bw)
+{
+  m_defaultBandwidth = bw;
+}
+
+inline std::string
+RocketfuelWeightsReader::GetDefaultBandwidth () const
+{
+  return m_defaultBandwidth;
+}
+
+inline void
+RocketfuelWeightsReader::SetDefaultQueue (const std::string &queue)
+{
+  m_queue = queue;
+}
+
+inline std::string
+RocketfuelWeightsReader::GetDefaultQueue () const
+{
+  return m_queue;
+}
+
+
 }; // end namespace ns3