/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 *
 * This program is a modification of mesh.cc
 *
 *
 * By default this script creates m_xSize * m_ySize(5*5) square grid topology with
 * IEEE802.11s stack installed at each node with peering management
 * and HWMP protocol.
 * 20 free mobile nodes are added to the grid.
 * Set up a stream from node2 to node 3
 *  
 * There may be some mistakes. The function is not implemented.
 * Thank you very much.
 * 
 */


#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/wifi-module.h"
#include "ns3/mesh-module.h"
#include "ns3/mobility-module.h"

//#include "ns3/ipv4-static-routing-helper.h"//w1-11
//#include "ns3/on-off-helper.h"//None
#include"ns3/flow-monitor-helper.h"//w1-11
#include "ns3/flow-monitor-module.h"
#include "ns3/waypoint-mobility-model.h"     //sth1214   to use way point 
#include "ns3/random-variable.h"//w1-11
#include "ns3/random-variable-stream.h"
#include "ns3/packet.h"

#include <vector>//w1-11

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("newMesh");
class MeshTest
{
public:
  /// Init test
  MeshTest ();
  /// Configure test from command line arguments
  void Configure (int argc, char ** argv);
  /// Run test
  int Run ();
  void throughput(Ptr<FlowMonitor> monitor,FlowMonitorHelper*  flowmon);
private:
  double begincbr;
  int       m_xSize;
  int       m_ySize;
  double    m_step;
  double    m_randomStart;
  double    m_totalTime;
  double    m_packetInterval;
  uint16_t  m_packetSize;
  uint32_t  m_nIfaces;
  bool      m_chan;
  bool      m_pcap;
  std::string m_stack;
  std::string m_root;
  /// List of network nodes
  NodeContainer allnodes;      /// List of all network nodes
   NodeContainer MRnodes;      
   NodeContainer MPnodes;       
  /// List of all mesh point devices
   NetDeviceContainer MRDevices;      //   List of MR point devices
      NetDeviceContainer MPDevices;      //    List of MP point devices
      NetDeviceContainer  allDevices;    // List of all mesh point devices
  //Addresses of interfaces:
  Ipv4InterfaceContainer interfaces;
  // MeshHelper. Report is not static methods
  MeshHelper mesh;
private:
  /// Create nodes and setup their mobility
  void CreateNodes ();
  /// Install internet m_stack on nodes
  void InstallInternetStack ();
  /// Install applications
  void InstallApplication ();
  /// Print mesh devices diagnostics
  void Report ();
  void InstallONOFFApplication();
};
MeshTest::MeshTest () :
  begincbr(10),
  m_xSize (5),
  m_ySize (5),
  m_step (100.0),
  m_randomStart (0.1),
  m_totalTime (100.0),
  m_packetInterval (0.1),
  m_packetSize (1024),
  m_nIfaces (1),
  m_chan (true),
  m_pcap (false),
  m_stack ("ns3::Dot11sStack"),
  m_root ("ff:ff:ff:ff:ff:ff")
{
}
void
MeshTest::Configure (int argc, char *argv[])
{
  CommandLine cmd;
  cmd.AddValue ("x-size", "Number of nodes in a row grid. [5]", m_xSize);
  cmd.AddValue ("y-size", "Number of rows in a grid. [5]", m_ySize);
  cmd.AddValue ("step",   "Size of edge in our grid, meters. [100 m]", m_step);
  /*
   * As soon as starting node means that it sends a beacon,
   * simultaneous start is not good.
   */
  cmd.AddValue ("start",  "Maximum random start delay, seconds. [0.1 s]", m_randomStart);
  cmd.AddValue ("time",  "Simulation time, seconds [100 s]", m_totalTime);
  cmd.AddValue ("packet-interval",  "Interval between packets in UDP ping, seconds [0.001 s]", m_packetInterval);
  cmd.AddValue ("packet-size",  "Size of packets in UDP ping", m_packetSize);
  cmd.AddValue ("interfaces", "Number of radio interfaces used by each mesh point. [1]", m_nIfaces);
  cmd.AddValue ("channels",   "Use different frequency channels for different interfaces. [0]", m_chan);
  cmd.AddValue ("pcap",   "Enable PCAP traces on interfaces. [0]", m_pcap);
  cmd.AddValue ("stack",  "Type of protocol stack. ns3::Dot11sStack by default", m_stack);
  cmd.AddValue ("root", "Mac address of root mesh point in HWMP", m_root);

  cmd.Parse (argc, argv);
  NS_LOG_DEBUG ("Grid:" << m_xSize << "*" << m_ySize);
  NS_LOG_DEBUG ("Simulation time: " << m_totalTime << " s");
}
void
MeshTest::CreateNodes ()
{ 
  /*
   * Create m_ySize*m_xSize stations to form a grid topology
   */
	 int nodeSpeed = 3; //in  m/s
	 int nodePause = 5; //in   s   modify
  MRnodes.Create (m_ySize*m_xSize);
  MPnodes.Create(20);
  allnodes.Add(MRnodes);  
 	  allnodes.Add(MPnodes);   
  // Configure YansWifiChannel
  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
  wifiPhy.Set ("EnergyDetectionThreshold", DoubleValue (-89.0) );     ///sth1201  down
  	  wifiPhy.Set ("CcaMode1Threshold", DoubleValue (-62.0) );
  	  wifiPhy.Set ("TxGain", DoubleValue (1.0) );
  	  wifiPhy.Set ("RxGain", DoubleValue (1.0) );
  	  wifiPhy.Set ("TxPowerLevels", UintegerValue (1) );
  	  wifiPhy.Set ("TxPowerEnd", DoubleValue (18.0) );
  	  wifiPhy.Set ("TxPowerStart", DoubleValue (18.0) );
  	  wifiPhy.Set ("RxNoiseFigure", DoubleValue (7.0) );
  	 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
  	 wifiPhy.SetChannel (wifiChannel.Create ());

  /*
   * Create mesh helper and set stack installer to it
   * Stack installer creates all needed protocols and install them to
   * mesh point device
   */
  mesh = MeshHelper::Default ();
  if (!Mac48Address (m_root.c_str ()).IsBroadcast ())
    {
      mesh.SetStackInstaller (m_stack, "Root", Mac48AddressValue (Mac48Address (m_root.c_str ())));
    }
  else
    {
      //If root is not set, we do not use "Root" attribute, because it
      //is specified only for 11s
      mesh.SetStackInstaller (m_stack);
    }
  if (m_chan)
    {
      mesh.SetSpreadInterfaceChannels (MeshHelper::SPREAD_CHANNELS);
    }
  else
    {
      mesh.SetSpreadInterfaceChannels (MeshHelper::ZERO_CHANNEL);
    }
  mesh.SetMacType ("RandomStart", TimeValue (Seconds (m_randomStart)));
  // Set number of interfaces - default is single-interface mesh point
  mesh.SetNumberOfInterfaces (m_nIfaces);
  // Install protocols and return container if MeshPointDevices
 // meshDevices = mesh.Install (wifiPhy, nodes);
  MRDevices = mesh.Install (wifiPhy, MRnodes);   ///sth1117  modify
   MPDevices = mesh.Install (wifiPhy, MPnodes);   ///sth1117  add  sth2016-04-18 modified
      //Malicious_BlackholeDevice =  mesh_blackhole.Install (wifiPhy,Malicious_BlackholeNode);    ///sth1122
       allDevices.Add(MRDevices);       ///sth1117
  allDevices.Add(MPDevices); ///sth1117
  Ptr<UniformRandomVariable> rand=CreateObject<UniformRandomVariable>();//wang1-22
    /********************************************************/
  /*              Setup mobility - static grid topology                       */
  /********************************************************/
  MobilityHelper mobility;
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0),
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (m_step),
                                 "DeltaY", DoubleValue (m_step),
                                 "GridWidth", UintegerValue (m_xSize),
                                 "LayoutType", StringValue ("RowFirst"));
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (MRnodes);
  /********************************************************/
     /*              new mobility of MP (client nodes )                        */
     /********************************************************/
  MobilityHelper mobilityRandom;
       int64_t streamIndex = 0; // used to get consistent mobility across scenarios

       ObjectFactory pos;
       pos.SetTypeId ("ns3::RandomRectanglePositionAllocator");
       pos.Set ("X", StringValue ("ns3::UniformRandomVariable[Min=-50.0|Max=450.0]"));  
       pos.Set ("Y", StringValue ("ns3::UniformRandomVariable[Min=-50.0|Max=450.0]"));  

       Ptr<PositionAllocator> taPositionAlloc = pos.Create ()->GetObject<PositionAllocator> ();
       streamIndex += taPositionAlloc->AssignStreams (streamIndex);

       std::stringstream ssSpeed;
       ssSpeed << "ns3::UniformRandomVariable[Min=0.0|Max=" << nodeSpeed << "]";
       std::stringstream ssPause;
       ssPause << "ns3::ConstantRandomVariable[Constant=" << nodePause << "]";
       mobilityRandom.SetMobilityModel ("ns3::RandomWaypointMobilityModel",
                                       "Speed", StringValue (ssSpeed.str ()),
                                       "Pause", StringValue (ssPause.str ()),
                                       "PositionAllocator", PointerValue (taPositionAlloc));
       mobilityRandom.SetPositionAllocator (taPositionAlloc);
       mobilityRandom.Install (MPnodes);
       streamIndex += mobilityRandom.AssignStreams (MPnodes, streamIndex);


  if (m_pcap)
    wifiPhy.EnablePcapAll (std::string ("mp-"));//wang1-24
}
void
MeshTest::InstallInternetStack ()
{
  InternetStackHelper internetStack;
  internetStack.Install (allnodes);
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");
  interfaces = address.Assign (allDevices);
}
void
MeshTest::InstallApplication ()
{
  UdpEchoServerHelper echoServer (12345);
  ApplicationContainer serverApps = echoServer.Install (allnodes.Get (25));
  serverApps.Start (Seconds (0.0));
  serverApps.Stop (Seconds (m_totalTime));
  UdpEchoClientHelper echoClient (interfaces.GetAddress (25), 12345);
  echoClient.SetAttribute ("MaxPackets", UintegerValue ((uint32_t)(m_totalTime*(1/m_packetInterval))));
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (m_packetInterval)));
  echoClient.SetAttribute ("PacketSize", UintegerValue (m_packetSize));
  ApplicationContainer clientApps = echoClient.Install (MPnodes.Get (9));
  clientApps.Start (Seconds (0.0));
  clientApps.Stop (Seconds (m_totalTime));
}
/********************************************************/
    /*              Add flow                        */
    /********************************************************/
