ns3 when running 2 bbr flows simulation, got 0 queuesize? - ns-3

I'm using ns-3.34.
I edit the "tcp-bbr-example.cc" to simulate 2 bbr flows situation.
The following codes are what I've changed.
NodeContainer sender, receiver;
NodeContainer routers;
sender.Create (2);
receiver.Create (2);
routers.Create (2);
// Create the point-to-point link helpers
PointToPointHelper bottleneckLink;
bottleneckLink.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
bottleneckLink.SetChannelAttribute ("Delay", StringValue ("10ms"));
PointToPointHelper edgeLink;
edgeLink.SetDeviceAttribute ("DataRate", StringValue ("1000Mbps"));
edgeLink.SetChannelAttribute ("Delay", StringValue ("5ms"));
// Create NetDevice containers
NetDeviceContainer senderEdge = edgeLink.Install (sender.Get (0), routers.Get (0));
NetDeviceContainer senderEdge2 = edgeLink.Install (sender.Get (1), routers.Get (0));
NetDeviceContainer r1r2 = bottleneckLink.Install (routers.Get (0), routers.Get (1));
NetDeviceContainer receiverEdge = edgeLink.Install (routers.Get (1), receiver.Get (0));
NetDeviceContainer receiverEdge2 = edgeLink.Install (routers.Get (1), receiver.Get (1));
...
// Assign IP addresses
Ipv4AddressHelper ipv4;
ipv4.SetBase ("10.0.0.0", "255.255.255.0");
Ipv4InterfaceContainer i1i2 = ipv4.Assign (r1r2);
ipv4.NewNetwork ();
Ipv4InterfaceContainer is1 = ipv4.Assign (senderEdge);
ipv4.NewNetwork ();
Ipv4InterfaceContainer is2 = ipv4.Assign (senderEdge2);
ipv4.NewNetwork ();
Ipv4InterfaceContainer ir1 = ipv4.Assign (receiverEdge);
ipv4.NewNetwork ();
Ipv4InterfaceContainer ir2 = ipv4.Assign (receiverEdge2);
// Populate routing tables
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
// Select sender side port
uint16_t port = 50001;
// Install application on the sender
BulkSendHelper source ("ns3::TcpSocketFactory", InetSocketAddress (ir1.GetAddress (1), port));
BulkSendHelper source2 ("ns3::TcpSocketFactory", InetSocketAddress (ir2.GetAddress (1), port));
source.SetAttribute ("MaxBytes", UintegerValue (0));
source2.SetAttribute ("MaxBytes", UintegerValue (0));
ApplicationContainer sourceApps = source.Install (sender.Get (0));
ApplicationContainer sourceApps2 = source2.Install (sender.Get (1));
sourceApps.Start (Seconds (0.0));
Simulator::Schedule (Seconds (0.2), &TraceCwnd, 0, 0);
sourceApps.Stop (stopTime);
sourceApps2.Start (Seconds (0.0));
Simulator::Schedule (Seconds (0.2), &TraceCwnd2, 0, 0);
sourceApps2.Stop (stopTime);
// Install application on the receiver
PacketSinkHelper sink ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port));
ApplicationContainer sinkApps = sink.Install (receiver.Get (0));
ApplicationContainer sinkApps2 = sink.Install (receiver.Get (1));
sinkApps.Start (Seconds (0.0));
sinkApps.Stop (stopTime);
sinkApps2.Start (Seconds (0.0));
sinkApps2.Stop (stopTime);
And the result queuesize figure like:
I don't know what's wrong...fully no idea...
Somebody told me maybe check the function related to queue, but I still don't understand and I don't know where the fuction is.

Related

when i want to simulate a adhoc scene,which use 802.11a wifiphy ,i usually get an error

