diff --git a/ns-3.35/src/ofswitch13/model/simple-controller-flex.cc b/ns-3.35/src/ofswitch13/model/simple-controller-flex.cc index 860833e4..cd156234 100644 --- a/ns-3.35/src/ofswitch13/model/simple-controller-flex.cc +++ b/ns-3.35/src/ofswitch13/model/simple-controller-flex.cc @@ -72,13 +72,15 @@ void SimpleControllerFlex::UpdateWeights () { Graph topo = Topology::GetGraph (); + IntegerWeightCalc weightCalc = Topology::GetDefaultWeightCalc (); - boost::graph_traits::edge_iterator edgeIt, edgeEnd; - for (boost::tie (edgeIt, edgeEnd) = boost::edges (topo); edgeIt != edgeEnd; ++edgeIt) + auto bmap = get (edge_bundle, topo); + + for (auto ed : make_iterator_range (edges (topo))) { - Edge ed = *edgeIt; - Ptr n1 = Topology::VertexToNode (ed.m_source); - Ptr n2 = Topology::VertexToNode (ed.m_target); + Edge &e = bmap[ed]; + Ptr n1 = NodeList::GetNode (e.first); + Ptr n2 = NodeList::GetNode (e.second); if (n1->IsSwitch () && n2->IsSwitch ()) { @@ -86,7 +88,7 @@ SimpleControllerFlex::UpdateWeights () float flex1 = EnergyAPI::GetFlexArray (Names::FindName (n1)).at (index); float flex2 = EnergyAPI::GetFlexArray (Names::FindName (n2)).at (index); - Topology::UpdateEdgeWeight (n1, n2, flex1 + flex2); + weightCalc.UpdateEdgeWeight (e, flex1 + flex2); } } } diff --git a/ns-3.35/src/parser/model/parse-links.cc b/ns-3.35/src/parser/model/parse-links.cc index 930c2dbe..08b09793 100644 --- a/ns-3.35/src/parser/model/parse-links.cc +++ b/ns-3.35/src/parser/model/parse-links.cc @@ -21,7 +21,7 @@ */ #include "parse-links.h" -#include "parser.h" +#include "ns3/topology.h" #include "toml.hpp" #include "ns3/ipv4-address-helper.h" #include "ns3/point-to-point-ethernet-helper.h" @@ -62,16 +62,16 @@ installLinks (toml::table tbl, string outPath) if (n0->IsHost ()) { Ipv4InterfaceContainer ips = address.Assign (p2pDevices.Get (0)); - Topology::AddHost (n0, ips.GetAddress (0)); + Topology::AddNodeIpAddress (n0, ips.GetAddress (0)); } if (n1->IsHost ()) { Ipv4InterfaceContainer ips = address.Assign (p2pDevices.Get (1)); - Topology::AddHost (n1, ips.GetAddress (0)); + Topology::AddNodeIpAddress (n1, ips.GetAddress (0)); } - Topology::AddLink (n0, n1, channel); + Topology::AddEdge (n0, n1, channel); } } diff --git a/ns-3.35/src/parser/model/parse-nodes.cc b/ns-3.35/src/parser/model/parse-nodes.cc index a0e1851a..2ec1a2a8 100644 --- a/ns-3.35/src/parser/model/parse-nodes.cc +++ b/ns-3.35/src/parser/model/parse-nodes.cc @@ -86,7 +86,6 @@ parseNodes (string topoName) node->SetAttribute ("CpuCapacity", StringValue (configs["cpuCapacity"].value_or ("100Gbps"))); parseEnergyModels (configs, node); - Topology::AddSwitch (node); } else if (!nodeType.compare ("host")) { diff --git a/ns-3.35/src/topology/model/topology.cc b/ns-3.35/src/topology/model/topology.cc index 06e215ae..d1904932 100644 --- a/ns-3.35/src/topology/model/topology.cc +++ b/ns-3.35/src/topology/model/topology.cc @@ -21,202 +21,94 @@ */ #include "topology.h" -#include -#include -#include +#include "ns3/node-list.h" namespace ns3 { NS_OBJECT_ENSURE_REGISTERED (Topology); -Graph Topology::m_graph = Graph (); +/* ########### IntegerWeightCalc ########### */ -std::map, Vertex> Topology::m_vertexes = std::map, Vertex> (); -std::map> Topology::m_nodes = std::map> (); -std::map Topology::m_ip_to_vertex = std::map (); -std::map Topology::m_vertex_to_ip = std::map (); -std::map> Topology::m_channels = std::map> (); - -TypeId -Topology::GetTypeId (void) +IntegerWeightCalc::IntegerWeightCalc () : m_weights () { - static TypeId tid = TypeId ("ns3::Topology").SetParent ().AddConstructor (); - return tid; } -Topology::Topology () +IntegerWeightCalc::~IntegerWeightCalc () { } -Topology::~Topology () +int +IntegerWeightCalc::GetInitialWeight () const { -} + return 0; +}; -Vertex -Topology::AddNode (Ptr node) +int +IntegerWeightCalc::GetNonViableWeight () const { - Vertex vd = add_vertex (node, m_graph); - m_vertexes[node] = vd; - m_nodes[vd] = node; - return vd; -} + return std::numeric_limits::max (); +}; -void -Topology::AddSwitch (Ptr sw) +int +IntegerWeightCalc::GetWeight (Edge &e) const { - AddNode (sw); -} + auto iter = m_weights.find (e); + if (iter == m_weights.end ()) + return 1; -void -Topology::AddHost (Ptr host, Ipv4Address ip) -{ - Vertex vd = AddNode (host); - m_ip_to_vertex[ip] = vd; - m_vertex_to_ip[vd] = ip; -} + return (*iter).second; +}; void -Topology::AddLink (Ptr n1, Ptr n2, Ptr channel) -{ - Vertex vd1 = m_vertexes[n1]; - Vertex vd2 = m_vertexes[n2]; - Edge e = add_edge (vd1, vd2, 1, m_graph).first; - m_channels[e] = channel; -} - -std::vector -Topology::DijkstraShortestPathsInternal (Vertex src) +IntegerWeightCalc::UpdateEdgeWeight (Edge &e, int weight) { - std::vector predecessors (num_vertices (m_graph)); - dijkstra_shortest_paths (m_graph, src, - predecessor_map (boost::make_iterator_property_map ( - predecessors.begin (), get (boost::vertex_index, m_graph))) - - ); - return predecessors; + m_weights[e] = weight; } -std::vector -Topology::DijkstraShortestPathInternal (Vertex src, Vertex dst) -{ - std::vector predecessors = DijkstraShortestPathsInternal (src); - std::vector path; - Vertex currentVertex = dst; +/* ########### Topology ########### */ - while (currentVertex != src) - { - path.push_back (currentVertex); - currentVertex = predecessors[currentVertex]; - } - path.push_back (src); - std::reverse (path.begin (), path.end ()); +Graph Topology::m_graph{}; +IntegerWeightCalc Topology::m_default_calc{}; - return path; -} +std::map> Topology::m_ip_to_node{}; +std::map> Topology::m_channels{}; -std::vector> -Topology::VertexToNode (std::vector path) -{ - std::vector> path_nodes = std::vector> (); - for (auto i = path.begin (); i != path.end (); i++) - path_nodes.push_back (m_nodes[*i]); - return path_nodes; -} - -std::vector> -Topology::DijkstraShortestPath (Ptr src, Ptr dst) -{ - return VertexToNode (DijkstraShortestPathInternal (m_vertexes[src], m_vertexes[dst])); -} - -std::vector> -Topology::DijkstraShortestPath (Ptr src, Ipv4Address dst) -{ - return DijkstraShortestPath (src, m_nodes[m_ip_to_vertex[dst]]); -} - -std::vector> -Topology::DijkstraShortestPath (Ipv4Address src, Ptr dst) +TypeId +Topology::GetTypeId (void) { - return DijkstraShortestPath (m_nodes[m_ip_to_vertex[src]], dst); + static TypeId tid = TypeId ("ns3::Topology").SetParent ().AddConstructor (); + return tid; } -std::vector> -Topology::DijkstraShortestPath (Ipv4Address src, Ipv4Address dst) +Topology::Topology () { - return DijkstraShortestPath (m_nodes[m_ip_to_vertex[src]], m_nodes[m_ip_to_vertex[dst]]); } -std::vector> -Topology::DijkstraShortestPath (std::string src, std::string dst) +Topology::~Topology () { - Ptr srcNode = Names::Find (src); - Ptr dstNode = Names::Find (dst); - return DijkstraShortestPath (srcNode, dstNode); } -std::vector> -Topology::DijkstraShortestPaths (Ptr src) +void +Topology::AddNodeIpAddress (Ptr node, Ipv4Address ip) { - return VertexToNode (DijkstraShortestPathsInternal (m_vertexes[src])); + m_ip_to_node[ip] = node; } -std::vector> -Topology::DijkstraShortestPaths (Ipv4Address src) +void +Topology::AddEdge (Ptr n1, Ptr n2, Ptr channel) { - return DijkstraShortestPaths (m_nodes[m_ip_to_vertex[src]]); + Edge e (n1->GetId (), n2->GetId ()); + add_edge (e.first, e.second, e, m_graph); + m_channels[e] = channel; } std::vector> -Topology::DijkstraShortestPaths (std::string src) -{ - Ptr srcNode = Names::Find (src); - return DijkstraShortestPaths (srcNode); -} - -// NOTE: Code partially generated by ChatGPT -std::vector>, int>> -Topology::DijkstraShortestPaths (Ptr src, Ptr dst) +Topology::VertexToNode (std::vector path) { - std::vector predecessors (num_vertices (m_graph)); - std::vector distances (num_vertices (m_graph)); - Vertex source = NodeToVertex (src); - Vertex target = NodeToVertex (dst); - - dijkstra_shortest_paths (m_graph, source, - predecessor_map (make_iterator_property_map ( - predecessors.begin (), get (vertex_index, m_graph))) - .distance_map (make_iterator_property_map ( - distances.begin (), get (vertex_index, m_graph)))); - - // Create a vector to store the paths and their distances - std::vector>, int>> paths; - - // Loop through all vertices and store the path and distance from the source - for (Vertex v = 0; v < num_vertices (m_graph); ++v) - { - if (v == source || v == target) - continue; - - std::vector> path; - for (Vertex u = v; u != source; u = predecessors[u]) - path.push_back (VertexToNode (u)); - - path.push_back (VertexToNode (source)); - std::reverse (path.begin (), path.end ()); - path.push_back (VertexToNode (target)); - - paths.emplace_back (std::move (path), distances[v]); - } - - // Sort the paths by distance in ascending order - std::sort (paths.begin (), paths.end (), - [] (const auto &lhs, const auto &rhs) { return lhs.second < rhs.second; }); - - // Now, the 'paths' vector contains all paths between 'source' and 'target' - // sorted by their distances in ascending order. - // Each entry in the 'paths' vector is a pair (path, distance). - return paths; + std::vector> path_nodes = std::vector> (); + for (auto i = path.begin (); i != path.end (); i++) + path_nodes.push_back (NodeList::GetNode (*i)); + return path_nodes; } Graph @@ -225,66 +117,35 @@ Topology::GetGraph () return m_graph; } -Ptr -Topology::VertexToNode (Vertex vd) -{ - return m_nodes[vd]; -} - -Vertex -Topology::NodeToVertex (Ptr node) -{ - return m_vertexes[node]; -} - -void -Topology::UpdateEdgeWeight (Ptr n1, Ptr n2, int newWeight) +IntegerWeightCalc & +Topology::GetDefaultWeightCalc () { - std::pair pair = boost::edge (m_vertexes[n1], m_vertexes[n2], m_graph); - - if (pair.second) - Topology::UpdateEdgeWeight (pair.first, newWeight); + return m_default_calc; } -void -Topology::UpdateEdgeWeight (Edge ed, int newWeight) -{ - // Prevent negative weights - if (newWeight < 0) - newWeight = 0; - put (edge_weight_t (), m_graph, ed, newWeight); -} - -int -Topology::GetEdgeWeight (Ptr n1, Ptr n2) -{ - std::pair pair = boost::edge (m_vertexes[n1], m_vertexes[n2], m_graph); - - if (pair.second) - return Topology::GetEdgeWeight (pair.first); - return -1; -} - -int -Topology::GetEdgeWeight (Edge e) +Ptr +Topology::VertexToNode (Vertex vd) { - return get (edge_weight_t (), m_graph, e); + return NodeList::GetNode (vd); } Ptr Topology::GetChannel (Ptr n1, Ptr n2) { - std::pair pair = boost::edge (m_vertexes[n1], m_vertexes[n2], m_graph); + Edge e (n1->GetId (), n2->GetId ()); - if (pair.second) - return Topology::GetChannel (pair.first); - return NULL; + return Topology::GetChannel (e); } Ptr Topology::GetChannel (Edge e) { - return m_channels[e]; + + auto iter = m_channels.find (e); + if (iter == m_channels.end ()) + return NULL; + + return (*iter).second; } } // namespace ns3 diff --git a/ns-3.35/src/topology/model/topology.h b/ns-3.35/src/topology/model/topology.h index f201f366..722d476a 100644 --- a/ns-3.35/src/topology/model/topology.h +++ b/ns-3.35/src/topology/model/topology.h @@ -26,15 +26,44 @@ #include "ns3/core-module.h" #include "ns3/node.h" #include +#include +#include +#include #include "ns3/channel.h" using namespace boost; namespace ns3 { -typedef adjacency_list, property> Graph; -typedef graph_traits::vertex_descriptor Vertex; -typedef graph_traits::edge_descriptor Edge; +using Edge = std::pair; +using Graph = adjacency_list; +using Vertex = graph_traits::vertex_descriptor; + +// weights have to define operator+ and operator< +template +class WeightCalc +{ +public: + virtual Weight GetInitialWeight () const = 0; + virtual Weight GetNonViableWeight () const = 0; + virtual Weight GetWeight (Edge &) const = 0; +}; + +class IntegerWeightCalc : public WeightCalc +{ +private: + unordered_map m_weights; + +public: + IntegerWeightCalc (); + ~IntegerWeightCalc (); + + int GetInitialWeight () const override; + int GetNonViableWeight () const override; + int GetWeight (Edge &) const override; + + void UpdateEdgeWeight (Edge &, int); +}; class Topology : public Object { @@ -43,54 +72,233 @@ class Topology : public Object Topology (); ~Topology (); - static void AddSwitch (Ptr sw); - static void AddHost (Ptr host, Ipv4Address ip); - static void AddLink (Ptr n1, Ptr n2, Ptr channel); + static void AddNodeIpAddress (Ptr node, Ipv4Address ip); + static void AddEdge (Ptr n1, Ptr n2, Ptr channel); + + template + static std::vector> + DijkstraShortestPath (Ptr src, Ptr dst, + WeightCalc &weight_calc = m_default_calc); + + template + static std::vector> + DijkstraShortestPath (Ptr src, Ipv4Address dst, + WeightCalc &weight_calc = m_default_calc); + + template + static std::vector> + DijkstraShortestPath (Ipv4Address src, Ptr dst, + WeightCalc &weight_calc = m_default_calc); - static std::vector> DijkstraShortestPath (Ptr src, Ptr dst); - static std::vector> DijkstraShortestPath (Ptr src, Ipv4Address dst); - static std::vector> DijkstraShortestPath (Ipv4Address src, Ptr dst); - static std::vector> DijkstraShortestPath (Ipv4Address src, Ipv4Address dst); - static std::vector> DijkstraShortestPath (std::string src, std::string dst); - static std::vector> DijkstraShortestPaths (Ptr src); - static std::vector> DijkstraShortestPaths (Ipv4Address src); - static std::vector> DijkstraShortestPaths (std::string src); + template + static std::vector> + DijkstraShortestPath (Ipv4Address src, Ipv4Address dst, + WeightCalc &weight_calc = m_default_calc); - static std::vector>, int>> DijkstraShortestPaths (Ptr src, - Ptr dst); + template + static std::vector> + DijkstraShortestPath (std::string src, std::string dst, + WeightCalc &weight_calc = m_default_calc); - static void UpdateEdgeWeight (Ptr n1, Ptr n2, int newWeight); - static int GetEdgeWeight (Ptr n1, Ptr n2); + template + static std::vector> + DijkstraShortestPaths (Ptr src, WeightCalc &weight_calc = m_default_calc); + + template + static std::vector> + DijkstraShortestPaths (Ipv4Address src, WeightCalc &weight_calc = m_default_calc); + + template + static std::vector> + DijkstraShortestPaths (std::string src, WeightCalc &weight_calc = m_default_calc); + + template + static std::vector>, Weight>> + DijkstraShortestPaths (Ptr src, Ptr dst, + WeightCalc &weight_calc = m_default_calc); static Graph GetGraph (); + static IntegerWeightCalc &GetDefaultWeightCalc (); static Ptr VertexToNode (Vertex vd); static std::vector> VertexToNode (std::vector path); - static Vertex NodeToVertex (Ptr node); - static Ptr GetChannel (Ptr n1, Ptr n2); private: static Graph m_graph; + static IntegerWeightCalc m_default_calc; - // NOTE: Perhaps we can simplify this using vertex/edge properties - static std::map, Vertex> m_vertexes; - static std::map> m_nodes; - static std::map m_ip_to_vertex; - static std::map m_vertex_to_ip; + static std::map> m_ip_to_node; static std::map> m_channels; - static std::vector DijkstraShortestPathsInternal (Vertex src); - static std::vector DijkstraShortestPathInternal (Vertex src, Vertex dst); - static void UpdateEdgeWeight (Edge ed, int newWeight); - static int GetEdgeWeight (Edge ed); + template + static std::vector DijkstraShortestPathsInternal (Vertex src, + WeightCalc &weight_calc); - static Ptr GetChannel (Edge e); + template + static std::vector DijkstraShortestPathInternal (Vertex src, Vertex dst, + WeightCalc &weight_calc); - static Vertex AddNode (Ptr node); + static Ptr GetChannel (Edge e); }; } // namespace ns3 +/******************************************************************** + * Implementation of the templates declared above. + ********************************************************************/ + +namespace ns3 { + +template +std::vector +Topology::DijkstraShortestPathsInternal (Vertex src, WeightCalc &weight_calc) +{ + std::vector predecessors (num_vertices (m_graph)); + dijkstra_shortest_paths ( + m_graph, src, + predecessor_map (&predecessors[0]) + .weight_map (make_transform_value_property_map ( + [&weight_calc] (Edge &e) -> Weight { return weight_calc.GetWeight (e); }, + get (edge_bundle, m_graph))) + .distance_zero (weight_calc.GetInitialWeight ()) + .distance_inf (weight_calc.GetNonViableWeight ())); + return predecessors; +} + +template +std::vector +Topology::DijkstraShortestPathInternal (Vertex src, Vertex dst, WeightCalc &weight_calc) +{ + std::vector predecessors = DijkstraShortestPathsInternal (src, weight_calc); + std::vector path; + Vertex currentVertex = dst; + + while (currentVertex != src) + { + path.push_back (currentVertex); + currentVertex = predecessors[currentVertex]; + } + path.push_back (src); + std::reverse (path.begin (), path.end ()); + + return path; +} + +template +inline std::vector> +Topology::DijkstraShortestPath (Ptr src, Ptr dst, WeightCalc &weight_calc) +{ + Vertex source = vertex (src->GetId (), m_graph); + Vertex target = vertex (dst->GetId (), m_graph); + return VertexToNode (DijkstraShortestPathInternal (source, target, weight_calc)); +} + +template +inline std::vector> +Topology::DijkstraShortestPath (Ptr src, Ipv4Address dst, WeightCalc &weight_calc) +{ + return DijkstraShortestPath (src, m_ip_to_node[dst], weight_calc); +} + +template +inline std::vector> +Topology::DijkstraShortestPath (Ipv4Address src, Ptr dst, WeightCalc &weight_calc) +{ + return DijkstraShortestPath (m_ip_to_node[src], dst, weight_calc); +} + +template +inline std::vector> +Topology::DijkstraShortestPath (Ipv4Address src, Ipv4Address dst, WeightCalc &weight_calc) +{ + return DijkstraShortestPath (m_ip_to_node[src], m_ip_to_node[dst], weight_calc); +} + +template +inline std::vector> +Topology::DijkstraShortestPath (std::string src, std::string dst, WeightCalc &weight_calc) +{ + Ptr srcNode = Names::Find (src); + Ptr dstNode = Names::Find (dst); + return DijkstraShortestPath (srcNode, dstNode, weight_calc); +} + +template +inline std::vector> +Topology::DijkstraShortestPaths (Ptr src, WeightCalc &weight_calc) +{ + Vertex src_vertex = vertex (src->GetId (), m_graph); + return VertexToNode (DijkstraShortestPathsInternal (src_vertex, weight_calc)); +} + +template +inline std::vector> +Topology::DijkstraShortestPaths (Ipv4Address src, WeightCalc &weight_calc) +{ + return DijkstraShortestPaths (m_ip_to_node[src], weight_calc); +} + +template +inline std::vector> +Topology::DijkstraShortestPaths (std::string src, WeightCalc &weight_calc) +{ + Ptr source = Names::Find (src); + return DijkstraShortestPaths (source, weight_calc); +} + +// NOTE: Code partially generated by ChatGPT +template +inline std::vector>, Weight>> +Topology::DijkstraShortestPaths (Ptr src, Ptr dst, WeightCalc &weight_calc) +{ + std::vector predecessors (num_vertices (m_graph)); + std::vector distances (num_vertices (m_graph)); + Vertex source = vertex (src->GetId (), m_graph); + Vertex target = vertex (dst->GetId (), m_graph); + + // add distance map + dijkstra_shortest_paths ( + m_graph, source, + predecessor_map (&predecessors[0]) + .weight_map (make_transform_value_property_map ( + [&weight_calc] (Edge &e) -> Weight { return weight_calc.GetWeight (e); }, + get (edge_bundle, m_graph))) + .distance_zero (weight_calc.GetInitialWeight ()) + .distance_inf (weight_calc.GetNonViableWeight ()) + .distance_map (&distances[0])); + + // Create a vector to store the paths and their distances + std::vector>, Weight>> paths; + + // Loop through all vertices and store the path and distance from the source + for (Vertex v = 0; v < num_vertices (m_graph); ++v) + { + if (v == source || v == target) + continue; + + std::vector> path; + for (Vertex u = v; u != source; u = predecessors[u]) + path.push_back (VertexToNode (u)); + + path.push_back (VertexToNode (source)); + std::reverse (path.begin (), path.end ()); + path.push_back (VertexToNode (target)); + + paths.emplace_back (std::move (path), distances[v].get ()); + } + + // Sort the paths by distance in ascending order + std::sort (paths.begin (), paths.end (), + [] (const auto &lhs, const auto &rhs) { return lhs.second < rhs.second; }); + + // Now, the 'paths' vector contains all paths between 'source' and 'target' + // sorted by their distances in ascending order. + // Each entry in the 'paths' vector is a pair (path, distance). + return paths; +} + +} // namespace ns3 + #endif /* TOPOLOGY_H */