--- a/src/ltp-protocol/examples/ltp-emu.cc Tue Feb 17 18:25:53 2015 +0100
+++ b/src/ltp-protocol/examples/ltp-emu.cc Tue Feb 17 23:18:33 2015 +0100
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2012 University of Washington, 2012 INRIA
+ * Copyright (c) 2012 University of Washington, 2012 INRIA
*
* 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
@@ -16,29 +16,32 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// Allow ns-3 to ping a real host somewhere, using emulation mode
+// Adapted from ns-3 example program fd-emu-ping.cc
//
-// +----------------------+
+// Allow ns-3 LTP client to send data to an external LTP server
+// (or external LTP client to send to ns-3 server)
+// using emulation mode
+//
+// +----------------------+
// | host |
-// +----------------------+
-// | ns-3 simulation |
-// +----------------------+
-// | ns-3 Node |
-// | +----------------+ |
-// | | ns-3 TCP | |
-// | +----------------+ |
-// | | ns-3 IPv4 | |
-// | +----------------+ |
-// | | FdNetDevice | |
-// |--+----------------+--+
-// | | eth0 | |
-// | +------+ |
-// | | |
-// +----------|-----------+
-// |
-// | +---------+
-// .---------| GW host |--- (Internet) -----
-// +---------+
+// +----------------------+
+// | ns-3 simulation |
+// +----------------------+
+// | ns-3 Node |
+// | +----------------+ |
+// | | ns-3 LTP | |
+// | +----------------+ |
+// | | ns-3 UDP/IP | |
+// | +----------------+ |
+// | | FdNetDevice | |
+// |--+----------------+--+
+// | | eth0 | | +----------------+
+// | +------+ | | LTP server |
+// | | | | implementation |
+// +----------|-----------+ +----------------+
+// | real device |
+// | |
+// .---------(network) -----------.
//
/// To use this example:
// 1) You need to decide on a physical device on your real system, and either
@@ -54,18 +57,28 @@
// That is, you will have to assign an IP address to the ns-3 node as if
// it were on your real subnet. Search for "Ipv4Address localIp" and
// replace the string "1.2.3.4" with a valid IP address.
-// 5) You will need to configure a default route in the ns-3 node to tell it
-// how to get off of your subnet. One thing you could do is a
-// 'netstat -rn' command and find the IP address of the default gateway
-// on your host. Search for "Ipv4Address gateway" and replace the string
-// "1.2.3.4" string with the gateway IP address.
-/// 6) Give root suid to the raw socket creator binary.
+// 5) If you are sending to a server off of the local subnet, you will
+// need to configure a default route in the ns-3 node to tell it
+// how to get off of your subnet. This example doesn't use a gateway
+// as presently written, however (see fd-emu-ping.cc for an example)
+/// 6) Give root suid to the raw socket creator binary, or run as root
// If the --enable-sudo option was used to configure ns-3 with waf, then the following
// step will not be necessary.
//
// $ sudo chown root.root build/src/fd-net-device/ns3-dev-raw-sock-creator
// $ sudo chmod 4755 build/src/fd-net-device/ns3-dev-raw-sock-creator
//
+// Some details on the LTP server assumptions: this example was tested
+// against LTPlib found at http://down.dsg.cs.tcd.ie/ltplib/
+// The LTP server was run as:
+// ltpd -m S -L 10.0.0.2:1113 -S 10.0.0.1:1113 -o ltpd.server.out
+// On the client side, the ns-3 configuration below was designed to
+// approximate a client ltpd command of:
+// ltpd -w20 -i a.txt -m C -D 10.0.0.2:1113 -S 10.0.0.1:1113
+// where the file 'a.txt' contained 1024x100 characters identically set to 'A'
+//
+// The ns-3 value of 1000ms for OneWayLightTime was conservative; the LTPlib
+// assumes a 200ms RTT
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
@@ -79,40 +92,55 @@
using namespace ns3;
using namespace ltp;
+NS_LOG_COMPONENT_DEFINE ("LtpEmulationExample");
+
+// Global variables for use in callbacks
+
+Ptr<Node> node;
+
+struct StartTransmissionParameters
+{
+ uint64_t clientServiceId;
+ uint64_t ltpEngineId;
+ std::vector<uint8_t> data;
+ uint32_t redPartSize;
+} params;
+
+// This callback will launch the LTP data transfer once a ICMP response is
+// received
void
-ClientServiceInstanceNotificationsSnd (SessionId id,
- StatusNotificationCode code,
- std::vector<uint8_t> data,
- uint32_t dataLength,
- bool endFlag,
- uint64_t srcLtpEngine,
- uint32_t offset )
+RttTracer (Time receivedRtt)
{
- std::cout << "ClientServiceNotification - Session ID: " << id.GetSessionNumber () << " Code : " << code << std::endl;
-
+ NS_LOG_DEBUG ("Received ping response at " << Simulator::Now ().GetSeconds ());
+ node->GetObject<LtpProtocol> ()->StartTransmission (params.clientServiceId, params.clientServiceId, params.ltpEngineId, params.data, params.redPartSize);
}
-NS_LOG_COMPONENT_DEFINE ("LtpEmulationExample");
+void
+ClientServiceInstanceNotificationsSend (SessionId id,
+ StatusNotificationCode code,
+ std::vector<uint8_t> data,
+ uint32_t dataLength,
+ bool endFlag,
+ uint64_t srcLtpEngine,
+ uint32_t offset )
+{
+ NS_LOG_DEBUG ("ClientServiceNotification - Session ID: " << id.GetSessionNumber () << " Code : " << code);
+}
int
main (int argc, char *argv[])
{
NS_LOG_INFO ("Ltp Emulation Example");
-
+
+ // If you are running with RTT greater than 2 seconds, increase the
+ // below default value further
+ Config::SetDefault ("ns3::ArpCache::WaitReplyTimeout", TimeValue (Seconds (3)));
+ std::string deviceName ("eth0"); // set to your local emulation interface
+ std::string remote ("10.0.0.2"); // set to destination LTP server IP address
+ uint8_t testNum = 0; // default
bool verbose = true;
-
- if (verbose)
- {
- LogComponentEnable ("LtpProtocol", LOG_LEVEL_ALL);
- LogComponentEnable ("LtpUdpConvergenceLayerAdapter", LOG_LEVEL_ALL);
- }
+ bool server = false;
- std::string deviceName ("eth0");
- std::string remote ("10.0.0.2");
- std::string type("nominal");
- uint8_t testNum = 0;
-
- Config::SetDefault ("ns3::ArpCache::WaitReplyTimeout", TimeValue (Seconds(3)));
//
// Allow the user to override any of the defaults at run-time, via
// command-line arguments
@@ -120,76 +148,64 @@
CommandLine cmd;
cmd.AddValue ("deviceName", "Device name", deviceName);
cmd.AddValue ("remote", "Remote IP address (dotted decimal only please)", remote);
- cmd.AddValue ("testType", " Type of test to perform" , type);
- cmd.AddValue ("testNum", " Test to perform" , testNum);
+ cmd.AddValue ("testNum", " Test to perform", testNum);
+ cmd.AddValue ("verbose", "Verbose log if true", verbose);
+ cmd.AddValue ("server", "Run as server mode", server);
cmd.Parse (argc, argv);
-
- /* Config tests */
-
- // Create a block of data
- uint32_t blockSize = 500;
- uint32_t redPartSize = 500;
- std::list<uint32_t> sender_losses;
-
- if (type == "nominal")
- {
- switch (testNum)
+
+ if (verbose)
{
- case '1':
- blockSize = 500;
- redPartSize = blockSize;
- break;
- case '2':
- blockSize = 5000;
- redPartSize = blockSize;
- break;
- case '3':
- blockSize = 500;
- redPartSize = 200;
- break;
- case '4':
- blockSize = 5000;
- redPartSize = 2000;
- break;
- case '5':
- blockSize = 500;
- redPartSize = 0;
- break;
- case '6':
- blockSize = 5000;
- redPartSize = 0;
- break;
- default:
- blockSize = 500;
- redPartSize = blockSize;
+ LogComponentEnable ("LtpProtocol", LOG_LEVEL_ALL);
+ LogComponentEnable ("LtpUdpConvergenceLayerAdapter", LOG_LEVEL_ALL);
+ LogComponentEnable ("Ipv4L3Protocol", LOG_LEVEL_ALL);
+ LogComponentEnable ("UdpSocketImpl", LOG_LEVEL_ALL);
+ LogComponentEnable ("UdpL4Protocol", LOG_LEVEL_ALL);
+ }
+ uint32_t blockSize;
+ uint32_t redPartSize;
+ if (server == false)
+ {
+ // these test numbers support emulation studies by varying the block
+ // size and red part size
+ switch (testNum)
+ {
+ case '1':
+ blockSize = 500;
+ redPartSize = blockSize;
+ break;
+ case '2':
+ blockSize = 5000;
+ redPartSize = blockSize;
+ break;
+ case '3':
+ blockSize = 500;
+ redPartSize = 200;
+ break;
+ case '4':
+ blockSize = 5000;
+ redPartSize = 2000;
+ break;
+ case '5':
+ blockSize = 500;
+ redPartSize = 0;
+ break;
+ case '6':
+ blockSize = 5000;
+ redPartSize = 0;
+ break;
+ default:
+ blockSize = 1024 * 100;
+ redPartSize = blockSize;
+ }
}
- }
- else if (type == "retrans")
- {
- switch (testNum)
- {
- case '1':
- blockSize = 1024*10;
- redPartSize = blockSize;
- break;
- default:
- blockSize = 1024*10;
- redPartSize = blockSize;
-
- }
- }
- else
- NS_ABORT_MSG("Test type not supported");
-
-
+
Ipv4Address remoteIp (remote.c_str ());
- Ipv4Address localIp ("10.0.0.1");
+ Ipv4Address localIp ("1.2.3.4");
+ Ipv4Mask localMask ("255.255.255.0");
NS_ABORT_MSG_IF (localIp == "1.2.3.4", "You must change the local IP address before running this example");
- Ipv4Mask localMask ("255.255.255.0");
-
//
// Since we are using a real piece of hardware we need to use the realtime
// simulator.
@@ -209,8 +225,7 @@
// First we need a single node.
//
NS_LOG_INFO ("Create Node");
- NodeContainer nodes;
- nodes.Create (1);
+ node = CreateObject<Node> ();
//
// Create an emu device, allocate a MAC address and point the device to the
@@ -218,7 +233,7 @@
// create a droptail queue and give it to the device. Finally, "install"
// the device into the node.
//
- // Do understand that the ns-3 allocated MAC address will be sent out over
+ // Understand that the ns-3 allocated MAC address will be sent out over
// your network since the emu net device will spoof it. By default, this
// address will have an Organizationally Unique Identifier (OUI) of zero.
// The Internet Assigned Number Authority IANA
@@ -226,16 +241,14 @@
// http://www.iana.org/assignments/ethernet-numbers
//
// reports that this OUI is unassigned, and so should not conflict with
- // real hardware on your net. It may raise all kinds of red flags in a
- // real environment to have packets from a device with an obviously bogus
- // OUI flying around. Be aware.
+ // real hardware on your net.
//
NS_LOG_INFO ("Create Device");
EmuFdNetDeviceHelper emu;
emu.SetDeviceName (deviceName);
- NetDeviceContainer devices = emu.Install (nodes.Get(0));
+ NetDeviceContainer devices = emu.Install (node);
Ptr<NetDevice> device = devices.Get (0);
- device->SetMtu(1500); // Ethernet
+ device->SetMtu (1500);
device->SetAttribute ("Address", Mac48AddressValue (Mac48Address::Allocate ()));
//
@@ -244,61 +257,88 @@
//
NS_LOG_INFO ("Add Internet Stack");
InternetStackHelper internetStackHelper;
- internetStackHelper.Install (nodes);
+ internetStackHelper.Install (node);
NS_LOG_INFO ("Create IPv4 Interface");
- Ptr<ns3::Ipv4> ipv4 = nodes.Get(0)->GetObject<ns3::Ipv4> ();
+ Ptr<ns3::Ipv4> ipv4 = node->GetObject<ns3::Ipv4> ();
uint32_t interface = ipv4->AddInterface (device);
Ipv4InterfaceAddress address = Ipv4InterfaceAddress (localIp, localMask);
ipv4->AddAddress (interface, address);
ipv4->SetMetric (interface, 1);
ipv4->SetUp (interface);
- // Define the ClientService ID Code of the Client Service Instance that will be using the Ltp protocol.
- uint64_t ClientServiceId = 0; // Bundle
+ // Begin LTP configuration. Define the ClientService ID Code of the
+ // Client Service Instance that will be using the Ltp protocol.
+ uint64_t ClientServiceId;
+ uint64_t remotePeer;
+ if (server == false)
+ {
+ // ns-3 values
+ ClientServiceId = 0; // Bundle
+ remotePeer = 1; // LTP engine id of remote host
+ }
+ else
+ {
+ // LTPlib values
+ ClientServiceId = 1113; // Bundle
+ remotePeer = 167772162; // LTP engine id of remote host
+ }
- uint64_t remotePeer = 1; // LTP engine id of remote host
-
- // Creta a LtpIpResolution table to perform mappings between Ipv4 adresses and LtpEngineIDs
+ // Create a LtpIpResolution table to perform mappings between Ipv4 adresses and LtpEngineIDs
Ptr<LtpIpResolutionTable> routing = CreateObjectWithAttributes<LtpIpResolutionTable> ("Addressing", StringValue ("Ipv4"));
+ // Port 1113 reserved for LTP
routing->AddBinding (remotePeer, remoteIp, 1113);
-
+
// Use a helper to create and install Ltp Protocol instances in the nodes.
+ // Make sure that the OneWayLightTime exceeds the real RTT; otherwise,
+ // spurious transmissions may result
LtpProtocolHelper ltpHelper;
- ltpHelper.SetAttributes("CheckPointRtxLimit", UintegerValue(20),
- "ReportSegmentRtxLimit", UintegerValue(20),
- "RetransCyclelimit", UintegerValue(20),
- "OneWayLightTime", TimeValue(MilliSeconds(1))
- );
+ ltpHelper.SetAttributes ("CheckPointRtxLimit", UintegerValue (20),
+ "ReportSegmentRtxLimit", UintegerValue (20),
+ "RetransCyclelimit", UintegerValue (20),
+ "OneWayLightTime", TimeValue (MilliSeconds (100))
+ );
ltpHelper.SetLtpIpResolutionTable (routing);
ltpHelper.SetBaseLtpEngineId (0);
- ltpHelper.SetStartTransmissionTime(Seconds(1));
- ltpHelper.InstallAndLink (nodes.Get(0), remotePeer);
+ ltpHelper.SetStartTransmissionTime (Seconds (1));
+ ltpHelper.InstallAndLink (node, remotePeer);
// Register ClientServiceInstances with the corresponding Ltp Engine of each node
- CallbackBase cb = MakeCallback (&ClientServiceInstanceNotificationsSnd);
- nodes.Get(0)->GetObject<LtpProtocol> ()->RegisterClientService (ClientServiceId,cb);
-
-
- std::vector<uint8_t> data3 ( blockSize, 65);
- std::cout << "Block size: " << data3.size() << " Red preffix size: " << redPartSize << std::endl;
- //std::vector<uint8_t> data3 ( 500, 65);
-
- // Transmit it from n0 to n1.
- uint64_t receiverLtpId = 1;
- nodes.Get(0)->GetObject<LtpProtocol> ()->StartTransmission (ClientServiceId,ClientServiceId,receiverLtpId,data3,redPartSize);
-
+ CallbackBase cb = MakeCallback (&ClientServiceInstanceNotificationsSend);
+ node->GetObject<LtpProtocol> ()->RegisterClientService (ClientServiceId,cb);
//
// Enable a promiscuous pcap trace to see what is coming and going on our device.
//
- emu.EnablePcap ("emu-ltp", device, true);
+ emu.EnablePcap ("ltp-emu", device, true);
+
+ if (server == false)
+ {
+ // Simulator will schedule transmission once a ping reply is received
+ // Set the global variables that need to be accessed by the callback
+ params.clientServiceId = ClientServiceId;
+ params.ltpEngineId = 1;
+ // '65' is ASCII character 'A'
+ params.data = std::vector<uint8_t> ( blockSize, 65);
+ params.redPartSize = redPartSize;
+ NS_LOG_DEBUG ("Block size: " << params.data.size () << " Red prefix size: " << redPartSize);
+
+ Ptr<V4Ping> v4ping = CreateObject<V4Ping> ();
+ v4ping->SetAttribute ("Remote", Ipv4AddressValue (Ipv4Address (remote.c_str ())));
+ // A value of 60 will cause only one ping to occur during a 30 second
+ // simulation (i.e. this approximates the '-c' count option of the
+ // real ping program, which is not a supported option in ns-3
+ v4ping->SetAttribute ("Interval", TimeValue (Seconds (60)));
+ node->AddApplication (v4ping);
+ v4ping->SetStartTime (MilliSeconds (500));
+ v4ping->TraceConnectWithoutContext ("Rtt", MakeCallback (&RttTracer));
+ }
//
// Now, do the actual emulation.
//
NS_LOG_INFO ("Run Emulation.");
- Simulator::Stop (Seconds (10.0));
+ Simulator::Stop (Seconds (40.0));
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");