void
MeshTest::InstallONOFFApplication()
{
	  ApplicationContainer cbrApps[1];
	  uint16_t cbrPort = 12345;

	   // flow 1:  node   -> node  10.1.1.3 -> 10.1.1.4
	  OnOffHelper onOffHelper1 ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.4"), cbrPort));   //sink node
	  onOffHelper1.SetAttribute ("PacketSize", UintegerValue (256));
	  onOffHelper1.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
	  onOffHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
	  onOffHelper1.SetAttribute ("DataRate", StringValue ("200Kbps"));
	  onOffHelper1.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.03)));
	  ///cbrApps.Add (onOffHelper1.Install (MPnodes.Get (0)));
	  //cbrApps[0]= (onOffHelper1.Install (MPnodes.Get (0)));    ///
	  cbrApps[0]=(onOffHelper1.Install (allnodes.Get (2)));    //
	  cbrApps[0].Stop(Seconds (m_totalTime));  //
	  PacketSinkHelper sink1 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.4",cbrPort));
	  cbrApps[0] = sink1.Install (allnodes.Get (3));   

//	  // flow 2:  node  -> node   10.1.1.4->10.1.1.12
//	  /** \internal
//	   * The slightly different start times and data rates are a workaround
//	   * for \bugid{388} and \bugid{912}
//	   */
//      OnOffHelper onOffHelper2 ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.12"), cbrPort));
//	  onOffHelper2.SetAttribute ("PacketSize", UintegerValue (256));
//	  onOffHelper2.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
//	  onOffHelper2.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
//	  onOffHelper2.SetAttribute ("DataRate", StringValue ("201Kbps"));
//	  onOffHelper2.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.03)));
//	  ///cbrApps.Add (onOffHelper2.Install (MPnodes.Get (2)));
//	  cbrApps[1]= (onOffHelper2.Install (allnodes.Get(3)));
//	  cbrApps[1].Stop(Seconds (m_totalTime));
//	  PacketSinkHelper sink2 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.12",cbrPort));
//		  cbrApps[1] = sink2.Install (allnodes.Get (11));
//
//	  //flow3  10.1.1.30-> 10.1.1.27
//	  OnOffHelper onOffHelper3("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.27"), cbrPort));
//		  onOffHelper3.SetAttribute ("PacketSize", UintegerValue (256));
//		  onOffHelper3.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
//		  onOffHelper3.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
//	  onOffHelper3.SetAttribute ("DataRate", StringValue ("205Kbps"));
//	  onOffHelper3.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.06)));
//      ///cbrApps.Add (onOffHelper3.Install (MPnodes.Get (4)));
//	  cbrApps[2]=(onOffHelper3.Install (MPnodes.Get (4)));    //10.1.1.30
//	  cbrApps[2].Stop(Seconds (m_totalTime));
//	  PacketSinkHelper sink3 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.27",cbrPort));
//		  cbrApps[2] = sink3.Install (allnodes.Get (26));     ///10.1.1.27
//
//	  //flow4  10.1.1.36-> 10.1.1.39
//	  OnOffHelper onOffHelper4("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.39"), cbrPort));
//		  onOffHelper4.SetAttribute ("PacketSize", UintegerValue (256));
//		  onOffHelper4.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
//		  onOffHelper4.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
//	  onOffHelper4.SetAttribute ("DataRate", StringValue ("199Kbps"));
//	  onOffHelper4.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.09)));
//      ///cbrApps.Add (onOffHelper4.Install (MPnodes.Get (11)));
//	  cbrApps[3]= (onOffHelper4.Install (MPnodes.Get (10)));  //10.1.1.36
//	  cbrApps[3].Stop(Seconds (m_totalTime));
//	  PacketSinkHelper sink4 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.39",cbrPort));
//		  cbrApps[3] = sink4.Install (allnodes.Get (38));   //10.1.1.39
//
////	//flow5  10.1.1.50-> 10.1.1.60
////        OnOffHelper onOffHelper5("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.60"), cbrPort));
////        onOffHelper5.SetAttribute ("PacketSize", UintegerValue (256));
////	    onOffHelper5.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
////	    onOffHelper5.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
////		 onOffHelper5.SetAttribute ("DataRate", StringValue ("198Kbps"));
////		 onOffHelper5.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.12)));
////	     cbrApps[4]= (onOffHelper5.Install (allnodes.Get (49)));  //10.1.1.50
////	     cbrApps[4].Stop(Seconds (m_totalTime));
////		 PacketSinkHelper sink5 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.60",cbrPort));
////		 cbrApps[4] = sink5.Install (allnodes.Get (59));   //10.1.1.60
//
////	//flow6  10.1.1.38-> 10.1.1.49
////            OnOffHelper onOffHelper6("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.49"), cbrPort));
////	    onOffHelper6.SetAttribute ("PacketSize", UintegerValue (256));
////	    onOffHelper6.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
////            onOffHelper6.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
////	    onOffHelper6.SetAttribute ("DataRate", StringValue ("201Kbps"));
////		 onOffHelper6.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.15)));
////	cbrApps[5]= (onOffHelper6.Install (allnodes.Get (37)));  //10.1.1.38
////	cbrApps[5].Stop(Seconds (m_totalTime));
////	 PacketSinkHelper sink6 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.49",cbrPort));
////	cbrApps[5] = sink6.Install (allnodes.Get (48));   //10.1.1.49
//
//	//flow5  10.1.1.27-> 10.1.1.44
//	 OnOffHelper onOffHelper7("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.44"), cbrPort));
//	onOffHelper7.SetAttribute ("PacketSize", UintegerValue (256));
//	onOffHelper7.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
//	 onOffHelper7.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
//	onOffHelper7.SetAttribute ("DataRate", StringValue ("190Kbps"));
//	onOffHelper7.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.18)));
//	cbrApps[6]= (onOffHelper7.Install (allnodes.Get (26)));  //10.1.1.39
//	cbrApps[6].Stop(Seconds (m_totalTime));
//	PacketSinkHelper sink7 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.44",cbrPort));
//	cbrApps[6] = sink7.Install (allnodes.Get (43));   //10.1.1.46
//
////	//flow8  10.1.1.61-> 10.1.1.63
////	OnOffHelper onOffHelper8("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.63"), cbrPort));
////	onOffHelper8.SetAttribute ("PacketSize", UintegerValue (256));
////	onOffHelper8.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
////	onOffHelper8.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
////	onOffHelper8.SetAttribute ("DataRate", StringValue ("210Kbps"));
////	onOffHelper8.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.21)));
////	cbrApps[7]= (onOffHelper8.Install (allnodes.Get (60)));  //10.1.1.62
////	 cbrApps[7].Stop(Seconds (m_totalTime));
////	 PacketSinkHelper sink8 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.63",cbrPort));
////	 cbrApps[7] = sink8.Install (allnodes.Get (62));   //10.1.1.64
//
////        //flow9  10.1.1.29-> 10.1.1.45
////        OnOffHelper onOffHelper9("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.45"), cbrPort));
////        onOffHelper9.SetAttribute ("PacketSize", UintegerValue (256));
////        onOffHelper9.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
////	onOffHelper9.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
////	 onOffHelper9.SetAttribute ("DataRate", StringValue ("192Kbps"));
////	 onOffHelper9.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.24)));
////	 cbrApps[8]= (onOffHelper9.Install (allnodes.Get (28)));  //10.1.1.29
////	 cbrApps[8].Stop(Seconds (m_totalTime));
////	 PacketSinkHelper sink9 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.45",cbrPort));
////	cbrApps[8] = sink9.Install (allnodes.Get (44));   //10.1.1.45
//
////	//flow10  10.1.1.37-> 10.1.1.62
////	 OnOffHelper onOffHelper10("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("10.1.1.62"), cbrPort));
////	 onOffHelper10.SetAttribute ("PacketSize", UintegerValue (256));
////	 onOffHelper10.SetAttribute ("OnTime",  StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
////	onOffHelper10.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
////	onOffHelper10.SetAttribute ("DataRate", StringValue ("208Kbps"));
////	 onOffHelper10.SetAttribute ("StartTime", TimeValue (Seconds (begincbr+0.27)));
////	 cbrApps[9]= (onOffHelper10.Install (allnodes.Get (36)));  //10.1.1.51
////	cbrApps[9].Stop(Seconds (m_totalTime));
////	PacketSinkHelper sink10 ("ns3::UdpSocketFactory",InetSocketAddress("10.1.1.62",cbrPort));
////	cbrApps[9] = sink10.Install (allnodes.Get (61));   //10.1.1.62

}
int
MeshTest::Run ()
{
  CreateNodes ();
  InstallInternetStack ();
  InstallApplication ();
  InstallONOFFApplication ();
  //Simulator::Schedule (Seconds (m_totalTime), &MeshTest::Report, this);
  //xxx  Install FlowMonitor on all nodes
    FlowMonitorHelper flowmon;
     Ptr<FlowMonitor> monitor = flowmon.InstallAll();
     //*********************************************************************************************//
     //Simulator::Schedule(Seconds(11.0), &MeshTest::throughput,this,monitor,flowmon);  // sth  2016-03-02


     Simulator::Stop (Seconds (m_totalTime));


     throughput(monitor,&flowmon);
  Simulator::Run ();


  Simulator::Destroy ();
  return 0;
}
void
MeshTest::Report ()
{
  unsigned n (0);
  for (NetDeviceContainer::Iterator i = allDevices.Begin (); i != allDevices.End (); ++i, ++n)
    {
      std::ostringstream os;
      os << "mmp-report-" << n << ".xml";
      std::cerr << "Printing mesh point device #" << n << " diagnostics to " << os.str () << "\n";
      std::ofstream of;
      of.open (os.str ().c_str ());
      if (!of.is_open ())
        {
          std::cerr << "Error: Can't open file " << os.str () << "\n";
          return;
        }
      mesh.Report (*i, of);
      of.close ();
    }
}
/********************************************************/
    /*             calculate throughput , packet loss rate and delay   (entire network)                  */
    /********************************************************/


