The version of ns3 I use is 3.37. I changed some code of the demo provided by ns3 and try to build a simple network with three nodes. The test process is as follows: node0 send one packet to node1, after node1 received, node1 send one packet to node2. If node0 send packet once, the process will be normal. But if node0 send packet twice, the node1 can only receive packet once! The code is as follows:
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
#include <ctime>
#include <set>
#include <cmath>
#include <unordered_set>
#include <random>
#include <ns3/applications-module.h>
#include <ns3/assert.h>
#include <ns3/packet.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>
using namespace ns3;
std::string LinkRate("10Mbps"); // link rate
std::string LinkDelay("2ms"); // link delay
const double SimTime = 3.00;
const double AppStartTime = 2.0001;
const double AppStopTime = 2.80001;
// ===========================================================================
//
// node 0 node 1 node 2
// +----------------+ +----------------+ +----------------+
// | ns-3 TCP | | ns-3 TCP | | ns-3 TCP |
// +----------------+ +----------------+ +----------------+
// | point-to-point | | point-to-point | | point-to-point |
// +----------------+ +----------------+ +----------------+
// | | |
// +---------------------+---------------------+
// 5 Mbps, 2 ms 5 Mbps, 2 ms
//
//
class SimpleApplication : public Application
{
public:
SimpleApplication() : m_socket(nullptr), m_peer() {}
~SimpleApplication() override { m_socket = nullptr; }
static TypeId GetTypeId()
{
static TypeId tid = TypeId("SimpleApp")
.SetParent<Application>()
.SetGroupName("Simple")
.AddConstructor<SimpleApplication>();
return tid;
}
void Setup(Ptr<Socket> socket, Address address, int id)
{
m_id = id;
m_socket = socket;
m_peer = address;
}
private:
void StartApplication() override
{
m_socket->Bind();
m_socket->SetRecvCallback(MakeCallback(&SimpleApplication::recv_packet, this));
if (m_id == 0)
{
SendPacket();
SendPacket(); // send twice
}
}
void recv_packet()
{
std::cout << "node " << m_id << " recv packet" << std::endl;
if (m_id == 1)
{
SendPacket();
}
}
void StopApplication() override
{
if (m_socket)
{
m_socket->Close();
}
}
void SendPacket()
{
Ptr<Packet> packet = Create<Packet>(1024);
m_socket->Connect(m_peer);
m_socket->Send(packet);
}
private:
int m_id;
Ptr<Socket> m_socket; //!< The tranmission socket.
Address m_peer;
};
int main(int argc, char const *argv[])
{
/* code */
NodeContainer nodes;
nodes.Create(3);
PointToPointHelper p2p;
p2p.SetDeviceAttribute("DataRate", StringValue(LinkRate));
p2p.SetChannelAttribute("Delay", StringValue(LinkDelay));
InternetStackHelper internet;
internet.Install(NodeContainer::GetGlobal());
Ipv4AddressHelper ipv4_n;
ipv4_n.SetBase("10.0.0.0", "255.255.255.252");
{
NodeContainer n_links = NodeContainer(nodes.Get(0), nodes.Get(1));
NetDeviceContainer n_devs = p2p.Install(n_links);
ipv4_n.Assign(n_devs);
ipv4_n.NewNetwork();
}
{
NodeContainer n_links = NodeContainer(nodes.Get(1), nodes.Get(2));
NetDeviceContainer n_devs = p2p.Install(n_links);
ipv4_n.Assign(n_devs);
ipv4_n.NewNetwork();
}
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
// node0 send packet to node1, then node1 send packet to node2
for (int i = 0; i < 3; i++)
{
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket(nodes.Get(i), SocketFactory::GetTypeId());
Ptr<Node> n = nodes.Get((i + 1) % 3);
Ptr<Ipv4> ipv4 = n->GetObject<Ipv4>();
Ipv4InterfaceAddress ipv4_int_addr = ipv4->GetAddress(1, 0);
Ipv4Address ip_addr = ipv4_int_addr.GetLocal();
Address address(InetSocketAddress(ip_addr, 8080));
Ptr<SimpleApplication> app = CreateObject<SimpleApplication>();
app->Setup(ns3TcpSocket, address, i);
nodes.Get(i)->AddApplication(app);
app->SetStartTime(Seconds(AppStartTime));
app->SetStopTime(Seconds(AppStopTime));
}
std::string tr_name = "n-node-ppp.tr";
AsciiTraceHelper ascii;
p2p.EnableAsciiAll(ascii.CreateFileStream(tr_name));
Simulator::Stop(Seconds(SimTime));
Simulator::Run();
Simulator::Destroy();
return 0;
}
The simplified trace file is as follows:
+ 2.0001 /NodeList/0/DeviceList/1/$ns3::PointToPointNetDevice/TxQueue/Enqueue
- 2.0001 /NodeList/0/DeviceList/1/$ns3::PointToPointNetDevice/TxQueue/Dequeue
r 2.00294 /NodeList/1/DeviceList/1/$ns3::PointToPointNetDevice/MacRx ns3::PppHeader
+ 2.00294 /NodeList/1/DeviceList/2/$ns3::PointToPointNetDevice/TxQueue/Enqueue
- 2.00294 /NodeList/1/DeviceList/2/$ns3::PointToPointNetDevice/TxQueue/Dequeue
r 2.00577 /NodeList/2/DeviceList/1/$ns3::PointToPointNetDevice/MacRx ns3::PppHeader
+ 2.00829 /NodeList/0/DeviceList/1/$ns3::PointToPointNetDevice/TxQueue/Enqueue ns3::PppHeader
- 2.00829 /NodeList/0/DeviceList/1/$ns3::PointToPointNetDevice/TxQueue/Dequeue ns3::PppHeader
r 2.01113 /NodeList/1/DeviceList/1/$ns3::PointToPointNetDevice/MacRx
The trace file shows that the net device of node1 has received the second packet, but this packet doesn't be pushed to the queue, so the application can't receive the second packet. I don't know how to solve this problem.
I except when node0 send packet to node1 twice, node1 can receive both of them.