assert failed. cond="m_wifiPhy->m_currentEvent == 0", +23.801712798s 11 file=../src/wifi/model/phy-entity.cc, line=467
terminate called without an active exception
here is my code.I am a freshman in ns3,but i need get my simulation run correctly Eagerly.These days i am really exhausted to find the problem,and sttle it.So I really need someone to help me.
#include <fstream>
#include <iostream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/aodv-module.h"
#include "ns3/olsr-module.h"
#include "ns3/dsdv-module.h"
#include "ns3/dsr-module.h"
#include "ns3/applications-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/animation-interface.h"
using namespace std;
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("constant-position-experiment");
void ReceivePacket (Ptr<Socket> socket)
{
NS_LOG_INFO ("Received one packet!");
Ptr<Packet> packet = socket->Recv ();
SocketIpTosTag tosTag;
NS_LOG_UNCOND (" received a packet!");
if (packet->RemovePacketTag (tosTag))
{
//NS_LOG_UNCOND (" TOS = " << (uint32_t)tosTag.GetTos ());
}
SocketIpTtlTag ttlTag;
if (packet->RemovePacketTag (ttlTag))
{
//NS_LOG_UNCOND (" TTL = " << (uint32_t)ttlTag.GetTtl ());
}
}
static void SendPacket (Ptr<Socket> socket, uint32_t pktSize,
uint128_t pktCount, Time pktInterval ,uint128_t counta)
{
if (pktCount > 0)
{
counta+=1;
socket->Send (Create<Packet> (pktSize));
Simulator::Schedule (pktInterval, &SendPacket,
socket, pktSize,pktCount - 1, pktInterval,counta);
NS_LOG_UNCOND (" send a packet!"<<(uint32_t)counta<<Simulator::Now());
}
else
{
socket->Close ();
}
}
int main(int argc,char*argv[])
{
int n=30;
double totaltime=4000000;
double settime=60;
double distance=35000;
string phyMode ("OfdmRate2_25MbpsBW5MHz");
string dataRate ("300kb/s");
uint64_t packetSize=512;
uint128_t packetCount =6530;
double packetInterval=0.05;
uint128_t counta(0);
uint32_t ipTos = 0;
bool ipRecvTos = true;
uint32_t ipTtl = 0;
bool ipRecvTtl = true;
//OfdmRate1_5MbpsBW5MHz
// OfdmRate2_25MbpsBW5MHz
// OfdmRate3MbpsBW5MHz
// OfdmRate4_5MbpsBW5MHz
// OfdmRate6MbpsBW5MHz
// OfdmRate9MbpsBW5MHz
// OfdmRate12MbpsBW5MHz
// OfdmRate13_5MbpsBW5MHz
// OfdmRate3MbpsBW10MHz
// OfdmRate4_5MbpsBW10MHz
// OfdmRate6MbpsBW10MHz
// OfdmRate9MbpsBW10MHz
// OfdmRate12MbpsBW10MHz
// OfdmRate18MbpsBW10MHz
// OfdmRate24MbpsBW10MHz
// OfdmRate27MbpsBW10MHz
// OfdmRate6Mbps
// OfdmRate9Mbps
// OfdmRate12Mbps
// OfdmRate18Mbps
// OfdmRate24Mbps
// OfdmRate36Mbps
// OfdmRate48Mbps
// OfdmRate54Mbps
CommandLine cmd (__FILE__);
cmd.AddValue ("distance", "the distance bettween nodes", distance);
cmd.AddValue ("settime", "olsr settime", settime);
cmd.AddValue ("phyMode", "olsr settime", phyMode);
cmd.AddValue ("dataRate", "olsr settime", dataRate);
cmd.Parse (argc, argv);
// LogComponentEnable("OnOffApplication",LOG_LEVEL_INFO);
NodeContainer c;
c.Create(n);
NodeContainer n0n23=NodeContainer(c.Get(0),c.Get(23));
NS_LOG_UNCOND ("distance:"<<distance<<"phymode: "<<phyMode<<"dataRate: "+dataRate);
//wifpyh wifchannel
WifiHelper wifi;
wifi.SetStandard (WIFI_STANDARD_80211a);
WifiMacHelper wifiMac;
YansWifiPhyHelper wifiPhy;
YansWifiChannelHelper wifiChannel;
wifiPhy.Set("TxGain",DoubleValue(4.5));
wifiPhy.Set("RxGain",DoubleValue(4.5));
//
wifiPhy.Set("RxSensitivity",DoubleValue(-90));
wifiPhy.Set("Antennas",UintegerValue(2));
wifiPhy.Set ("TxPowerStart",DoubleValue (37));
wifiPhy.Set ("TxPowerEnd", DoubleValue (37));
wifiPhy.Set ("RxNoiseFigure",DoubleValue (0));
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel","Frequency",DoubleValue(1.2e+09));
wifiPhy.SetChannel (wifiChannel.Create ());
wifiMac.SetType ("ns3::AdhocWifiMac");
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue (phyMode),
"ControlMode",StringValue (phyMode));
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
//mobility
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (distance),
"DeltaY", DoubleValue (distance),
"GridWidth", UintegerValue (5),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
"Bounds", RectangleValue (Rectangle (-200000, 200000, -200000, 200000)),
"Speed", StringValue ("ns3::ConstantRandomVariable[Constant=39]"),
"Pause", StringValue ("ns3::ConstantRandomVariable[Constant=2]"));
mobility.Install (c);
//internet
OlsrHelper olsr;
Ipv4ListRoutingHelper list;
list.Add (olsr, 10);
InternetStackHelper internet;
internet.SetRoutingHelper (list); // has effect on the next Install ()
internet.Install (c);
Ipv4AddressHelper addressAdhoc;
addressAdhoc.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces;
interfaces = addressAdhoc.Assign (devices);
//application
NS_LOG_INFO ("Create sockets.");
//Receiver socket on n1
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
Ptr<Socket> recvSink = Socket::CreateSocket (c.Get (1), tid);
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 4477);
recvSink->SetIpRecvTos (ipRecvTos);
recvSink->SetIpRecvTtl (ipRecvTtl);
recvSink->Bind (local);
recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));
//Sender socket on n0
Ptr<Socket> source = Socket::CreateSocket (c.Get (27), tid);
InetSocketAddress remote = InetSocketAddress (interfaces.GetAddress (1), 4477);
//Set socket options, it is also possible to set the options after the socket has been created/connected.
if (ipTos > 0)
{
source->SetIpTos (ipTos);
}
if (ipTtl > 0)
{
source->SetIpTtl (ipTtl);
}
source->Connect (remote);
//flowmonitor
string s1=phyMode.substr(8,3);
string s2=phyMode.substr(phyMode.length()-4,4);
string s3=dataRate.substr(0,dataRate.length()-2);
string filename=to_string(int(distance/1000))+"_"+s1+"_"+s2+"_"+s3;
Ptr<FlowMonitor> flowmon;
FlowMonitorHelper flowmonHelper;
flowmon = flowmonHelper.InstallAll ();
Ptr<OutputStreamWrapper> routingStream=Create<OutputStreamWrapper>(filename+"routes.tr",std::ios::out);
olsr.PrintRoutingTableAt(Seconds(40.0),c.Get(2),routingStream);
AnimationInterface anim ((filename+".xml"));
anim.SetMaxPktsPerTraceFile(99999999999999);
Time interPacketInterval = Seconds (packetInterval);
Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
Seconds (1.0), &SendPacket,
source, packetSize, packetCount, interPacketInterval,counta);
Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
Seconds (70.0), &SendPacket,
source, packetSize, packetCount, interPacketInterval,counta);
Simulator::ScheduleWithContext (source->GetNode ()->GetId (),
Seconds (30.0), &SendPacket,
source, packetSize, packetCount, interPacketInterval,counta);
Simulator::Stop (Seconds (totaltime));
Simulator::Run ();
Simulator::Destroy ();
flowmon->SerializeToXmlFile (filename+".flowmon", false, false);
// numPackets=0;
return 0;
}
why this problem occur ?
How to settle it?

