/* * 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 * Author: Justin P. Rohrer * Author: Amit Dandekar * * James P.G. Sterbenz , director * ResiliNets Research Group https://resilinets.org/ * Information and Telecommunication Technology Center * and * Department of Electrical Engineering and Computer Science * The University of Kansas * Lawrence, KS USA * * Work supported in part by NSF FIND (Future Internet Design) Program * under grant CNS-0626918 (Postmodern Internet Architecture) and * by NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI) * * 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 "ns3/applications-module.h" #include "ns3/assert.h" #include "ns3/core-module.h" #include "ns3/global-route-manager.h" #include "ns3/internet-module.h" #include "ns3/ipv4-global-routing-helper.h" #include "ns3/mobility-module.h" #include "ns3/netanim-module.h" #include "ns3/network-module.h" #include "ns3/point-to-point-module.h" #include #include #include #include #include #include using namespace ns3; // ---------- Prototypes ------------------------------------------------------ std::vector> readNxNMatrix(std::string adj_mat_file_name); std::vector> readCordinatesFile(std::string node_coordinates_file_name); void printCoordinateArray(const char* description, std::vector> coord_array); void printMatrix(const char* description, std::vector> 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(nullptr)); // 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.xml"); std::string adj_mat_file_name("examples/matrix-topology/adjacency_matrix.txt"); std::string node_coordinates_file_name("examples/matrix-topology/node_coordinates.txt"); CommandLine cmd(__FILE__); cmd.Parse(argc, argv); // ---------- End of Simulation Variables ---------------------------------- // ---------- Read Adjacency Matrix ---------------------------------------- std::vector> 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 ----------------------------------- std::vector> 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_FATAL_ERROR("The number of lines in coordinate file is: " << n_nodes << " not equal to the number of nodes in adjacency matrix size " << matrixDimension); } // ---------- 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; 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); 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); NS_LOG_INFO("Number of all nodes is: " << nodes.GetN()); 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 positionAlloc_n = CreateObject(); for (size_t m = 0; m < coord_array.size(); m++) { positionAlloc_n->Add(Vector(coord_array[m][0], coord_array[m][1], 0)); Ptr n0 = nodes.Get(m); Ptr nLoc = n0->GetObject(); if (!nLoc) { nLoc = CreateObject(); 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->SetPosition(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. Ptr x = CreateObject(); x->SetAttribute("Min", DoubleValue(0)); x->SetAttribute("Max", DoubleValue(1)); double rn = x->GetValue(); Ptr n = nodes.Get(j); Ptr ipv4 = n->GetObject(); 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.SetConstantRate(DataRate(AppPacketRate)); 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)); // p2p.EnablePcapAll(pcap_name); // Ptr flowmon; // FlowMonitorHelper flowmonHelper; // flowmon = flowmonHelper.InstallAll(); // Configure animator with default settings AnimationInterface anim(anim_name); NS_LOG_INFO("Run Simulation."); Simulator::Stop(Seconds(SimTime)); Simulator::Run(); // flowmon->SerializeToXmlFile(flow_name, true, true); Simulator::Destroy(); // ---------- End of Simulation Monitoring --------------------------------- return 0; } // ---------- Function Definitions ------------------------------------------- std::vector> readNxNMatrix(std::string adj_mat_file_name) { std::ifstream adj_mat_file; adj_mat_file.open(adj_mat_file_name, std::ios::in); if (adj_mat_file.fail()) { NS_FATAL_ERROR("File " << adj_mat_file_name << " not found"); } std::vector> array; int i = 0; int n_nodes = 0; while (!adj_mat_file.eof()) { std::string line; getline(adj_mat_file, line); if (line == "") { NS_LOG_WARN("WARNING: Ignoring blank row in the array: " << i); break; } std::istringstream iss(line); bool element; std::vector 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_FATAL_ERROR("ERROR: The number of rows is not equal to the number of columns! in " "the adjacency matrix"); } else { array.push_back(row); } i++; } if (i != n_nodes) { NS_LOG_ERROR("There are " << i << " rows and " << n_nodes << " columns."); NS_FATAL_ERROR("ERROR: The number of rows is not equal to the number of columns! in the " "adjacency matrix"); } adj_mat_file.close(); return array; } std::vector> readCordinatesFile(std::string node_coordinates_file_name) { std::ifstream node_coordinates_file; node_coordinates_file.open(node_coordinates_file_name, std::ios::in); if (node_coordinates_file.fail()) { NS_FATAL_ERROR("File " << node_coordinates_file_name << " not found"); } std::vector> coord_array; int m = 0; while (!node_coordinates_file.eof()) { std::string line; getline(node_coordinates_file, line); if (line == "") { NS_LOG_WARN("WARNING: Ignoring blank row: " << m); break; } std::istringstream iss(line); double coordinate; std::vector 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++; } node_coordinates_file.close(); return coord_array; } void printMatrix(const char* description, std::vector> array) { std::cout << "**** Start " << description << "********" << std::endl; for (size_t m = 0; m < array.size(); m++) { for (size_t n = 0; n < array[m].size(); n++) { std::cout << array[m][n] << ' '; } std::cout << std::endl; } std::cout << "**** End " << description << "********" << std::endl; } void printCoordinateArray(const char* description, std::vector> coord_array) { std::cout << "**** Start " << description << "********" << std::endl; for (size_t m = 0; m < coord_array.size(); m++) { for (size_t n = 0; n < coord_array[m].size(); n++) { std::cout << coord_array[m][n] << ' '; } std::cout << std::endl; } std::cout << "**** End " << description << "********" << std::endl; } // ---------- End of Function Definitions ------------------------------------