根据官网的文档(https://ndnsim.net/current/getting-started.html#)说明,仿真场景文件(即自己的代码)有三种运行方式:
第一种
将代码直接写在NS-3目录下的 scratch/ 文件夹中cc后缀的脚本文件中。
这里以 ndn-simple.cpp 中的代码为例,如何编写代码请参考:ndnSIM 如何进行仿真实验 仿真步骤-优快云博客
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ndnSIM-module.h"
namespace ns3 {
int
main(int argc, char* argv[])
{
// setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
NodeContainer nodes;
nodes.Create(3);
// Connecting nodes using two links
PointToPointHelper p2p;
p2p.Install(nodes.Get(0), nodes.Get(1));
p2p.Install(nodes.Get(1), nodes.Get(2));
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// Choosing forwarding strategy
ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/multicast");
// Installing applications
// Consumer
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
// Consumer will request /prefix/0, /prefix/1, ...
consumerHelper.SetPrefix("/prefix");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 10 interests a second
auto apps = consumerHelper.Install(nodes.Get(0)); // first node
apps.Stop(Seconds(10.0)); // stop the consumer app at 10 seconds mark
// Producer
ndn::AppHelper producerHelper("ns3::ndn::Producer");
// Producer will reply to all requests starting with /prefix
producerHelper.SetPrefix("/prefix");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(nodes.Get(2)); // last node
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
我们将其命名保存为 mytest.cc 放在 ns-3 / scratch / 文件夹中。
然后重新编译运行:
./waf
等待将自己的代码编译完成后,运行自己的代码:
./waf --run mytest
可以看到运行成功。
当然,也可以直接运行,当发现脚本没有编译时会自动重新编译后运行,一步到位。(当然这种简单方法也是后来才发现的。。。)
./waf --run mytest
# or
./waf --run mytest --vis
第二种
将代码写在NS-3目录下的 src / ndnSIM / examples 文件夹中,命名为 .cpp 文件。
同样以 ndn-simple.cpp 中的代码为例,如何编写代码请参考:ndnSIM 如何进行仿真实验 仿真步骤-优快云博客
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/ndnSIM-module.h"
namespace ns3 {
int
main(int argc, char* argv[])
{
// setting default parameters for PointToPoint links and channels
Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
// Read optional command-line parameters (e.g., enable visualizer with ./waf --run=<> --visualize
CommandLine cmd;
cmd.Parse(argc, argv);
// Creating nodes
NodeContainer nodes;
nodes.Create(3);
// Connecting nodes using two links
PointToPointHelper p2p;
p2p.Install(nodes.Get(0), nodes.Get(1));
p2p.Install(nodes.Get(1), nodes.Get(2));
// Install NDN stack on all nodes
ndn::StackHelper ndnHelper;
ndnHelper.SetDefaultRoutes(true);
ndnHelper.InstallAll();
// Choosing forwarding strategy
ndn::StrategyChoiceHelper::InstallAll("/prefix", "/localhost/nfd/strategy/multicast");
// Installing applications
// Consumer
ndn::AppHelper consumerHelper("ns3::ndn::ConsumerCbr");
// Consumer will request /prefix/0, /prefix/1, ...
consumerHelper.SetPrefix("/prefix");
consumerHelper.SetAttribute("Frequency", StringValue("10")); // 10 interests a second
auto apps = consumerHelper.Install(nodes.Get(0)); // first node
apps.Stop(Seconds(10.0)); // stop the consumer app at 10 seconds mark
// Producer
ndn::AppHelper producerHelper("ns3::ndn::Producer");
// Producer will reply to all requests starting with /prefix
producerHelper.SetPrefix("/prefix");
producerHelper.SetAttribute("PayloadSize", StringValue("1024"));
producerHelper.Install(nodes.Get(2)); // last node
Simulator::Stop(Seconds(20.0));
Simulator::Run();
Simulator::Destroy();
return 0;
}
} // namespace ns3
int
main(int argc, char* argv[])
{
return ns3::main(argc, argv);
}
我们将其命名保存为 mytest2.cpp 放在 ns-3 / src / ndnSIM / examples 文件夹中。
创建文件的过程就不细说了,同样可以先编译再运行或者直接运行(这里的编译也会只编译这一个文件,因为其他的库文件和示例代码之前已经编译过了,每次都只编译增量)。修改过也需要重新编译。
./waf --run mytest2
# or
./waf --run mytest2 --vis
我没有试过第一种和第二种重名都使用的情况,毕竟只是为了做实验,会用就行,有结果的同学评论区见!
第三种
由于上述两种情况将使用者自己编写的代码和运行框架的src源码混合在了一起,不利于开发。因此,官网推荐的一种方式是在独立于NS-3或ndnSIM的独立存储库中编写模拟方案。同时提供了模板来编写扩展,模拟方案和度量标准处理脚本:https://github.com/cawka/ndnSIM-scenario-template
这种方法将代码写在了和 ns-3、ndnSIM都不相关的仓库(repository)里。,也可以直接运行,但是需要进行额外的安装过程,执行一些命令。同时,相比之下,这种方式只对使用者编写的代码进行编译和链接,能够大大提高运行仿真的速度(大概能快十倍左右)。在提高编译速度的同时,这种方式也能很好地区分代码是自己写的还是模拟器自带的,所以官网上推荐是使用独立的库来编写自己的仿真场景。
具体的实现过程可以参考教程:ndnSIM 如何使用 scenario 模板 进行 真实场景仿真-优快云博客
注意事项
代码文件(无论cc还是cpp)名字是什么就run什么,去除后缀后的文件名称就是仿真名称。
NDN科研工作者,长期研究,欢迎讨论交流与合作!