examples: Added simulation scenario with MPI support
docs: Update documentation to include instructions
for MPI support and scenario executed in parallel
Change-Id: I5235462cad6f01751bcd5141b2c3e14585d5baa3
Refs: #2504
diff --git a/examples/ndn-simple-mpi.cpp b/examples/ndn-simple-mpi.cpp
new file mode 100644
index 0000000..84ec673
--- /dev/null
+++ b/examples/ndn-simple-mpi.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2015 Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+// ndn-simple-mpi.cpp
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/point-to-point-module.h"
+#include "ns3/ndnSIM-module.h"
+#include "ns3/mpi-interface.h"
+
+#ifdef NS3_MPI
+#include <mpi.h>
+#else
+#error "ndn-simple-mpi scenario can be compiled only if NS3_MPI is enabled"
+#endif
+
+namespace ns3 {
+
+/**
+ * This scenario simulates a very simple network topology using mpi:
+ *
+ *
+ * +----------+ 1 Mbps +----------+
+ * | consumer | <------------> | producer |
+ * +----------+ 10ms +----------+
+ *
+ *
+ * Consumer requests data from producer with frequency 10 interests per second
+ * (interests contain constantly increasing sequence number).
+ *
+ * For every received interest, producer replies with a data packet, containing
+ * 1024 bytes of virtual payload.
+ *
+ * To run scenario and see what is happening, use the following command:
+ *
+ * NS_LOG=ndn.Consumer:ndn.Producer mpirun -np 2 ./waf --run=ndn-simple-mpi
+ *
+ * The default parallel synchronization strategy implemented in the
+ * DistributedSimulatorImpl class is based on a globally synchronized algorithm
+ * using an MPI collective operation to synchronize simulation time across all LPs.
+ * A second synchronization strategy based on local communication and null messages
+ * is implemented in the NullMessageSimulatorImpl class, For the null message strategy
+ * the global all to all gather is not required; LPs only need to communication with
+ * LPs that have shared point-to-point links. The algorithm to use is controlled by
+ * which the ns-3 global value SimulatorImplementationType.
+ *
+ * The strategy can be selected according to the value of nullmsg. If nullmsg is true,
+ * then the local communication strategy is selected. If nullmsg is false, then the
+ * globally synchronized strategy is selected. This parameter can be passed either
+ * as a command line argument or by directly modifying the simulation scenario.
+ *
+ */
+
+int
+main(int argc, char* argv[])
+{
+ // setting default parameters for PointToPoint links and channels
+ Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Gbps"));
+ Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("1ms"));
+ Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("10"));
+
+ bool nullmsg = false;
+
+ // Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
+ CommandLine cmd;
+ cmd.AddValue("nullmsg", "Enable the use of null-message synchronization", nullmsg);
+ cmd.Parse(argc, argv);
+
+ // Distributed simulation setup; by default use granted time window algorithm.
+ if (nullmsg) {
+ GlobalValue::Bind("SimulatorImplementationType",
+ StringValue("ns3::NullMessageSimulatorImpl"));
+ }
+ else {
+ GlobalValue::Bind("SimulatorImplementationType",
+ StringValue("ns3::DistributedSimulatorImpl"));
+ }
+
+ // Enable parallel simulator with the command line arguments
+ MpiInterface::Enable(&argc, &argv);
+
+ uint32_t systemId = MpiInterface::GetSystemId();
+ uint32_t systemCount = MpiInterface::GetSize();
+
+ if (systemCount != 2) {
+ std::cout << "Simulation will run on a single processor only" << std::endl
+ << "To run using MPI, run" << std::endl
+ << " mpirun -np 2 ./waf --run=ndn-simple-mpi" << std::endl;
+ }
+
+ // Creating nodes
+
+ // consumer node is associated with system id 0
+ Ptr<Node> node1 = CreateObject<Node>(0);
+
+ // producer node is associated with system id 1 (or 0 when running on single CPU)
+ Ptr<Node> node2 = CreateObject<Node>(systemCount == 2 ? 1 : 0);
+
+ // Connecting nodes using a link
+ PointToPointHelper p2p;
+ p2p.Install(node1, node2);
+
+ // Install NDN stack on all nodes
+ ndn::StackHelper ndnHelper;
+ ndnHelper.InstallAll();
+
+ ndn::FibHelper::AddRoute(node1, "/prefix/1", node2, 1);
+ ndn::FibHelper::AddRoute(node2, "/prefix/2", node1, 1);
+
+ // Installing applications
+ ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
+ consumerHelper.SetAttribute("Frequency", StringValue("100")); // 10 interests a second
+
+ ndn::AppHelper producerHelper("ns3::ndn::Producer");
+ producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
+
+ // Run consumer application on the first processor only (if running on 2 CPUs)
+ if (systemCount != 2 || systemId == 0) {
+ consumerHelper.SetPrefix("/prefix/1"); // request /prefix/1/*
+ consumerHelper.Install(node1);
+
+ producerHelper.SetPrefix("/prefix/2"); // serve /prefix/2/*
+ producerHelper.Install(node1);
+
+ ndn::L3RateTracer::Install(node1, "node1.txt", Seconds(0.5));
+ }
+
+ // Run consumer application on the second processor only (if running on 2 CPUs)
+ if (systemCount != 2 || systemId == 1) {
+ // Producer
+ consumerHelper.SetPrefix("/prefix/2"); // request /prefix/2/*
+ consumerHelper.Install(node2);
+
+ producerHelper.SetPrefix("/prefix/1"); // serve /prefix/1/*
+ producerHelper.Install(node2);
+
+ ndn::L3RateTracer::Install(node2, "node2.txt", Seconds(0.5));
+ }
+
+ Simulator::Stop(Seconds(400.0));
+
+ Simulator::Run();
+ Simulator::Destroy();
+
+ MpiInterface::Disable();
+ return 0;
+}
+
+} // namespace ns3
+
+
+int
+main(int argc, char* argv[])
+{
+ return ns3::main(argc, argv);
+}
diff --git a/examples/wscript b/examples/wscript
index b7e9afb..c1eb9c3 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -6,7 +6,11 @@
# This may be necessary for visualizer to work
all_modules = [mod[len("ns3-"):] for mod in bld.env['NS3_ENABLED_MODULES']]
- for i in bld.path.ant_glob(['*.cpp']):
+ examples = bld.path.ant_glob(['*.cpp'], excl=['*-mpi.cpp'])
+ if 'NS3_MPI' in bld.env['DEFINES_MPI']:
+ examples += bld.path.ant_glob(['*-mpi.cpp'])
+
+ for i in examples:
name = str(i)[:-len(".cpp")]
obj = bld.create_ns3_program(name, all_modules)
obj.source = [i] + bld.path.ant_glob(['%s/**/*.cpp' % name])