Index: examples/matrix-topology/matrix-topology.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/examples/matrix-topology/matrix-topology.cc |
@@ -0,0 +1,422 @@ |
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) 2010 Egemen K. Cetinkaya, Justin P. Rohrer, and Amit Dandekar |
+ * |
+ * 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: Egemen K. Cetinkaya <ekc@ittc.ku.edu> |
+ * Author: Justin P. Rohrer <rohrer@ittc.ku.edu> |
+ * Author: Amit Dandekar <dandekar@ittc.ku.edu> |
+ * |
+ * Thanks to the students and our advisor Dr. James P.G. Sterbenz |
+ * in the ResiliNets group at The University of Kansas, |
+ * https://wiki.ittc.ku.edu/resilinets/Main_Page |
+ * |
+ * This program reads an upper triangular adjacency matrix (e.g. adjacency_matrix.txt) and |
+ * node coordinates file (e.g. node_coordinates.txt). The program also set-ups a |
+ * wired network topology with P2P links according to the adjacency matrix with |
+ * nx(n-1) CBR traffic flows, in which n is the number of nodes in the adjacency matrix. |
+ */ |
+ |
+// ---------- Header Includes ---------------------------------------------------- |
+#include <iostream> |
+#include <fstream> |
+#include <sstream> |
+#include <string> |
+#include <vector> |
+#include <cstdlib> |
+#include <time.h> |
+ |
+#include "ns3/core-module.h" |
+#include "ns3/simulator-module.h" |
+#include "ns3/node-module.h" |
+#include "ns3/helper-module.h" |
+#include "ns3/global-route-manager.h" |
+#include "ns3/mobility-module.h" |
+#include "ns3/assert.h" |
+ |
+using namespace std; |
+using namespace ns3; |
+ |
+// ---------- Prototypes --------------------------------------------------------- |
+ |
+vector<vector<bool> > readNxNMatrix (std::string adj_mat_file_name); |
+vector<vector<double> > readCordinatesFile (std::string node_coordinates_file_name); |
+void printCoordinateArray (const char* description, vector<vector<double> > coord_array); |
+void printMatrix (const char* description, vector<vector<bool> > array); |
+ |
+NS_LOG_COMPONENT_DEFINE ("GenericTopologyCreation"); |
+ |
+int main (int argc, char *argv[]) |
+{ |
+ |
+ // ---------- Simulation Variables ----------------------------------------------- |
+ |
+ // Change the variables and file names only in this block! |
+ |
+ double SimTime = 3.00; |
+ double SinkStartTime = 1.0001; |
+ double SinkStopTime = 2.90001; |
+ double AppStartTime = 2.0001; |
+ double AppStopTime = 2.80001; |
+ |
+ std::string AppPacketRate ("40Kbps"); |
+ Config::SetDefault ("ns3::OnOffApplication::PacketSize",StringValue ("1000")); |
+ Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (AppPacketRate)); |
+ std::string LinkRate ("10Mbps"); |
+ std::string LinkDelay ("2ms"); |
+ // DropTailQueue::MaxPackets affects the # of dropped packets, default value:100 |
+ // Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (1000)); |
+ |
+ srand ( (unsigned)time ( NULL ) ); // generate different seed each time |
+ |
+ std::string tr_name ("n-node-ppp.tr"); |
+ std::string pcap_name ("n-node-ppp"); |
+ std::string flow_name ("n-node-ppp.xml"); |
+ std::string anim_name ("n-node-ppp.anim"); |
+ |
+ std::string adj_mat_file_name ("adjacency_matrix.txt"); |
+ std::string node_coordinates_file_name ("node_coordinates.txt"); |
+ |
+ // ---------- End of Simulation Variables ---------------------------------------- |
+ |
+ // ---------- Read Adjacency Matrix ---------------------------------------------- |
+ |
+ vector<vector<bool> > Adj_Matrix; |
+ Adj_Matrix = readNxNMatrix (adj_mat_file_name); |
+ |
+ // Optionally display 2-dimensional adjacency matrix (Adj_Matrix) array |
+ // printMatrix (adj_mat_file_name.c_str (),Adj_Matrix); |
+ |
+ // ---------- End of Read Adjacency Matrix --------------------------------------- |
+ |
+ // ---------- Read Node Coordinates File ----------------------------------------- |
+ |
+ vector<vector<double> > coord_array; |
+ coord_array = readCordinatesFile (node_coordinates_file_name); |
+ |
+ // Optionally display node co-ordinates file |
+ // printCoordinateArray (node_coordinates_file_name.c_str (),coord_array); |
+ |
+ int n_nodes = coord_array.size (); |
+ int matrixDimension = Adj_Matrix.size (); |
+ |
+ if (matrixDimension != n_nodes) |
+ { |
+ NS_LOG_ERROR ("The number of lines in coordinate file is: " << n_nodes << " not equal to the number of nodes in adjacency matrix size " << matrixDimension); |
+ exit (1); |
+ } |
+ |
+ // ---------- End of Read Node Coordinates File ---------------------------------- |
+ |
+ // ---------- Network Setup ------------------------------------------------------ |
+ |
+ NS_LOG_INFO ("Create Nodes."); |
+ |
+ NodeContainer nodes; // Declare nodes objects |
+ nodes.Create (n_nodes); |
+ |
+ NS_LOG_INFO ("Create P2P Link Attributes."); |
+ |
+ PointToPointHelper p2p; |
+ p2p.SetDeviceAttribute ("DataRate", StringValue (LinkRate)); |
+ p2p.SetChannelAttribute ("Delay", StringValue (LinkDelay)); |
+ |
+ NS_LOG_INFO ("Install Internet Stack to Nodes."); |
+ |
+ InternetStackHelper internet; |
+ internet.Install (NodeContainer::GetGlobal ()); |
+ |
+ NS_LOG_INFO ("Assign Addresses to Nodes."); |
+ |
+ Ipv4AddressHelper ipv4_n; |
+ ipv4_n.SetBase ("10.0.0.0", "255.255.255.252"); |
+ |
+ NS_LOG_INFO ("Create Links Between Nodes."); |
+ |
+ uint32_t linkCount = 0; |
+ |
+ Ipv4InterfaceContainer n_ic[n_nodes][n_nodes]; // Create an array of interface containers for links |
+ |
+ for (size_t i = 0; i < Adj_Matrix.size (); i++) |
+ { |
+ for (size_t j = 0; j < Adj_Matrix[i].size (); j++) |
+ { |
+ |
+ if (Adj_Matrix[i][j] == 1) |
+ { |
+ NodeContainer n_links = NodeContainer (nodes.Get (i), nodes.Get (j)); |
+ NetDeviceContainer n_devs = p2p.Install (n_links); |
+ n_ic[i][j] = ipv4_n.Assign (n_devs); |
+ ipv4_n.NewNetwork (); |
+ linkCount++; |
+ NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is 1"); |
+ } |
+ else |
+ { |
+ NS_LOG_INFO ("matrix element [" << i << "][" << j << "] is 0"); |
+ } |
+ } |
+ } |
+ NS_LOG_INFO ("Number of links in the adjacency matrix is: " << linkCount); |
+ uint32_t nNodes = nodes.GetN (); |
+ NS_LOG_INFO ("Number of all nodes is: " << nNodes); |
+ |
+ NS_LOG_INFO ("Initialize Global Routing."); |
+ Ipv4GlobalRoutingHelper::PopulateRoutingTables (); |
+ |
+ // ---------- End of Network Set-up ---------------------------------------------- |
+ |
+ // ---------- Allocate Node Positions ----------------------------------------- |
+ |
+ NS_LOG_INFO ("Allocate Positions to Nodes."); |
+ |
+ MobilityHelper mobility_n; |
+ Ptr<ListPositionAllocator> positionAlloc_n = CreateObject<ListPositionAllocator> (); |
+ |
+ for (size_t m = 0; m < coord_array.size (); m++) |
+ { |
+ positionAlloc_n->Add (Vector (coord_array[m][0], coord_array[m][1], 0)); |
+ Ptr<Node> n0 = nodes.Get (m); |
+ Ptr<CanvasLocation> nLoc = n0->GetObject<CanvasLocation> (); |
+ if (nLoc == 0) |
+ { |
+ nLoc = CreateObject<CanvasLocation> (); |
+ n0->AggregateObject (nLoc); |
+ } |
+ // y-coordinates are negated for correct display in NetAnim |
+ // NetAnim's (0,0) reference coordinates are located on upper left corner |
+ // by negating the y coordinates, we declare the reference (0,0) coordinate |
+ // to the bottom left corner |
+ Vector nVec (coord_array[m][0], -coord_array[m][1], 0); |
+ nLoc->SetLocation (nVec); |
+ |
+ } |
+ mobility_n.SetPositionAllocator (positionAlloc_n); |
+ mobility_n.Install (nodes); |
+ |
+ // ---------- End of Allocate Node Positions ---------------------------------- |
+ |
+ // ---------- Create n*(n-1) CBR Flows ------------------------------------------- |
+ |
+ NS_LOG_INFO ("Setup Packet Sinks."); |
+ |
+ uint16_t port = 9; |
+ |
+ for (int i = 0; i < n_nodes; i++) |
+ { |
+ PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port)); |
+ ApplicationContainer apps_sink = sink.Install (nodes.Get (i)); // sink is installed on all nodes |
+ apps_sink.Start (Seconds (SinkStartTime)); |
+ apps_sink.Stop (Seconds (SinkStopTime)); |
+ } |
+ |
+ NS_LOG_INFO ("Setup CBR Traffic Sources."); |
+ |
+ for (int i = 0; i < n_nodes; i++) |
+ { |
+ for (int j = 0; j < n_nodes; j++) |
+ { |
+ if (i != j) |
+ { |
+ |
+ // We needed to generate a random number (rn) to be used to eliminate |
+ // the artificial congestion caused by sending the packets at the |
+ // same time. This rn is added to AppStartTime to have the sources |
+ // start at different time, however they will still send at the same rate. |
+ |
+ UniformVariable x (0,1); |
+ double rn = x.GetValue (); |
+ Ptr<Node> n = nodes.Get (j); |
+ Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> (); |
+ Ipv4InterfaceAddress ipv4_int_addr = ipv4->GetAddress (1, 0); |
+ Ipv4Address ip_addr = ipv4_int_addr.GetLocal (); |
+ OnOffHelper onoff ("ns3::UdpSocketFactory", InetSocketAddress (ip_addr, port)); // traffic flows from node[i] to node[j] |
+ onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1))); |
+ onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); |
+ ApplicationContainer apps = onoff.Install (nodes.Get (i)); // traffic sources are installed on all nodes |
+ apps.Start (Seconds (AppStartTime + rn)); |
+ apps.Stop (Seconds (AppStopTime)); |
+ } |
+ } |
+ } |
+ |
+ // ---------- End of Create n*(n-1) CBR Flows ------------------------------------ |
+ |
+ // ---------- Simulation Monitoring ---------------------------------------------- |
+ |
+ NS_LOG_INFO ("Configure Tracing."); |
+ |
+ AsciiTraceHelper ascii; |
+ p2p.EnableAsciiAll (ascii.CreateFileStream (tr_name.c_str ())); |
+ // p2p.EnablePcapAll (pcap_name.c_str()); |
+ |
+ // Ptr<FlowMonitor> flowmon; |
+ // FlowMonitorHelper flowmonHelper; |
+ // flowmon = flowmonHelper.InstallAll (); |
+ |
+ // Configure animator with default settings |
+ |
+ AnimationInterface anim; |
+ anim.SetServerPort (9); |
+ anim.SetOutputFile (anim_name.c_str ()); |
+ anim.StartAnimation (); |
+ |
+ NS_LOG_INFO ("Run Simulation."); |
+ |
+ Simulator::Stop (Seconds (SimTime)); |
+ Simulator::Run (); |
+ // flowmon->SerializeToXmlFile (flow_name.c_str(), true, true); |
+ Simulator::Destroy (); |
+ |
+ // ---------- End of Simulation Monitoring --------------------------------------- |
+ |
+ return 0; |
+ |
+} |
+ |
+// ---------- Function Definitions ----------------------------------------------- |
+ |
+vector<vector<bool> > readNxNMatrix (std::string adj_mat_file_name) |
+{ |
+ ifstream adj_mat_file (adj_mat_file_name.c_str ()); |
+ vector<vector<bool> > array; |
+ int i = 0; |
+ int n_nodes = 0; |
+ |
+ while (!adj_mat_file.eof ()) |
+ { |
+ string line; |
+ getline (adj_mat_file, line); |
+ if (line == "") |
+ { |
+ NS_LOG_WARN ("WARNING: Ignoring blank row in the array: " << i); |
+ break; |
+ } |
+ |
+ istringstream iss (line); |
+ bool element; |
+ vector<bool> row; |
+ int j = 0; |
+ |
+ while (iss >> element) |
+ { |
+ row.push_back (element); |
+ j++; |
+ } |
+ |
+ if (i == 0) |
+ { |
+ n_nodes = j; |
+ } |
+ |
+ if (j != n_nodes ) |
+ { |
+ NS_LOG_ERROR ("ERROR: Number of elements in line " << i << ": " << j << " not equal to number of elements in line 0: " << n_nodes); |
+ NS_LOG_ERROR ("ERROR: The number of rows is not equal to the number of columns! in the adjacency matrix"); |
+ exit (1); |
+ } |
+ else |
+ { |
+ array.push_back (row); |
+ } |
+ i++; |
+ } |
+ |
+ if (i != n_nodes) |
+ { |
+ NS_LOG_ERROR ("There are " << i << " rows and " << n_nodes << " columns."); |
+ NS_LOG_ERROR ("ERROR: The number of rows is not equal to the number of columns! in the adjacency matrix"); |
+ exit (1); |
+ } |
+ |
+ return array; |
+ |
+} |
+ |
+vector<vector<double> > readCordinatesFile (std::string node_coordinates_file_name) |
+{ |
+ ifstream node_coordinates_file (node_coordinates_file_name.c_str ()); |
+ vector<vector<double> > coord_array; |
+ int m = 0; |
+ |
+ while (!node_coordinates_file.eof ()) |
+ { |
+ string line; |
+ getline (node_coordinates_file, line); |
+ |
+ if (line == "") |
+ { |
+ NS_LOG_WARN ("WARNING: Ignoring blank row: " << m); |
+ break; |
+ } |
+ |
+ istringstream iss (line); |
+ double coordinate; |
+ vector<double> row; |
+ int n = 0; |
+ while (iss >> coordinate) |
+ { |
+ row.push_back (coordinate); |
+ n++; |
+ } |
+ |
+ if (n != 2) |
+ { |
+ NS_LOG_ERROR ("ERROR: Number of elements at line#" << m << " is " << n << " which is not equal to 2 for node coordinates file"); |
+ exit (1); |
+ } |
+ |
+ else |
+ { |
+ coord_array.push_back (row); |
+ } |
+ m++; |
+ } |
+ |
+ return coord_array; |
+ |
+} |
+ |
+void printMatrix (const char* description, vector<vector<bool> > array) |
+{ |
+ cout << "**** Start " << description << "********" << endl; |
+ for (size_t m = 0; m < array.size (); m++) |
+ { |
+ for (size_t n = 0; n < array[m].size (); n++) |
+ { |
+ cout << array[m][n] << ' '; |
+ } |
+ cout << endl; |
+ } |
+ cout << "**** End " << description << "********" << endl; |
+ |
+} |
+ |
+void printCoordinateArray (const char* description, vector<vector<double> > coord_array) |
+{ |
+ cout << "**** Start " << description << "********" << endl; |
+ for (size_t m = 0; m < coord_array.size (); m++) |
+ { |
+ for (size_t n = 0; n < coord_array[m].size (); n++) |
+ { |
+ cout << coord_array[m][n] << ' '; |
+ } |
+ cout << endl; |
+ } |
+ cout << "**** End " << description << "********" << endl; |
+ |
+} |
+ |
+// ---------- End of Function Definitions ---------------------------------------- |