From de21686fd7d3df93c9f53a4e767a9593b79de394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20M=C3=A4kel=C3=A4?= Date: Tue, 15 Dec 2009 21:07:22 -0800 Subject: [PATCH] examples for Socket::BindToNetDevice() --- .../socket/socket-bound-static-routing.cc | 220 +++++++++++++++++ .../socket/socket-bound-tcp-static-routing.cc | 231 ++++++++++++++++++ examples/socket/waf | 1 + examples/socket/wscript | 8 + 4 files changed, 460 insertions(+) create mode 100644 examples/socket/socket-bound-static-routing.cc create mode 100644 examples/socket/socket-bound-tcp-static-routing.cc create mode 100755 examples/socket/waf create mode 100644 examples/socket/wscript diff --git a/examples/socket/socket-bound-static-routing.cc b/examples/socket/socket-bound-static-routing.cc new file mode 100644 index 000000000..9e9df10b9 --- /dev/null +++ b/examples/socket/socket-bound-static-routing.cc @@ -0,0 +1,220 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* 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 +*/ + +#include +#include +#include +#include + +#include "ns3/core-module.h" +#include "ns3/simulator-module.h" +#include "ns3/node-module.h" +#include "ns3/helper-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("SocketBoundRoutingExample"); + +void SendStuff (Ptr sock, Ipv4Address dstaddr, uint16_t port); +void BindSock (Ptr sock, Ptr netdev); +void srcSocketRecv (Ptr socket); +void dstSocketRecv (Ptr socket); + +int +main (int argc, char *argv[]) +{ + + // Allow the user to override any of the defaults and the above + // DefaultValue::Bind ()s at run-time, via command-line arguments + CommandLine cmd; + cmd.Parse (argc, argv); + + Ptr nSrc = CreateObject (); + Ptr nDst = CreateObject (); + Ptr nRtr1 = CreateObject (); + Ptr nRtr2 = CreateObject (); + Ptr nDstRtr = CreateObject (); + + NodeContainer c = NodeContainer (nSrc, nDst, nRtr1, nRtr2, nDstRtr); + + InternetStackHelper internet; + internet.Install (c); + + // Point-to-point links + NodeContainer nSrcnRtr1 = NodeContainer (nSrc, nRtr1); + NodeContainer nSrcnRtr2 = NodeContainer (nSrc, nRtr2); + NodeContainer nRtr1nDstRtr = NodeContainer (nRtr1, nDstRtr); + NodeContainer nRtr2nDstRtr = NodeContainer (nRtr2, nDstRtr); + NodeContainer nDstRtrnDst = NodeContainer (nDstRtr, nDst); + + // We create the channels first without any IP addressing information + PointToPointHelper p2p; + p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); + p2p.SetChannelAttribute ("Delay", StringValue ("2ms")); + NetDeviceContainer dSrcdRtr1 = p2p.Install (nSrcnRtr1); + NetDeviceContainer dSrcdRtr2 = p2p.Install (nSrcnRtr2); + NetDeviceContainer dRtr1dDstRtr = p2p.Install (nRtr1nDstRtr); + NetDeviceContainer dRtr2dDstRtr = p2p.Install (nRtr2nDstRtr); + NetDeviceContainer dDstRtrdDst = p2p.Install (nDstRtrnDst); + + Ptr SrcToRtr1=dSrcdRtr1.Get (0); + Ptr SrcToRtr2=dSrcdRtr2.Get (0); + + // Later, we add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iSrciRtr1 = ipv4.Assign (dSrcdRtr1); + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + Ipv4InterfaceContainer iSrciRtr2 = ipv4.Assign (dSrcdRtr2); + ipv4.SetBase ("10.10.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iRtr1iDstRtr = ipv4.Assign (dRtr1dDstRtr); + ipv4.SetBase ("10.10.2.0", "255.255.255.0"); + Ipv4InterfaceContainer iRtr2iDstRtr = ipv4.Assign (dRtr2dDstRtr); + ipv4.SetBase ("10.20.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iDstRtrDst = ipv4.Assign (dDstRtrdDst); + + Ptr ipv4Src = nSrc->GetObject (); + Ptr ipv4Rtr1 = nRtr1->GetObject (); + Ptr ipv4Rtr2 = nRtr2->GetObject (); + Ptr ipv4DstRtr = nDstRtr->GetObject (); + Ptr ipv4Dst = nDst->GetObject (); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr staticRoutingSrc = ipv4RoutingHelper.GetStaticRouting (ipv4Src); + Ptr staticRoutingRtr1 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr1); + Ptr staticRoutingRtr2 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr2); + Ptr staticRoutingDstRtr = ipv4RoutingHelper.GetStaticRouting (ipv4DstRtr); + Ptr staticRoutingDst = ipv4RoutingHelper.GetStaticRouting (ipv4Dst); + + // Create static routes from Src to Dst + staticRoutingRtr1->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.1.2"), 2); + staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.2.2"), 2); + + // Two routes to same destination - setting separate metrics. + // You can switch these to see how traffic gets diverted via different routes + staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.1.2"), 1,5); + staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.2.2"), 2,10); + + // Creating static routes from DST to Source pointing to Rtr1 VIA Rtr2(!) + staticRoutingDst->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.20.1.1"), 1); + staticRoutingDstRtr->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.10.2.1"), 2); + staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.2.1"), 1); + + Ipv4InterfaceAddress ifInAddrSrc=ipv4Src->GetAddress (1,0); + + // There are no apps that can utilize the Socket Option so doing the work directly.. + // Taken from tcp-large-transfer example + + Ptr srcSocket = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::UdpSocketFactory")); + srcSocket->Bind (); + srcSocket->SetRecvCallback (MakeCallback (&srcSocketRecv)); + + Ptr dstSocket = Socket::CreateSocket (nDst, TypeId::LookupByName ("ns3::UdpSocketFactory")); + uint16_t dstport = 12345; + Ipv4Address dstaddr ("10.20.1.2"); + InetSocketAddress dst = InetSocketAddress (dstaddr, dstport); + dstSocket->Bind (dst); + dstSocket->SetRecvCallback (MakeCallback (&dstSocketRecv)); + + std::ofstream ascii; + ascii.open ("socket-bound-static-routing.tr"); + PointToPointHelper::EnablePcapAll ("socket-bound-static-routing"); + PointToPointHelper::EnableAsciiAll (ascii); + + LogComponentEnableAll (LOG_PREFIX_TIME); + LogComponentEnable ("SocketBoundRoutingExample", LOG_LEVEL_INFO); + + // First packet as normal (goes via Rtr1) + Simulator::Schedule (Seconds (0.1),&SendStuff, srcSocket, dstaddr, dstport); + // Second via Rtr1 explicitly + Simulator::Schedule (Seconds (1.0),&BindSock, srcSocket, SrcToRtr1); + Simulator::Schedule (Seconds( 1.1),&SendStuff, srcSocket, dstaddr, dstport); + // Third via Rtr2 explicitly + Simulator::Schedule (Seconds (2.0),&BindSock, srcSocket, SrcToRtr2); + Simulator::Schedule (Seconds (2.1),&SendStuff, srcSocket, dstaddr, dstport); + // Fourth again as normal (goes via Rtr1) + Simulator::Schedule (Seconds (3.0),&BindSock, srcSocket, Ptr(0)); + Simulator::Schedule (Seconds (3.1),&SendStuff, srcSocket, dstaddr, dstport); + // If you uncomment what's below, it results in ASSERT failing since you can't + // bind to a socket not existing on a node + // Simulator::Schedule(Seconds(4.0),&BindSock, srcSocket, dDstRtrdDst.Get(0)); + Simulator::Run (); + Simulator::Destroy (); + + return 0; +} + +void SendStuff(Ptr sock, Ipv4Address dstaddr, uint16_t port) +{ + Ptr p = Create (); + p->AddPaddingAtEnd (100); + sock->SendTo (p, 0, InetSocketAddress (dstaddr,port)); + return; +} + +void BindSock(Ptr sock, Ptr netdev) +{ + sock->BindToNetDevice (netdev); + return; +} + +void +srcSocketRecv (Ptr socket) +{ + Address from; + Ptr packet = socket->RecvFrom (from); + packet->RemoveAllPacketTags (); + packet->RemoveAllByteTags (); + InetSocketAddress address = InetSocketAddress::ConvertFrom (from); + NS_LOG_INFO ("Source Received " << packet->GetSize () << " bytes from " << address.GetIpv4()); + if (socket->GetBoundNetDevice ()) + { + NS_LOG_INFO ("Socket was bound"); + } + else + { + NS_LOG_INFO ("Socket was not bound"); + } +} + +void +dstSocketRecv (Ptr socket) +{ + Address from; + Ptr packet = socket->RecvFrom (from); + packet->RemoveAllPacketTags (); + packet->RemoveAllByteTags (); + InetSocketAddress address = InetSocketAddress::ConvertFrom (from); + NS_LOG_INFO ("Destination Received " << packet->GetSize () << " bytes from " << address.GetIpv4 ()); + NS_LOG_INFO ("Triggering packet back to source node's interface 1"); + SendStuff(socket, Ipv4Address ("10.1.1.1"), address.GetPort ()); +} diff --git a/examples/socket/socket-bound-tcp-static-routing.cc b/examples/socket/socket-bound-tcp-static-routing.cc new file mode 100644 index 000000000..6b1f1e581 --- /dev/null +++ b/examples/socket/socket-bound-tcp-static-routing.cc @@ -0,0 +1,231 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* 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 +*/ + +#include +#include +#include +#include + +#include "ns3/core-module.h" +#include "ns3/simulator-module.h" +#include "ns3/node-module.h" +#include "ns3/helper-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("SocketBoundTcpRoutingExample"); + +static const uint32_t totalTxBytes = 20000; +static uint32_t currentTxBytes = 0; +static const uint32_t writeSize = 1040; +uint8_t data[writeSize]; + + +void StartFlow (Ptr, Ipv4Address, uint16_t); +void WriteUntilBufferFull (Ptr, uint32_t); + +void SendStuff (Ptr sock, Ipv4Address dstaddr, uint16_t port); +void BindSock (Ptr sock, Ptr netdev); +void srcSocketRecv (Ptr socket); +void dstSocketRecv (Ptr socket); + +int +main (int argc, char *argv[]) +{ + + // Allow the user to override any of the defaults and the above + // DefaultValue::Bind ()s at run-time, via command-line arguments + CommandLine cmd; + cmd.Parse (argc, argv); + + Ptr nSrc = CreateObject (); + Ptr nDst = CreateObject (); + Ptr nRtr1 = CreateObject (); + Ptr nRtr2 = CreateObject (); + Ptr nDstRtr = CreateObject (); + + NodeContainer c = NodeContainer (nSrc, nDst, nRtr1, nRtr2, nDstRtr); + + InternetStackHelper internet; + internet.Install (c); + + // Point-to-point links + NodeContainer nSrcnRtr1 = NodeContainer (nSrc, nRtr1); + NodeContainer nSrcnRtr2 = NodeContainer (nSrc, nRtr2); + NodeContainer nRtr1nDstRtr = NodeContainer (nRtr1, nDstRtr); + NodeContainer nRtr2nDstRtr = NodeContainer (nRtr2, nDstRtr); + NodeContainer nDstRtrnDst = NodeContainer (nDstRtr, nDst); + + // We create the channels first without any IP addressing information + PointToPointHelper p2p; + p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); + p2p.SetChannelAttribute ("Delay", StringValue ("2ms")); + NetDeviceContainer dSrcdRtr1 = p2p.Install (nSrcnRtr1); + NetDeviceContainer dSrcdRtr2 = p2p.Install (nSrcnRtr2); + NetDeviceContainer dRtr1dDstRtr = p2p.Install (nRtr1nDstRtr); + NetDeviceContainer dRtr2dDstRtr = p2p.Install (nRtr2nDstRtr); + NetDeviceContainer dDstRtrdDst = p2p.Install (nDstRtrnDst); + + Ptr SrcToRtr1=dSrcdRtr1.Get (0); + Ptr SrcToRtr2=dSrcdRtr2.Get (0); + + // Later, we add IP addresses. + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iSrciRtr1 = ipv4.Assign (dSrcdRtr1); + ipv4.SetBase ("10.1.2.0", "255.255.255.0"); + Ipv4InterfaceContainer iSrciRtr2 = ipv4.Assign (dSrcdRtr2); + ipv4.SetBase ("10.10.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iRtr1iDstRtr = ipv4.Assign (dRtr1dDstRtr); + ipv4.SetBase ("10.10.2.0", "255.255.255.0"); + Ipv4InterfaceContainer iRtr2iDstRtr = ipv4.Assign (dRtr2dDstRtr); + ipv4.SetBase ("10.20.1.0", "255.255.255.0"); + Ipv4InterfaceContainer iDstRtrDst = ipv4.Assign (dDstRtrdDst); + + Ptr ipv4Src = nSrc->GetObject (); + Ptr ipv4Rtr1 = nRtr1->GetObject (); + Ptr ipv4Rtr2 = nRtr2->GetObject (); + Ptr ipv4DstRtr = nDstRtr->GetObject (); + Ptr ipv4Dst = nDst->GetObject (); + + Ipv4StaticRoutingHelper ipv4RoutingHelper; + Ptr staticRoutingSrc = ipv4RoutingHelper.GetStaticRouting (ipv4Src); + Ptr staticRoutingRtr1 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr1); + Ptr staticRoutingRtr2 = ipv4RoutingHelper.GetStaticRouting (ipv4Rtr2); + Ptr staticRoutingDstRtr = ipv4RoutingHelper.GetStaticRouting (ipv4DstRtr); + Ptr staticRoutingDst = ipv4RoutingHelper.GetStaticRouting (ipv4Dst); + + // Create static routes from Src to Dst + staticRoutingRtr1->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.1.2"), 2); + staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.10.2.2"), 2); + + // Two routes to same destination - setting separate metrics. + // You can switch these to see how traffic gets diverted via different routes + staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.1.2"), 1,5); + staticRoutingSrc->AddHostRouteTo (Ipv4Address ("10.20.1.2"), Ipv4Address ("10.1.2.2"), 2,10); + + // Creating static routes from DST to Source pointing to Rtr1 VIA Rtr2(!) + staticRoutingDst->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.20.1.1"), 1); + staticRoutingDstRtr->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.10.2.1"), 2); + staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.1.1.1"), Ipv4Address ("10.1.2.1"), 1); + + staticRoutingDst->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.20.1.1"), 1); + staticRoutingDstRtr->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.10.2.1"), 2); + staticRoutingRtr2->AddHostRouteTo (Ipv4Address ("10.1.2.1"), Ipv4Address ("10.1.2.1"), 1); + + Ipv4InterfaceAddress ifInAddrSrc=ipv4Src->GetAddress (1,0); + + // There are no apps that can utilize the Socket Option so doing the work directly.. + // Taken from tcp-large-transfer example + + Ptr srcSocket1 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory")); + Ptr srcSocket2 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory")); + Ptr srcSocket3 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory")); + Ptr srcSocket4 = Socket::CreateSocket (nSrc, TypeId::LookupByName ("ns3::TcpSocketFactory")); + + + uint16_t dstport = 12345; + Ipv4Address dstaddr ("10.20.1.2"); + + PacketSinkHelper sink ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny(), dstport)); + ApplicationContainer apps = sink.Install (nDst); + apps.Start (Seconds (0.0)); + apps.Stop (Seconds (10.0)); + + std::ofstream ascii; + ascii.open ("socket-bound-tcp-static-routing.tr"); + PointToPointHelper::EnablePcapAll ("socket-bound-tcp-static-routing"); + PointToPointHelper::EnableAsciiAll (ascii); + + LogComponentEnableAll (LOG_PREFIX_TIME); + LogComponentEnable ("SocketBoundTcpRoutingExample", LOG_LEVEL_INFO); + + // First packet as normal (goes via Rtr1) + Simulator::Schedule (Seconds (0.1),&StartFlow, srcSocket1, dstaddr, dstport); + // Second via Rtr1 explicitly + Simulator::Schedule (Seconds (1.0),&BindSock, srcSocket2, SrcToRtr1); + Simulator::Schedule (Seconds (1.1),&StartFlow, srcSocket2, dstaddr, dstport); + // Third via Rtr2 explicitly + Simulator::Schedule (Seconds (2.0),&BindSock, srcSocket3, SrcToRtr2); + Simulator::Schedule (Seconds (2.1),&StartFlow, srcSocket3, dstaddr, dstport); + // Fourth again as normal (goes via Rtr1) + Simulator::Schedule (Seconds (3.0),&BindSock, srcSocket4, Ptr(0)); + Simulator::Schedule (Seconds (3.1),&StartFlow, srcSocket4, dstaddr, dstport); + // If you uncomment what's below, it results in ASSERT failing since you can't + // bind to a socket not existing on a node + // Simulator::Schedule(Seconds(4.0),&BindSock, srcSocket, dDstRtrdDst.Get(0)); + Simulator::Run (); + Simulator::Destroy (); + + return 0; +} + +void BindSock(Ptr sock, Ptr netdev) +{ + sock->BindToNetDevice(netdev); + return; +} + +void StartFlow(Ptr localSocket, + Ipv4Address servAddress, + uint16_t servPort) +{ + NS_LOG_INFO ("Starting flow at time " << Simulator::Now ().GetSeconds ()); + currentTxBytes = 0; + localSocket->Bind (); + 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 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 (); +} diff --git a/examples/socket/waf b/examples/socket/waf new file mode 100755 index 000000000..941d56b43 --- /dev/null +++ b/examples/socket/waf @@ -0,0 +1 @@ +exec "`dirname "$0"`"/../../waf "$@" diff --git a/examples/socket/wscript b/examples/socket/wscript new file mode 100644 index 000000000..c95aa9ca5 --- /dev/null +++ b/examples/socket/wscript @@ -0,0 +1,8 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_program('socket-bound-static-routing', ['node', 'csma', 'internet-stack']) + obj.source = 'socket-bound-static-routing.cc' + + obj = bld.create_ns3_program('socket-bound-tcp-static-routing', ['node', 'csma', 'internet-stack']) + obj.source = 'socket-bound-tcp-static-routing.cc'