I created a ring topology for multi-interface purpose similar the ns3 example SocketBoundTcpRoutingExample. The topolgy in SocketBoundTcpRoutingExample is the following:
/* Test program for multi-interface host, static routing
Destination host (10.20.1.2)
|
| 10.20.1.0/24
DSTRTR
10.10.1.0/24 / \ 10.10.2.0/24
/ \
Rtr1 Rtr2
10.1.1.0/24 | | 10.1.2.0/24
| /
\ /
Source
*/
But I just add two routers in my topology:
/* Ring Network Topology
10.1.1.0 n1--10.1.2.0--n2 10.1.3.0
n0/ \n5
\10.1.4.0 n3--10.1.5.0--n4 / 10.1.6.0
*/
But it just did not work. The server can receive syn packet but the client seems can not get the syn+ack packet. So the three handshakes failed. Finally, I found the interface parameter in function(AddHostRouteTo (Ipv4Address (“10.1.1.1”), Ipv4Address (“10.1.2.1”), 2)) is the reason for this misbehavior. I change it to number 1, and it works. This parameter is the index for multi-interface of node. I put up my codes that works in here for record purpose.
ringtopology.cc
#include <ctype.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#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"
/* Ring Network Topology
10.1.1.0 n1--10.1.2.0--n2 10.1.3.0
n0/ \n5
\10.1.4.0 n3--10.1.5.0--n4 / 10.1.6.0
*/
using namespace ns3;
using namespace std;
NS_LOG_COMPONENT_DEFINE("FirstRingTopology");
// The number of bytes to send in this simulation.
static const uint32_t totalTxBytes = 150000000;
//static const uint32_t totalTxBytes = 100;
static const uint32_t sendBufSize = 14000; //2000000;
static const uint32_t recvBufSize = 15000; //2000000;
static uint32_t currentTxBytes = 0;
static const double simDuration = 30.0;
Ptr<Node> client;
Ptr<Node> server;
static const uint32_t writeSize = 1500;
uint8_t data[writeSize];
void StartFlow (Ptr<Socket>, Ipv4Address, uint16_t);
void WriteUntilBufferFull (Ptr<Socket>, unsigned int);
void connectionSucceeded(Ptr<Socket>);
void connectionFailed(Ptr<Socket>);
void HandlePeerClose (Ptr<Socket>);
void HandlePeerError (Ptr<Socket>);
void CloseConnection (Ptr<Socket>);
int connect(Address &addr);
static void
CwndTracer (double oldval, double newval)
{
NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
}
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;
}
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
uint32_t queueSize=100;
uint32_t bottleQueueSize=5;
LogComponentEnable("FirstRingTopology", LOG_LEVEL_ALL);
LogComponentEnable("TcpSocketBase", LOG_LEVEL_ALL);
// initialize the tx buffer.
for(uint32_t i = 0; i < writeSize; ++i)
{
char m = toascii (97 + i % 26);
data[i] = m;
}
// Creation of the hosts
NodeContainer nodes;
nodes.Create(6);
client = nodes.Get(0);
server = nodes.Get(5);
InternetStackHelper spstack;
spstack.SetTcp("ns3::TcpL4Protocol");
spstack.Install(nodes);
vector<Ipv4InterfaceContainer> ipv4Ints;
//link n0-n1 0
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(queueSize));
p2plink.SetChannelAttribute("Delay", StringValue("30ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("2Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(0),nodes.Get(1));
std::stringstream netAddr;
netAddr << "10.1." <<"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);
}
//link n1-n2 1
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(bottleQueueSize));
p2plink.SetChannelAttribute("Delay", StringValue("50ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("1Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(1),nodes.Get(2));
std::stringstream netAddr;
netAddr << "10.1." <<"2"<< ".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);
}
//link n2-n5 2
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(queueSize));
p2plink.SetChannelAttribute("Delay", StringValue("20ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("2Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(2),nodes.Get(5));
std::stringstream netAddr;
netAddr << "10.1." <<"3"<< ".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);
}
//link n0-n3 3
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(queueSize));
p2plink.SetChannelAttribute("Delay", StringValue("50ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("3Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(0),nodes.Get(3));
std::stringstream netAddr;
netAddr << "10.1." <<"4"<< ".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);
}
//link n3-n4 4
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(bottleQueueSize));
p2plink.SetChannelAttribute("Delay", StringValue("100ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("1Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(3),nodes.Get(4));
std::stringstream netAddr;
netAddr << "10.1." <<"5"<< ".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);
}
//link n4-n5 5
{
PointToPointHelper p2plink;
p2plink.SetQueue ("ns3::DropTailQueue", "MaxPackets",UintegerValue(bottleQueueSize));
p2plink.SetChannelAttribute("Delay", StringValue("50ms"));
p2plink.SetDeviceAttribute ("DataRate", StringValue("3Mbps"));
NetDeviceContainer netDevices;
netDevices = p2plink.Install(nodes.Get(4),nodes.Get(5));
std::stringstream netAddr;
netAddr << "10.1." <<"6"<< ".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);
}
Ptr<Ipv4> ipv4n0 = nodes.Get(0)->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4n1 = nodes.Get(1)->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4n2 = nodes.Get(2)->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4n5 = nodes.Get(5)->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4n3 = nodes.Get(3)->GetObject<Ipv4> ();
Ptr<Ipv4> ipv4n4 = nodes.Get(4)->GetObject<Ipv4> ();
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr<Ipv4StaticRouting> staticRoutingn0 = ipv4RoutingHelper.GetStaticRouting (ipv4n0);
Ptr<Ipv4StaticRouting> staticRoutingn1 = ipv4RoutingHelper.GetStaticRouting (ipv4n1);
Ptr<Ipv4StaticRouting> staticRoutingn2 = ipv4RoutingHelper.GetStaticRouting (ipv4n2);
Ptr<Ipv4StaticRouting> staticRoutingn5 = ipv4RoutingHelper.GetStaticRouting (ipv4n5);
Ptr<Ipv4StaticRouting> staticRoutingn3 = ipv4RoutingHelper.GetStaticRouting (ipv4n3);
Ptr<Ipv4StaticRouting> staticRoutingn4 = ipv4RoutingHelper.GetStaticRouting (ipv4n4);
//n1->n5
staticRoutingn1->AddHostRouteTo (Ipv4Address ("10.1.3.2"), Ipv4Address ("10.1.2.2"), 2);
//n0->n5
staticRoutingn0->AddHostRouteTo (Ipv4Address ("10.1.3.2"), Ipv4Address ("10.1.1.2"),1, 5);
//n3->n5
staticRoutingn3->AddHostRouteTo (Ipv4Address ("10.1.6.2"), Ipv4Address ("10.1.5.2"), 2);
//n0->n5
staticRoutingn0->AddHostRouteTo (Ipv4Address ("10.1.6.2"), Ipv4Address ("10.1.4.2"), 2,10);
//n2->n0
staticRoutingn2->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.2.1"), 1);
//fuck this metrics,cost me nearly four hours!fuck!
//n5->n0
staticRoutingn5->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.3.1"),1, 5);
//n1->n0
//staticRoutingn1->AddHostRouteTo(Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.1.1"), 1);
//n4->n0
staticRoutingn4->AddHostRouteTo (Ipv4Address ("10.1.4.1"), Ipv4Address ("10.1.5.1"), 1);
//n5->n0
staticRoutingn5->AddHostRouteTo (Ipv4Address ("10.1.4.1"), Ipv4Address ("10.1.6.1"), 2,10);
NS_LOG_INFO("is exist route"<<IsExistRoute(nodes.Get(0),Ipv4Address ("10.1.1.1"),Ipv4Address ("10.1.3.2")));
NS_LOG_INFO("is exist route"<<IsExistRoute(nodes.Get(0),Ipv4Address ("10.1.4.1"),Ipv4Address ("10.1.6.2")));
NS_LOG_INFO("is exist route"<<IsExistRoute(nodes.Get(5),Ipv4Address ("10.1.3.2"),Ipv4Address ("10.1.1.1")));
NS_LOG_INFO("is exist route"<<IsExistRoute(nodes.Get(5),Ipv4Address ("10.1.6.2"),Ipv4Address ("10.1.4.1")));
NS_LOG_INFO("is exist route"<<IsExistRoute(nodes.Get(0),Ipv4Address ("10.1.1.1"),Ipv4Address ("10.1.6.2")));
Ptr<Ipv4L3Protocol> ipv4l3 = nodes.Get(0)->GetObject<Ipv4L3Protocol>();
for(int i = 0; i < ipv4l3->GetNInterfaces(); i++)
{
Ptr<Ipv4Interface> interface = ipv4l3->GetInterface(i);
Ipv4InterfaceAddress interfaceAddr = interface->GetAddress (0);
Ipv4Address ipv4Addr = interfaceAddr.GetLocal();
NS_LOG_INFO ("node0 address " << ipv4Addr);
}
NS_LOG_INFO ("server address " << ipv4Ints[5].GetAddress (1));
uint32_t servPort = 5000;
PacketSinkHelper sink ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), servPort));
ApplicationContainer apps = sink.Install (server);
apps.Start(Seconds(0.0));
apps.Stop(Seconds(simDuration));
Ptr<Socket> lSocket=Socket::CreateSocket (client, TypeId::LookupByName ("ns3::TcpSocketFactory"));
//InetSocketAddress local = InetSocketAddress (ipv4Ints[0].GetAddress (0), 4000);
NS_LOG_INFO ("client address " << ipv4Ints[0].GetAddress (1));
lSocket->Bind ();
Simulator::ScheduleNow (&StartFlow, lSocket, ipv4Ints[5].GetAddress (1), servPort);
Simulator::Stop (Seconds(simDuration + 10.0));
Simulator::Run ();
Simulator::Destroy();
NS_LOG_LOGIC("mpTopology:: simulation ended");
return 0;
}
void StartFlow (Ptr<Socket> lSocket,
Ipv4Address servAddress,
uint16_t servPort)
{
NS_LOG_LOGIC ("Starting flow at time " << Simulator::Now ().GetSeconds ());
lSocket->SetConnectCallback (MakeCallback (&connectionSucceeded), MakeCallback (&connectionFailed));
int connectionState = lSocket->Connect (InetSocketAddress (servAddress, servPort));
NS_LOG_INFO ("in startflow server address "<<servAddress<<" "<<servPort);
if(connectionState == 0)
{
NS_LOG_INFO("connection succeed");
lSocket->SetDataSentCallback (MakeCallback (&WriteUntilBufferFull));
lSocket->SetCloseCallbacks (MakeCallback (&HandlePeerClose), MakeCallback(&HandlePeerError));
}else
{
NS_LOG_LOGIC("ringTopology:: connection failed");
}
}
void connectionSucceeded (Ptr<Socket> localSocket)
{
NS_LOG_FUNCTION_NOARGS();
NS_LOG_INFO("mpTopology: Connection requeste succeed");
Simulator::ScheduleNow (&WriteUntilBufferFull, localSocket, 0);
Simulator::Schedule (Seconds (simDuration), &CloseConnection, localSocket);
}
void connectionFailed (Ptr<Socket> lSocket)
{
NS_LOG_FUNCTION_NOARGS();
NS_LOG_INFO("mpTopology: Connection requeste failure");
lSocket->Close();
}
void HandlePeerClose (Ptr<Socket> localSocket)
{
NS_LOG_FUNCTION_NOARGS();
//NS_LOG_INFO("mpTopology: Connection closed by peer");
NS_LOG_LOGIC("mpTopology: Connection closed by peer"<<Simulator::Now ().GetSeconds ());
localSocket->Close();
}
void HandlePeerError (Ptr<Socket> localSocket)
{
NS_LOG_FUNCTION_NOARGS();
//NS_LOG_INFO("mpTopology: Connection closed by peer error");
NS_LOG_LOGIC("mpTopology: Connection closed by peer error"<<Simulator::Now ().GetSeconds ());
localSocket->Close();
}
void CloseConnection (Ptr<Socket> localSocket)
{
localSocket->Close();
NS_LOG_LOGIC("ringTopology:: currentTxBytes = " << currentTxBytes);
NS_LOG_LOGIC("ringTopology:: totalTxBytes = " << totalTxBytes);
NS_LOG_LOGIC("ringTopology:: connection to remote host has been closed");
}
void WriteUntilBufferFull (Ptr<Socket> localSocket, unsigned int 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);
NS_LOG_INFO("DATA SENT in WriteUntilBufferFull"<<amountSent);
if(amountSent < 0)
{
// we will be called again when new tx space becomes available.
return;
}
currentTxBytes += amountSent;
}
localSocket->Close ();
}
And this interfaces index configuration works too:
// -(if1)-n1-(if2)-----(if1)-n2-(if2)-
//(if1)/ \(if1)
// n0 n5
//if(2) \ /(if2)
// -(if1)-n3-(if2)-----(if1)-n4-(if2)-
//n1->n5
staticRoutingn1->AddHostRouteTo (Ipv4Address ("10.1.3.2"), Ipv4Address ("10.1.2.2"), 2);
//n0->n5
staticRoutingn0->AddHostRouteTo (Ipv4Address ("10.1.3.2"), Ipv4Address ("10.1.1.2"),1);
//n3->n5
staticRoutingn3->AddHostRouteTo (Ipv4Address ("10.1.6.2"), Ipv4Address ("10.1.5.2"), 2);
//n0->n5
staticRoutingn0->AddHostRouteTo (Ipv4Address ("10.1.6.2"), Ipv4Address ("10.1.4.2"), 2);
//n2->n0
staticRoutingn2->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.2.1"), 1);
//n5->n0
staticRoutingn5->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.3.1"),1);
//n1->n0
//staticRoutingn1->AddHostRouteTo(Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.1.1"), 1);
//n4->n0
staticRoutingn4->AddHostRouteTo (Ipv4Address ("10.1.4.1"), Ipv4Address ("10.1.5.1"), 1);
//n5->n0
staticRoutingn5->AddHostRouteTo (Ipv4Address ("10.1.4.1"), Ipv4Address ("10.1.6.1"), 2,10);