The demo has only one single file and tested on ns-3.26.
mpudp.cc
#include "ns3/simulator.h"
#include "ns3/log.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/node-list.h"
#include "ns3/socket.h"
#include<map>
#include<vector>
#include<cassert>
NS_LOG_COMPONENT_DEFINE ("MpUdp");
using namespace ns3;
using namespace std;
#define PACKET_SIZE 1000
bool IsExistRoute (Ptr<Node> node,Ipv4Address src, Ipv4Address dst)
{
bool found = false;
uint32_t interface=0;
Ptr<Node> m_node=node;
// Look up the source address
Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
assert (ipv4->GetRoutingProtocol () != 0);
Ipv4Header l3Header;
Socket::SocketErrno errno_;
Ptr<Ipv4Route> route;
interface=ipv4->GetInterfaceForAddress(src); //Pablo UC
Ptr<NetDevice> oif=ipv4->GetNetDevice(interface); //Pablo UC
l3Header.SetSource (src);
l3Header.SetDestination (dst);
route = ipv4->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), l3Header, oif, errno_);
if ((route != 0) && (src == route->GetSource ()))
{
NS_LOG_INFO ("IsThereRoute -> Route from srcAddr "<< src << " to dstAddr " << dst << " oit "<<oif<<", exist !");
found = true;
}else
NS_LOG_INFO ("IsThereRoute -> No Route from srcAddr "<< src << " to dstAddr " << dst << " oit "<<oif<<", exist !");
return found;
}
void GetNodeAddress(Ptr<Node>node,std::vector<Ipv4Address>&addresses)
{
uint32_t interface=0;
uint32_t totalInterface=0;
Ptr<Ipv4> ipv4 =node->GetObject<Ipv4> ();
totalInterface=ipv4->GetNInterfaces();
NS_LOG_INFO("totalinterfaces "<<totalInterface);
for(interface=0;interface<totalInterface;interface++)
{
Ipv4Address srcIp = ipv4->GetAddress (interface, 0).GetLocal ();
if(srcIp==Ipv4Address::GetLoopback()) continue;
addresses.push_back(srcIp);
NS_LOG_INFO("srcIp "<<srcIp);
}
}
struct AddressInfo
{
Ipv4Address srcIp;
Ipv4Address destIp;
uint16_t port;
};
class MpUdpReceiver:public ns3::Application
{
public:
MpUdpReceiver(){}
~MpUdpReceiver(){}
void Bind(uint16_t port)
{
std::vector<Ipv4Address> srcAddresses;
GetNodeAddress(GetNode(),srcAddresses);
for(uint32_t i=0;i<srcAddresses.size();i++)
{
Ptr<Socket> socket=Socket::CreateSocket (GetNode (), UdpSocketFactory::GetTypeId ());
auto local = InetSocketAddress{srcAddresses[i], port};
auto ret=socket->Bind(local);
NS_ASSERT (ret == 0);
socket->SetRecvCallback (MakeCallback (&MpUdpReceiver::RecvPacket,this));
m_sockets.insert(std::make_pair(srcAddresses[i],socket));
}
m_running = false;
}
private:
void StartApplication()
{
m_running=true;
}
void StopApplication()
{
m_running=false;
}
void RecvPacket(Ptr<Socket>socket)
{
Address remoteAddr;
auto packet = socket->RecvFrom (remoteAddr);
auto srcIp = InetSocketAddress::ConvertFrom (remoteAddr).GetIpv4 ();
auto srcPort = InetSocketAddress::ConvertFrom (remoteAddr).GetPort ();
NS_LOG_INFO("recv from src "<<srcIp<<"port "<<srcPort);
}
private:
std::map<Ipv4Address,Ptr<Socket>>m_sockets;
std::vector<AddressInfo>m_addrInfo;
bool m_running{false};
};
class MpUdpSender:public ns3::Application
{
public:
MpUdpSender(){}
~MpUdpSender(){}
void Init()
{
std::vector<Ipv4Address> srcAddresses;
GetNodeAddress(GetNode(),srcAddresses);
for(uint32_t i=0;i<srcAddresses.size();i++)
{
Ptr<Socket> socket=Socket::CreateSocket (GetNode (), UdpSocketFactory::GetTypeId ());
auto local = InetSocketAddress{srcAddresses[i], 0};
auto ret=socket->Bind(local);
NS_ASSERT (ret == 0);
socket->SetRecvCallback (MakeCallback (&MpUdpSender::RecvPacket,this));
m_sockets.insert(std::make_pair(srcAddresses[i],socket));
}
Address addr;
NS_LOG_INFO("print bind port info");
for(auto it=m_sockets.begin();it!=m_sockets.end();it++)
{
Ptr<Socket> socket=it->second;
socket->GetSockName(addr);
InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (addr);
NS_LOG_INFO(iaddr.GetIpv4()<<"port "<<iaddr.GetPort());
}
}
void AddPath(Ipv4Address destIp,uint16_t destPort)
{
for(auto it=m_sockets.begin();it!=m_sockets.end();it++)
{
Ipv4Address srcIp=it->first;
if(IsExistRoute(GetNode(),srcIp,destIp))
{
AddressInfo info{srcIp,destIp,destPort};
m_addrInfo.push_back(info);
}
}
}
void FakePacket()
{
if(m_gennerateTimer.IsExpired())
{
Ptr<Packet> packet=Create<Packet>(PACKET_SIZE);
RoundRobinSchedule(packet);
Time time=MilliSeconds(m_period);
m_gennerateTimer=Simulator::Schedule(time,&MpUdpSender::FakePacket,this);
}
}
private:
void StartApplication()
{
m_running=true;
m_gennerateTimer=Simulator::ScheduleNow(&MpUdpSender::FakePacket,this);
}
void StopApplication()
{
m_running=false;
}
void RecvPacket(Ptr<Socket>socket)
{
//TODO
}
void RoundRobinSchedule(Ptr<Packet> packet)
{
uint32_t i=m_pathIndex;
Ptr<Socket> socket;
Ipv4Address destIp;
uint16_t destPort;
for(i;i<m_addrInfo.size();i++)
{
Ipv4Address srcIp=m_addrInfo[i].srcIp;
auto it=m_sockets.find(srcIp);
if(it!=m_sockets.end())
{
socket=it->second;
destIp=m_addrInfo[i].destIp;
destPort=m_addrInfo[i].port;
break;
}
}
m_pathIndex=(i+1)%m_addrInfo.size();
socket->SendTo(packet,0,InetSocketAddress{destIp,destPort});
}
private:
std::map<Ipv4Address,Ptr<Socket>>m_sockets;
std::vector<AddressInfo>m_addrInfo;
bool m_running{false};
EventId m_gennerateTimer;
uint32_t m_period{10};//in milliseconds
uint8_t m_pathIndex{0};
};
static uint16_t servPort=5000;
static uint16_t queueSize=10;
static uint8_t links=3;
static int64_t startTime=0;
static int64_t stopTime=1000;
static int64_t endTime=2;//2s
int main(int argc, char *argv[])
{
LogComponentEnable("MpUdp", LOG_LEVEL_ALL);
NodeContainer n0n1;
n0n1.Create (2);
InternetStackHelper stack;
stack.Install (n0n1);
vector<Ipv4InterfaceContainer> ipv4Ints;
for(int i=0; i <links; i++)
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(queueSize));
p2plink.SetChannelAttribute("Delay", StringValue("10ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("5Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(n0n1);
// Attribution of the IP addresses
std::stringstream netAddr;
netAddr << "10.1." << (i+1) << ".0";
string str = netAddr.str();
Ipv4AddressHelper ipv4addr;
ipv4addr.SetBase(str.c_str(), "255.255.255.0");
Ipv4InterfaceContainer interface = ipv4addr.Assign(netDevices);
ipv4Ints.insert(ipv4Ints.end(), interface);
}
std::vector<Ipv4Address> destAddresses;
GetNodeAddress(n0n1.Get(1),destAddresses);
uint32_t i=0;
Ptr<MpUdpSender> sendApp = CreateObject<MpUdpSender> ();
Ptr<MpUdpReceiver> recvApp = CreateObject<MpUdpReceiver> ();
n0n1.Get(0)->AddApplication (sendApp);
n0n1.Get(1)->AddApplication (recvApp);
recvApp->Bind(servPort);
sendApp->Init();
/*for(i=0;i<destAddresses.size();i++)
{
sendApp->AddPath(destAddresses[i],servPort);
NS_LOG_INFO(destAddresses[i]);
}
sendApp->SetStartTime (MilliSeconds (startTime));
sendApp->SetStopTime (MilliSeconds (stopTime));
recvApp->SetStartTime (MilliSeconds (startTime));
recvApp->SetStopTime (MilliSeconds (stopTime));
Simulator::Stop (Seconds (endTime));
Simulator::Run ();
Simulator::Destroy ();*/
return 0;
}
And the function void GetNodeAddress(Ptrnode,std::vector&addresses) is used to get the ip address from a node.