how do I connect an ethernet module to a gps module using arduino

First, I apologize for my mediocre English, hello I'm doing a project for college where I need to use a GY-GPS6MV2 gps module and using this module I need to use an enc28j60 ethernet module to save the gps data on a web page and later use a api. I was using the code below but I didn't get any data. Initially I used only the code related to the ethernet module so that later I could add the gps code.
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <UIPEthernet.h>
EthernetServer server = EthernetServer(80);
SoftwareSerial serial1(6, 7); // RX, TX
TinyGPS gps1;
void setup() {
serial1.begin(9600);
Serial.begin(9600);
uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
IPAddress myIP(192, 168, 0, 200);
Ethernet.begin(mac, myIP);
server.begin();
Serial.println("GPS Animal Tracker...");
}
void loop() {
bool recebido = false;
while (serial1.available()) {
char cIn = serial1.read();
recebido = gps1.encode(cIn);
}
if (recebido) {
Serial.println("----------------------------------------");
long latitude, longitude;
unsigned long idadeInfo;
gps1.get_position(&latitude, &longitude, &idadeInfo);
if (latitude != TinyGPS::GPS_INVALID_F_ANGLE) {
Serial.print("Latitude: ");
Serial.println(float(latitude) / 100000, 6);
}
if (longitude != TinyGPS::GPS_INVALID_F_ANGLE) {
Serial.print("Longitude: ");
Serial.println(float(longitude) / 100000, 6);
}
if (idadeInfo != TinyGPS::GPS_INVALID_AGE) {
Serial.print("Idade da Informacao (ms): ");
Serial.println(idadeInfo);
}
int ano;
byte mes, dia, hora, minuto, segundo, centesimo;
gps1.crack_datetime(&ano, &mes, &dia, &hora, &minuto, &segundo, &idadeInfo);
Serial.print("Data (GMT): ");
Serial.print(dia);
Serial.print("/");
Serial.print(mes);
Serial.print("/");
Serial.println(ano);
Serial.print("Horario (GMT): ");
Serial.print(hora);
Serial.print(":");
Serial.print(minuto);
Serial.print(":");
size_t size;
if (EthernetClient client = server.available())
{
while ((size = client.available()) > 0)
{
uint8_t* msg = (uint8_t*)malloc(size);
size = client.read(msg, size);
Serial.write(msg, size);
free(msg);
}
client.println("<h1>ModuloEletronica</h1>");
client.print("<h1>Latitude</h1>");
//client.print((float(latitude) / 100000, 6));
client.println();
client.print ("<h1>Longitude</h1>");
//client.print ((float(longitude) / 100000, 6));
client.println();
client.stop();
}
Serial.print(segundo);
}

How to get the received time of each packet in NS-3? (802.11n+MIMO example)

I am using this example : https://github.com/nsnam/ns-3-dev-git/blob/master/examples/wireless/80211n-mimo.cc
and i want to get the received time of packets to be plotted. I tried to use Simulator::Now().GetSeconds(); but it shows the same value every time (6s)
I ask if there's any other way to solve this please.
/* Setting applications */
ApplicationContainer serverApp;
if (udp)
{
//UDP flow
uint16_t port = 9;
UdpServerHelper server (port);
serverApp = server.Install (wifiStaNode.Get (0));
serverApp.Start (Seconds (0.0));
serverApp.Stop (Seconds (simulationTime + 1));
UdpClientHelper client (staNodeInterface.GetAddress (0), port);
client.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
client.SetAttribute ("Interval", TimeValue (Time ("0.00001"))); //packets/s
client.SetAttribute ("PacketSize", UintegerValue (payloadSize));
ApplicationContainer clientApp = client.Install (wifiApNode.Get (0));
clientApp.Start (Seconds (1.0));
clientApp.Stop (Seconds (simulationTime + 1));
}
else
{
//TCP flow
uint16_t port = 50000;
Address localAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", localAddress);
serverApp = packetSinkHelper.Install (wifiStaNode.Get (0));
serverApp.Start (Seconds (0.0));
serverApp.Stop (Seconds (simulationTime + 1));
OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ());
onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
onoff.SetAttribute ("DataRate", DataRateValue (1000000000)); //bit/s
AddressValue remoteAddress (InetSocketAddress (staNodeInterface.GetAddress (0), port));
onoff.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp = onoff.Install (wifiApNode.Get (0));
clientApp.Start (Seconds (1.0));
clientApp.Stop (Seconds (simulationTime + 1));
}
Simulator::Stop (Seconds (simulationTime + 1));
Simulator::Run ();
double throughput = 0;
**double received = Simulator::Now().GetSeconds();**
if (udp)
{
//UDP
uint64_t totalPacketsThrough = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); //Mbit/s
}
else
{
//TCP
uint64_t totalPacketsThrough = DynamicCast<PacketSink> (serverApp.Get (0))->GetTotalRx ();
throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); //Mbit/s
}
dataset.Add (d, throughput);
std::cout << throughput << " Mbit/s" << std::endl;
**std::cout << "received After :" << received << " s" << std::endl;**
d += step;
Simulator::Destroy ();
}
plot.AddDataset (dataset);
}
I tried to use "Simulator::Now().GetSeconds();" but it shows the same value every time(6s).
The same value is returned by Simulator::Now().GetSeconds() because it is being called after the simulation is complete. It has to be invoked during the actual simulation. One way would be to actually dig around the huge library of code (TCP/UDP modules under 'src/internet/', in this case) and figure out which function actually deals with the reception of the packet. But to make life easier, ns-3 has already implemented tracing to handle this.
To answer your specific question, you will require a packet sink trace.
Consider the code where you are installing the packet sink inside your main() function:
ApplicationContainer TcpSinkApps = TcpPacketSink.Install (nodeContainer.Get(0));
Ptr<PacketSink> pktSink = StaticCast<PacketSink> (TcpSinkApps.Get(0));
std::stringstream ss; ss << "Some information";
pktSink->TraceConnect("Rx", ss.str(), MakeCallback (&SinkRxTrace));
The "Rx" trace is defined in packet-sink.cc, such that SinkRxTrace() is a function that is called every time a packet is received successfully. Now you can go ahead and define the SinkRxTrace() in your code (above main() of course):
void SinkRxTrace(std::string context, Ptr<const Packet> pkt, const Address &addr)
{
std::cout<<"Packet received at "<<Simulator::Now().GetSeconds()<<" s\n";
}

