#include "flow_stat.hpp"
#include "ns3/applications-module.h"
#include "ns3/coll-trace-tag.h"
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/netanim-module.h"
#include "ns3/network-module.h"
#include "ns3/nstime.h"
#include "ns3/point-to-point-module.h"
#include "ns3/simulator.h"
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
using namespace ns3;
NodeContainer g_nodes; // Declare nodes objects
double SimTime = 10.00;
double SinkStartTime = 0.00001;
double AppStartTime = 0.0001;
constexpr uint32_t NEWFLOWID = UINT32_MAX;
// ---------- Prototypes ------------------------------------------------------
uint16_t g_port = 9;
// std::vector<std::vector<ApplicationContainer>> g_sendApplication;
void RecvComplete(Ptr<const Packet> pkt, const Address &src,
const Address &dest);
vector<vector<int>> readNxNMatrix(std::string adj_mat_file_name);
void printMatrix(const char *description, vector<vector<bool>> array);
uint32_t GetNextAction(uint32_t id);
void SendComplete(Ptr<const Packet> pkt);
void StartSendApp(int srcId, int destId);
NS_LOG_COMPONENT_DEFINE("COLL_SCHE");
void InstallSendApp(const uint32_t srcId, const uint32_t destId,
const uint32_t preFlowid) {
static uint32_t curFlowId = 0;
// auto i = srcId;
if (srcId >= NodeList::GetNNodes() || destId >= NodeList::GetNNodes()) {
cerr << "wrong" << endl;
return;
}
// printf ("%s with %d %d\n", __FUNCTION__, srcId, destId);
Ptr<Node> dstNode = NodeList::GetNode(destId);
Ptr<Ipv4> ipv4 = dstNode->GetObject<Ipv4>();
Ipv4InterfaceAddress ipv4_int_addr = ipv4->GetAddress(1, 0);
Ipv4Address ip_addr = ipv4_int_addr.GetLocal();
BulkSendHelper bulk("ns3::TcpSocketFactory",
InetSocketAddress(ip_addr, g_port));
bulk.SetAttribute("MaxBytes", UintegerValue(1048576)); // 64MB
// 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
auto apps = bulk.Install(NodeList::GetNode(srcId));
// add tag
auto bulkapp = DynamicCast<BulkSendApplication>(apps.Get(0));
uint32_t flowId = 0;
if (preFlowid == NEWFLOWID) {
flowId = curFlowId++;
} else {
flowId = preFlowid;
}
assert(apps.GetN() == 1);
// stat flow info
std::ostringstream oss;
oss << "start," << flowId << "," << srcId << "," << destId << ","
<< Simulator::Now().GetSeconds() << "\n";
NS_LOG_UNCOND(oss.str());
apps.Start(Simulator::Now());//!!! should start at 2s but real start at time 4s should change to apps.Start(Seconds(0));
apps.Stop(Seconds(SimTime));
apps.Get(0)->TraceConnectWithoutContext("Tx", MakeCallback(&SendComplete));
}
void InstallSinkApp(const uint32_t destId) {
PacketSinkHelper sink("ns3::TcpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), g_port));
// 将PacketSink安装到节点1
ApplicationContainer sinkApps = sink.Install(NodeList::GetNode(destId));
sinkApps.Get(0)->TraceConnectWithoutContext("RxWithAddresses",
MakeCallback(&RecvComplete));
sinkApps.Start(Seconds(SinkStartTime));
sinkApps.Stop(Seconds(SimTime));
}
void RecvComplete(Ptr<const Packet> pkt, const Address &src,
const Address &dest) {
static int count = 0;
static int srcId = 1;
static int destId = 2;
count++;
if (count > 10000) {
InstallSendApp((srcId++) % 6, (destId++) % 6, NEWFLOWID);
// InstallSendApp (curId + 1, curId + 3);
std::ostringstream oss;
oss << "recv," << srcId << "," << destId << ","
<< Simulator::Now().GetSeconds() << "\n";
NS_LOG_UNCOND(oss.str());
}
// if(!pkt->m_connected){
// printf("has completed a flow from node %d\n",pkt->NodeId);
// // cout<<" src "<<src<<"dest "<<dest<<"on time
// "<<Simulator::Now().GetSeconds()<< endl;
// }
}
void SendComplete(Ptr<const Packet> pkt) {
;
}
int main(int argc, char *argv[]) {
// ---------- Simulation Variables ------------------------------------------
// Change the variables and file names only in this block!
std::string LinkRateUnit("MBps");
std::string LinkDelay("2ms");
srand((unsigned)time(NULL)); // generate different seed each time
// LogComponentEnable ("BulkSendApplication", LOG_LEVEL_INFO);
// LogComponentEnable ("PacketSink", LOG_LEVEL_INFO);
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(
"contrib/opengym/examples/collective_schedule/dymmy_beel_6_adj.txt");
CommandLine cmd(__FILE__);
cmd.Parse(argc, argv);
// ---------- End of Simulation Variables ----------------------------------
// ---------- Read Adjacency Matrix ----------------------------------------
auto 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 -----------------------------------
int n_nodes = Adj_Matrix.size();
// g_sendApplication.resize (n_nodes);
printf("node num %d\n", n_nodes);
// ---------- End of Read Node Coordinates File ----------------------------
// ---------- Network Setup ------------------------------------------------
NS_LOG_INFO("Create Nodes.");
g_nodes.Create(n_nodes);
NS_LOG_INFO("Create P2P Link Attributes.");
PointToPointHelper p2p;
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 (auto band = Adj_Matrix[i][j]; band != 0) // C++17
{
NodeContainer n_links = NodeContainer(g_nodes.Get(i), g_nodes.Get(j));
std::string LinkRate = to_string(band) + LinkRateUnit;
p2p.SetDeviceAttribute("DataRate", StringValue(LinkRate));
printf("node %ld to node %ld: %s\n", i, j, LinkRate.c_str());
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: " << g_nodes.GetN());
NS_LOG_INFO("Initialize Global Routing.");
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
// ---------- End of Network Set-up ----------------------------------------
// ---------- Create n*(n-1) CBR Flows -------------------------------------
NS_LOG_INFO("Setup Packet Sinks.");
NS_LOG_INFO("Setup CBR Traffic Sources.");
// for (int i = 0; i < n_nodes; i++)
// {
// for (int j = 0; j < n_nodes; j++)
// {
// InstallSendApp (i, j);
// }
// }
fprintf(stdout, "action,flowid,srcid,destid,time\n");
Simulator::Schedule(Seconds(2),InstallSendApp,0, 1, NEWFLOWID);
for (uint32_t i = 0; i < NodeList::GetNNodes(); i++) {
InstallSinkApp(i);
}
// create a ns3 bulkApplication send 64kb data from 0 to 1
// 为接收完成事件添加回调函数
// sinkApps.Get (0)->TraceConnectWithoutContext ("RxWithAddresses",
// MakeCallback (&ReceiveComplete));
// ---------- 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
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 ---------------------------------
cout << "end simulation" << endl;
return 0;
}
// ---------- Function Definitions -------------------------------------------
vector<vector<int>> readNxNMatrix(std::string adj_mat_file_name) {
ifstream adj_mat_file;
adj_mat_file.open(adj_mat_file_name.c_str(), ios::in);
if (adj_mat_file.fail()) {
NS_FATAL_ERROR("File " << adj_mat_file_name.c_str() << " not found");
}
vector<vector<int>> 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);
int element;
vector<int> 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;
}
vector<vector<double>>
readCordinatesFile(std::string node_coordinates_file_name) {
ifstream node_coordinates_file;
node_coordinates_file.open(node_coordinates_file_name.c_str(), ios::in);
if (node_coordinates_file.fail()) {
NS_FATAL_ERROR("File " << node_coordinates_file_name.c_str()
<< " not found");
}
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++;
}
node_coordinates_file.close();
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;
}