helper: Add LFID route calculation
Loop-Free In-port Dependent (LFID) route calculation provides a set of loop-free paths.
Basically porting the existing code from https://github.com/schneiderklaus/ndnSIM-routing
Refs: #4985
Change-Id: I1ab25e729851cf2233c3b99be715ba0159cca0c7
diff --git a/examples/lfid.cpp b/examples/lfid.cpp
new file mode 100644
index 0000000..e2d6f05
--- /dev/null
+++ b/examples/lfid.cpp
@@ -0,0 +1,154 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2019 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/>.
+ **/
+
+#include "ns3/command-line.h"
+#include "ns3/double.h"
+#include "ns3/names.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/uinteger.h"
+
+#include "ns3/ndnSIM/helper/ndn-app-helper.hpp"
+#include "ns3/ndnSIM/helper/ndn-global-routing-helper.hpp"
+#include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
+#include "ns3/ndnSIM/helper/ndn-strategy-choice-helper.hpp"
+#include "ns3/ndnSIM/model/ndn-l3-protocol.hpp"
+#include "ns3/ndnSIM/model/ndn-net-device-transport.hpp"
+//#include "ns3/ndnSIM/NFD/daemon/fw/random-strategy.hpp"
+#include "ns3/ndnSIM/NFD/daemon/fw/best-route-strategy2.hpp"
+#include "ns3/ndnSIM/utils/topology/annotated-topology-reader.hpp"
+
+namespace ns3 {
+
+void
+displayRoutes(const NodeContainer& allNodes, const std::string& prefix)
+{
+ for (const auto& n : allNodes) {
+ const auto& fib = n->GetObject<ndn::L3Protocol>()->getForwarder()->getFib();
+ const auto& e = fib.findLongestPrefixMatch(prefix);
+
+ std::cout << "Node " << n->GetId() << ", prefix: " << prefix << "\n";
+
+ for (const auto& nh : e.getNextHops()) {
+ // Get remote nodeId from face:
+ const auto transport = dynamic_cast<ndn::NetDeviceTransport*>(nh.getFace().getTransport());
+ if (transport == nullptr)
+ continue;
+
+ const auto nd1 = transport->GetNetDevice()->GetObject<PointToPointNetDevice>();
+ if (nd1 == nullptr)
+ continue;
+
+ const auto ppChannel = DynamicCast<PointToPointChannel>(nd1->GetChannel());
+ if (ppChannel == nullptr)
+ continue;
+
+ auto nd2 = ppChannel->GetDevice(0);
+ if (nd2->GetNode() == n)
+ nd2 = ppChannel->GetDevice(1);
+
+ std::cout << " NextHop: " << nd2->GetNode()->GetId() << ", cost: " << nh.getCost() << "\n";
+ }
+ std::cout << "\n";
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ bool grid = false; // Use grid topology?
+ std::string routing = "lfid";
+ CommandLine cmd;
+ cmd.AddValue("grid", "use grid topology (instead of abilene)", grid);
+ cmd.AddValue("routing", "which route computation to use (lfid, sp, allroutes)", routing);
+ cmd.Parse(argc, argv);
+
+ std::string topoName = "abilene";
+ if (grid) {
+ topoName = "grid";
+ }
+
+ std::cout << "Using " << topoName << " topology\n\n";
+
+ AnnotatedTopologyReader topologyReader{};
+ topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-" + topoName + ".txt");
+ topologyReader.Read();
+
+ ndn::StackHelper stackHelper{};
+ stackHelper.InstallAll();
+
+ // IMPORTANT: Has to be run after StackHelper!
+ topologyReader.ApplyOspfMetric();
+
+ const std::string prefix{"/prefix"};
+
+ Ptr<Node> consumerN = Names::Find<Node>("router0");
+ Ptr<Node> producerN = Names::Find<Node>("producer");
+ NS_ABORT_MSG_UNLESS(consumerN && producerN, "consumer or producer name does not exist in topo file!");
+
+ ndn::GlobalRoutingHelper routingHelper;
+ routingHelper.InstallAll(); // Fills GlobalRouter with incidencies.
+ routingHelper.AddOrigin(prefix, producerN);
+
+ if (routing == "lfid") {
+ routingHelper.CalculateLfidRoutes();
+ }
+ else if (routing == "sp") {
+ routingHelper.CalculateRoutes();
+ }
+ else if (routing == "allroutes") {
+ routingHelper.CalculateAllPossibleRoutes();
+ }
+ else {
+ NS_FATAL_ERROR("Unknown route calculation! Use --routing {lfid|sp|allroutes}");
+ }
+
+ // IMPORTANT: Some strategy needs to be installed for displayRoutes() to work.
+ ndn::StrategyChoiceHelper strategyHelper;
+ strategyHelper.InstallAll<nfd::fw::BestRouteStrategy2>("/");
+
+ // TODO: Needs RandomStrategy for test to work!
+ // Uncomment after NFD version has been updated.
+ // strategyHelper.InstallAll<nfd::fw::RandomStrategy>("/");
+
+ displayRoutes(topologyReader.GetNodes(), prefix);
+
+ // Installing applications
+ ndn::AppHelper consumerHelperX{"ns3::ndn::ConsumerCbr"};
+ consumerHelperX.SetPrefix(prefix);
+ consumerHelperX.SetAttribute("Frequency", DoubleValue(100.0));
+ consumerHelperX.Install(consumerN);
+
+ ndn::AppHelper producerHelper0{"ns3::ndn::Producer"};
+ producerHelper0.SetPrefix(prefix);
+ producerHelper0.Install(producerN);
+
+ Simulator::Stop(Seconds(30));
+ Simulator::Run();
+ Simulator::Destroy();
+
+ return 0;
+}
+
+} // namespace ns3
+
+int
+main(int argc, char* argv[])
+{
+ return ns3::main(argc, argv);
+}