void MeshTest::throughput(Ptr<FlowMonitor> monitor,FlowMonitorHelper*  flowmon)
{
	  monitor->CheckForLostPackets();
	    	monitor->SerializeToXmlFile("monitor.xml", true, true);
	    	Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon->GetClassifier());
	    	std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();
	    	//double Throughput = 0.0;
	    	  	u_int32_t rxPackets = 0, txPackets = 0;
	    	  	u_int64_t rxBytes = 0;
	    	  	int64_t firstRxTime = 9999999999;
	    	  	int64_t lastRxTime = 0;
	    	  	u_int64_t delaySum = 0 ;
	    	  //	int64_t pkt_byte_sum[1200];
	    	  //	int64_t init=0;
	    	  //	int k=0;
	    	  //	double start_time;
	    	  //	double end_time[1200];

	    		for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i =
	    	    				stats.begin(); i != stats.end(); i++) {

	    	    			if (i->first > 0) {
	    	    				Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
	    	    	//			if (t.sourcePort != 698 && t.sourcePort != 654 ) {
	    	    				if (t.destinationPort == 12345)
	    	    				{
	    	    					txPackets += i->second.txPackets;
	    	    					rxPackets += i->second.rxPackets;
	    	    					delaySum += i->second.delaySum.GetMilliSeconds();
	    	    					rxBytes += i->second.rxBytes;

	    	    					std::cout << "Flow " << i->first<< " (" << t.sourceAddress
	    	    							<< " -> " << t.destinationAddress << ")\n";
	    	    					std::cout << "  send packets：	" << i->second.txPackets << "\n";
	    	    					std::cout << "  send bytes：	" << i->second.txBytes << "\n";

	    	    					int64_t thisFirstRxTime = i->second.timeFirstRxPacket.GetMilliSeconds();
	    	    					int64_t thisLastRxTime = i->second.timeLastRxPacket.GetMilliSeconds();

	    	    					if (thisFirstRxTime < firstRxTime) firstRxTime = thisFirstRxTime;
	    	    					if (thisLastRxTime > lastRxTime) lastRxTime = thisLastRxTime;

	    	    					/********************************************************/
	    	    					    /*          calculate throughput , packet loss rate and delay  in every flow        */
	    	    					    /********************************************************/

	    	    	//				std::cout   << "  ";

	    	    					std::cout << "  receive packets： 	" << i->second.rxPackets << "\n";
	    	    					std::cout << "  receive bytes：  	" << i->second.rxBytes << "\n";

	    	    					std::ofstream out5("delayHistogram.xml");
	    	    					i->second.delayHistogram.SerializeToXmlStream(out5, 0 ,std::string("delayHistogr"));


	    	    	//				std::cout << "  : 	"
	    	    	//						<< i->second.rxBytes * 8.0 / 9.0 / 1000 / 1000
	    	    	//						<< " Mbps\n";
	    	    					std::cout << "  packet loss rate:    	"
	    	    							<< (1 - ((double)i->second.rxPackets / (double)i->second.txPackets)) * 100
	    	    							<< "%\n";
	    	    					std::cout << "  total delay：   	"
	    	    							<< i->second.delaySum.GetMilliSeconds() << " ms\n";
	    	    					std::cout << "  average delay：   	"
	    	    							<< (double)i->second.delaySum.GetMilliSeconds() / (double)i->second.rxPackets << " ms/packet\n";

	    	    					NS_LOG_UNCOND( "  throughput:  	" << (double)rxBytes * 8 / (double)(lastRxTime - firstRxTime) << " Kbps");
	    	    					//    					Throughput = i->second.rxBytes * 8.0
	    	//    							/ (i->second.timeLastRxPacket.GetSeconds()
	    	//    									- i->second.timeFirstTxPacket.GetSeconds())
	    	//    							/ 1024;
	    	    					//	//NS_LOG_UNCOND("Throughput: " <<  Throughput << " Kbps");

	    	    				}
	    	    			}
	    	    		}
	    		/********************************************************/
	    		    /*             calculate  throughput , packet loss rate and delay  of entire network                    */
	    		    /********************************************************/

	    		        std::cout << "\n\n entire network:"<<std::endl;
	    	    		std::cout << "\n\n  send packets:	" << txPackets << "\n";
	    	    		std::cout << "  receive packets:	" << rxPackets << "\n";
	    	    		std::cout << "  packet loss rate:   	" << (1 - ((double)rxPackets / (double)txPackets)) * 100 << "%\n";

	    	    		std::cout << "  total delay:   	" << delaySum << " ms\n";
	    	    		std::cout << "  average delay:   	" << (double)delaySum / (double)rxPackets << " ms/packet\n";
	    	    		std::cout << "  throughput:  	" << (double)rxBytes * 8 / (double)(lastRxTime - firstRxTime) << " Kbps";


}



int main (int argc, char *argv[])
{
  MeshTest t; 
  t.Configure (argc, argv);
  return t.Run ();
}