How to get the number of lost packets using TCP in NS-3 ? (80211n + MIMO example)

I am using this example : https://github.com/nsnam/ns-3-dev-git/blob/master/examples/wireless/80211n-mimo.cc .
For UDP, there's a function called "GetLost()" in UdpServer that returns the number of lost packets but for TCP there's not. I ask if there's any solution to solve this please. Thanks
/* Setting applications */
ApplicationContainer serverApp;
if (udp)
{
//UDP flow
uint16_t port = 9;
UdpServerHelper server (port);
serverApp = server.Install (wifiStaNode.Get (0));
serverApp.Start (Seconds (0.0));
serverApp.Stop (Seconds (simulationTime + 1));
UdpClientHelper client (staNodeInterface.GetAddress (0), port);
client.SetAttribute ("MaxPackets", UintegerValue (4294967295u));
client.SetAttribute ("Interval", TimeValue (Time ("0.00001"))); //packets/s
client.SetAttribute ("PacketSize", UintegerValue (payloadSize));
ApplicationContainer clientApp = client.Install (wifiApNode.Get (0));
clientApp.Start (Seconds (1.0));
clientApp.Stop (Seconds (simulationTime + 1));
}
else
{
//TCP flow
uint16_t port = 50000;
Address localAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", localAddress);
serverApp = packetSinkHelper.Install (wifiStaNode.Get (0));
serverApp.Start (Seconds (0.0));
serverApp.Stop (Seconds (simulationTime + 1));
OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ());
onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize));
onoff.SetAttribute ("DataRate", DataRateValue (1000000000)); //bit/s
AddressValue remoteAddress (InetSocketAddress (staNodeInterface.GetAddress (0), port));
onoff.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp = onoff.Install (wifiApNode.Get (0));
clientApp.Start (Seconds (1.0));
clientApp.Stop (Seconds (simulationTime + 1));
}
Simulator::Stop (Seconds (simulationTime + 1));
Simulator::Run ();
uint64_t nb = 0;
uint64_t lost = 0;
if (udp)
{
//UDP
nb = DynamicCast<UdpServer> (serverApp.Get (0))->GetReceived ();
lost = DynamicCast<UdpServer> (serverApp.Get (0))->GetLost();
double window = DynamicCast<UdpServer> (serverApp.Get (0))->GetPacketWindowSize();
std::cout << "Window Size :" << window << std::endl;
}
else
{
//TCP
uint64_t totalPacketsThrough = DynamicCast<PacketSink> (serverApp.Get (0))->GetTotalRx ();
nb = totalPacketsThrough / payloadSize ;
/*need help here to get the number of lost packets using TCP Thanks*/
}
dataset1.Add (d, nb);
dataset2.Add (d, lost);
std::cout << nb << " Received packets" << std::endl;
std::cout << lost << " Lost packets" << std::endl;
d += step;
Simulator::Destroy ();
}
plot1.AddDataset (dataset1);
plot2.AddDataset (dataset2);
}
Use the "Tx" trace for the OnOffApplication to call a function every time a packet is transmitted -
void SourceUdpTrace(Ptr<const Packet> pkt)
{
nPacketsSent++;
}
Inside main(), use the following Config::Connect statement to set up the trace and link it with SourceUdpTrace. This statement has to be placed before Simulator::Run()
Config::ConnectWithoutContext("/NodeList/*/ApplicationList/*/$ns3::ManualOnOffApp/Tx",MakeCallback(&SourceUdpTrace));
Once you know the number of sent packets, you can easily determine the number of lost packets by comparing it the value of nb, as found by your line of code - nb = totalPacketsThrough / payloadSize;

How do I change the TCP payload in NS3?

I am new to ns3 and I am implementing a code to test out how different MTUs impact the throughput. However the payload seems to be capped at 536 bytes which makes all my MTUs have similar timings. How do I go about changing it?
I have tried editing the variable writesize equal to the MTU but the payload limits what I try to achieve.
My code:
#include <iostream>
#include <fstream>
#include <string>
#include "ns3/netanim-module.h"
#include "ns3/core-module.h"
#include "ns3/applications-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ipv4-global-routing-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TCPtest");
// The number of bytes to send in this simulation.
static const uint32_t totalTxBytes = 30000000;
static uint32_t currentTxBytes = 0;
// Perform series of 1040 byte writes (this is a multiple of 26 since
// we want to detect data splicing in the output stream)
static const uint32_t writeSize = 9000;
uint8_t data[writeSize];
// These are for starting the writing process, and handling the sending
// socket's notification upcalls (events). These two together more or less
// implement a sending "Application", although not a proper ns3::Application
// subclass.
void StartFlow (Ptr<Socket>, Ipv4Address, uint16_t);
void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
static void
CwndTracer (uint32_t oldval, uint32_t newval)
{
NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
}
int
main (int argc, char *argv[])
{
Time::SetResolution (Time::NS);
// initialize the tx buffer.
for(uint32_t i = 0; i < writeSize; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
NodeContainer nodes;
nodes.Create (6);
StringValue Mtu;
Mtu.Set("9000");
InternetStackHelper stack;
stack.Install (nodes);
PointToPointHelper p2p1;
p2p1.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
p2p1.SetChannelAttribute ("Delay", StringValue ("5ms"));
p2p1.SetDeviceAttribute ("Mtu", Mtu);
PointToPointHelper p2p2;
p2p2.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
p2p2.SetChannelAttribute ("Delay", StringValue ("300ms"));
p2p2.SetDeviceAttribute ("Mtu", StringValue ("9000"));
PointToPointHelper p2p3;
p2p3.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
p2p3.SetChannelAttribute ("Delay", StringValue ("5ms"));
p2p3.SetDeviceAttribute ("Mtu", StringValue ("9000"));
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
NetDeviceContainer devices;
devices = p2p1.Install (nodes.Get (0), nodes.Get (1));
Ipv4InterfaceContainer interfaces = address.Assign (devices);
address.SetBase ("10.1.4.0", "255.255.255.0");
devices = p2p1.Install (nodes.Get (4), nodes.Get (1));
interfaces = address.Assign (devices);
devices = p2p2.Install (nodes.Get (1), nodes.Get (2));
address.SetBase ("10.1.2.0", "255.255.255.0");
interfaces = address.Assign (devices);
devices = p2p3.Install (nodes.Get (2), nodes.Get (3));
address.SetBase ("10.1.3.0", "255.255.255.0");
interfaces = address.Assign (devices);
devices = p2p3.Install (nodes.Get (2), nodes.Get (5));
address.SetBase ("10.1.5.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces2 = address.Assign (devices);
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
uint16_t port = 9;
// Create a packet sink to receive these packets on n1...
PacketSinkHelper sink ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), port));
ApplicationContainer apps = sink.Install (nodes.Get (3));
apps.Start (Seconds (0.0));
apps.Stop (Seconds (10.0));
PacketSinkHelper sink2 ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), port));
ApplicationContainer apps2 = sink2.Install (nodes.Get (5));
apps2.Start (Seconds (0.0));
apps2.Stop (Seconds (10.0));
// Create and bind the socket...
Ptr<Socket> localSocket =
Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
localSocket->Bind ();
Ptr<Socket> localSocket2 =
Socket::CreateSocket (nodes.Get (4), TcpSocketFactory::GetTypeId ());
localSocket2->Bind ();
// Trace changes to the congestion window
Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
// ...and schedule the sending "Application"; This is similar to what an
// ns3::Application subclass would do internally.
Simulator::ScheduleNow (&StartFlow, localSocket, interfaces.GetAddress (1), port);
Simulator::ScheduleNow (&StartFlow, localSocket2, interfaces2.GetAddress (1), port);
// One can toggle the comment for the following line on or off to see the
// effects of finite send buffer modelling. One can also change the size of
// said buffer.
//localSocket->SetAttribute("SndBufSize", UintegerValue(4096));
//Ask for ASCII and pcap traces of network traffic
AsciiTraceHelper ascii;
p2p3.EnableAsciiAll (ascii.CreateFileStream ("tcp-test1.tr"));
p2p3.EnablePcapAll ("tcp-test1");
AnimationInterface anim ("tcptest.xml");
anim.SetConstantPosition (nodes.Get (0), 0.0, 0.0);
anim.SetConstantPosition (nodes.Get (1), 20.0, 25.0);
anim.SetConstantPosition (nodes.Get (2), 35.0, 40.0);
anim.SetConstantPosition (nodes.Get (3), 50.0, 55.0);
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
void StartFlow (Ptr<Socket> localSocket,
Ipv4Address servAddress,
uint16_t servPort)
{
NS_LOG_LOGIC ("Starting flow at time " << Simulator::Now ().GetSeconds ());
localSocket->Connect (InetSocketAddress (servAddress, servPort)); //connect
// tell the tcp implementation to call WriteUntilBufferFull again
// if we blocked and new tx buffer space becomes available
localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ());
}
void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
{
while (currentTxBytes < totalTxBytes && localSocket->GetTxAvailable () > 0)
{
uint32_t left = totalTxBytes - currentTxBytes;
uint32_t dataOffset = currentTxBytes % writeSize;
uint32_t toWrite = writeSize - dataOffset;
toWrite = std::min (toWrite, left);
toWrite = std::min (toWrite, localSocket->GetTxAvailable ());
int amountSent = localSocket->Send (&data[dataOffset], toWrite, 0);
if(amountSent < 0)
{
// we will be called again when new tx space becomes available.
return;
}
currentTxBytes += amountSent;
}
localSocket->Close ();
}