【网络仿真】ns-3与物理网络连接

实验目的:在ns-3中ping通指定域名的网站。

step1 运行脚本src/fd-net-device/examples/fd-tap-ping.cc

脚本功能:使用主机上的ns-3仿真模型和节点,ping远程主机。
脚本拓扑:

//
//   +-------------------------------------+    
//   |                host                 |
//   +-------------------------------------+    
//   |    ns-3 simulation   |              |                       
//   +----------------------+              |    
//   |       ns-3 Node      |              |   
//   |  +----------------+  |              |   
//   |  |    ns-3 TCP    |  |              |   
//   |  +----------------+  |              |   
//   |  |    ns-3 IPv4   |  |              |   
//   |  +----------------+  |              |   
//   |  |   FdNetDevice  |  |              |  
//   |--+----------------+--+    +------+  |
//   |       | TAP  |            | eth0 |  | 
//   |       +------+            +------+  |
//   |       1.2.3.4                 |     |
//   +-------------------------------|-----+ 
//                                   |
//                                   |                             +-------------+
//                                   ------------ (Internet) ----- | Remote host |                            
//                                                                 +-------------+
//
  1. 脚本配置

设置TAP设备和ns-3 FdNetDevice的网络地址(ns-3会为物理本主机创建TAP设备)

std::string network ("192.168.6.0");

请添加图片描述

  1. 主机配置
    为了使本地主机可以将仿真器生成的数据发送到网络中,对于Linux操作系统需要配置文件ip_forward内容为1(该文件内容为0,表示禁止数据包转发,1表示允许,将其修改为1)
    使用命令:
echo 1 > /proc/sys/net/ipv4/ip_forward

查看配置:
请添加图片描述
为了使远程主机的ICMP可以应答本地的TAP设备,需要开启natting。
输入命令:

iptables -t nat -A POSTROUTING -s 192.168.6.0/255.255.255.0 -j MASQUERADE
# iptables -t nat -A POSTROUTING -s <TAP-network-address>/<TAP-network-mask> -j MASQUERADE
# 注意这里设置是网络本身的地址,不是具体地址
  1. 配置仿真器权限
    运行脚本前,确保tap创建器的二进制文件有root suid。
    执行如下命令:
./waf --enable-sudo
# 或
chown root.root build/src/fd-net-device/ns3-dev-tap-device-creator # 设置文件拥有者
sudo chmod 4755 build/src/fd-net-device/ns3-dev-tap-device-creator # 设置文件权限

请添加图片描述

  1. 执行脚本
./waf --run fd-tap-ping
# ./waf --run fd-tap-ping --command-template="%s --tapNetwork=<TAP-network-address> --tapMask=<TAP-network-mask>" 

结果:
请添加图片描述

step2 配置ns-3地址解析功能

由于ns-3不支持DNS解析,上一步使用的是www.qhnu.edu.cn的IP地址210.27.146.81。(查询方法:http://www.seocha.net/ip_address/)
因此,需要一个函数,类似于DNS功能,输入域名,输出IP地址。

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>

/*
作用:将网络地址转化为IP
参数:ipbuf是输出缓冲区, host是要转化的域名, maxlen是缓冲区大小
返回值:返回-1是失败,0是成功
*/
int get_ip_from_host(char *ipbuf, const char *host, int maxlen)
{
	struct sockaddr_in sa;
	sa.sin_family = AF_INET;
	if (inet_aton(host, &sa.sin_addr) == 0) 
	{
		struct hostent *he;
		he = gethostbyname(host);
		if (he == NULL)
			return -1;
		memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
	}
	strncpy(ipbuf, inet_ntoa(sa.sin_addr), maxlen);
	return 0;
}

//测试例子
int
main (int argc, char *argv[])
{
  	char ipbuf[128];
	get_ip_from_host(ipbuf, "www.baidu.com", 128);
	printf("ip: %s\n", ipbuf);
	return 0;
}


运行:

./waf --run testip.cc

step3 整合

./waf --run "test-ping --remote=ibdl.pku.edu.cn" 

请添加图片描述
完整代码:

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * 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
 * 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
 */

// Allow ns-3 to ping a real host somewhere, using emulation mode and ping
// the simulated node from the host.
//
//   +-------------------------------------+    
//   |                host                 |
//   +-------------------------------------+    
//   |    ns-3 simulation   |              |                       
//   +----------------------+              |    
//   |       ns-3 Node      |              |   
//   |  +----------------+  |              |   
//   |  |    ns-3 TCP    |  |              |   
//   |  +----------------+  |              |   
//   |  |    ns-3 IPv4   |  |              |   
//   |  +----------------+  |              |   
//   |  |   FdNetDevice  |  |              |  
//   |--+----------------+--+    +------+  |
//   |       | TAP  |            | eth0 |  | 
//   |       +------+            +------+  |
//   |       1.2.3.4                 |     |
//   +-------------------------------|-----+ 
//                                   |
//                                   |                             +-------------+
//                                   ------------ (Internet) ----- | Remote host |                            
//                                                                 +-------------+
//
// To use this example:
//  1) ns-3 will create the TAP device for you in the host machine.
//     For this you need to provide the network address to allocate IP addresses
//     for the TAP device and the ns-3 FdNetDevice.
//
//  2) Take into consideration that this experiment requires the host to be able
//     to forward traffic generated by the simulation to the Internet.
//     So for Linux systems, make sure to configure:
//     # echo 1 > /proc/sys/net/ipv4/ip_forward
//
//     Also enable natting so the ICMP replies from the remote host can reach 
//     back the TAP. 
//     - TAP-network-address is the same as 'tapNetwork'
//     - TAP-network-mask is the same as 'tapMask'
//     # iptables -t nat -A POSTROUTING -s <TAP-network-address>/<TAP-network-mask> -j MASQUERADE
//
//  3) Before running the example make sure that the tap creator binary has root suid.
//     If the --enable-sudo option was used to configure ns-3 with waf, then the following
//     step will not be necessary.
//
//     # chown root.root build/src/fd-net-device/ns3-dev-tap-device-creator
//     # sudo chmod 4755 build/src/fd-net-device/ns3-dev-tap-device-creator
//
//  4)  The example can be executed as follows using waf:
//  
//     ./waf --run fd-tap-ping --command-template="%s --tapNetwork=<TAP-network-address> --tapMask=<TAP-network-mask>" 
//
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>

#include "ns3/abort.h"
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/network-module.h"
#include "ns3/fd-net-device-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/ipv4-static-routing-helper.h"
#include "ns3/ipv4-list-routing-helper.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("TAPPingExample");

static void
PingRtt (std::string context, Time rtt)
{
  NS_LOG_UNCOND ("Received Response with RTT = " << rtt);
}

/*
作用:将网络地址转化为IP
参数:ipbuf是输出缓冲区, host是要转化的域名, maxlen是缓冲区大小
返回值:返回-1是失败,0是成功
*/

int get_ip_from_host(char *ipbuf, const char *host, int maxlen)
{
	struct sockaddr_in sa;
	sa.sin_family = AF_INET;
	if (inet_aton(host, &sa.sin_addr) == 0) 
	{
		struct hostent *he;
		he = gethostbyname(host);
		if (he == NULL)
			return -1;
		memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
	}
	strncpy(ipbuf, inet_ntoa(sa.sin_addr), maxlen);
	return 0;
}

int
main (int argc, char *argv[])
{
  NS_LOG_INFO ("Ping Emulation Example with TAP");

  std::string deviceName ("tap0");

  char remote[128];
  
  char remote_domain_name[128] = ("www.qhnu.edu.cn");
  std::string network ("192.168.6.0");
  std::string mask ("255.255.255.0");
  std::string pi ("no");

  //
  // Allow the user to override any of the defaults at run-time, via
  // command-line arguments
  //
  CommandLine cmd (__FILE__);
  cmd.AddValue ("deviceName", "Device name", deviceName);
  // cmd.AddValue ("remote", "Remote IP address (dotted decimal only please)", remote);
  cmd.AddValue ("remote", "Remote domain name", remote_domain_name);
  cmd.AddValue ("tapNetwork", "Network address to assign the TAP device IP address (dotted decimal only please)", network);
  cmd.AddValue ("tapMask", "Network mask for configure the TAP device (dotted decimal only please)", mask);
  cmd.AddValue ("modePi", "If 'yes' a PI header will be added to the traffic traversing the device(flag IFF_NOPI will be unset).", pi);
  cmd.Parse (argc, argv);

  NS_ABORT_MSG_IF (network == "1.2.3.4", "You must change the local IP address before running this example");
  get_ip_from_host(remote, remote_domain_name, 128);
  // Ipv4Address remoteIp (remote.c_str ());
  Ipv4Address remoteIp (remote);
  Ipv4Address tapNetwork (network.c_str ());
  Ipv4Mask tapMask (mask.c_str ());

  bool modePi = ( pi == "yes" ? true : false);

  //
  // Since we are using a real piece of hardware we need to use the realtime
  // simulator.
  //
  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));

  //
  // Since we are going to be talking to real-world machines, we need to enable
  // calculation of checksums in our protocols.
  //
  GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));

  //
  // In such a simple topology, the use of the helper API can be a hindrance
  // so we drop down into the low level API and do it manually.
  //
  // First we need a single node.
  //
  NS_LOG_INFO ("Create Node");
  Ptr<Node> node = CreateObject<Node> ();

  // Create an fd device, set a MAC address and point the device to the
  // Linux device name.  The device needs a transmit queueing discipline so
  // create a droptail queue and give it to the device.  Finally, "install"
  // the device into the node.
  //
  Ipv4AddressHelper addresses;
  addresses.SetBase (tapNetwork, tapMask);
  Ipv4Address tapIp = addresses.NewAddress ();

  NS_LOG_INFO ("Create Device");
  TapFdNetDeviceHelper helper;
  helper.SetDeviceName (deviceName);
  helper.SetModePi (modePi);
  helper.SetTapIpv4Address (tapIp);
  helper.SetTapIpv4Mask (tapMask);

  NetDeviceContainer devices = helper.Install (node);
  Ptr<NetDevice> device = devices.Get (0);

  //
  // Add a default internet stack to the node (ARP, IPv4, ICMP, UDP and TCP).
  //
  NS_LOG_INFO ("Add Internet Stack");
  InternetStackHelper internetStackHelper;
  internetStackHelper.Install (node);

  //
  // Add an address to the ns-3 device in the same network than one
  // assigned to the TAP.
  //
  NS_LOG_INFO ("Create IPv4 Interface");
  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
  uint32_t interface = ipv4->AddInterface (device);
  Ipv4Address devIp = addresses.NewAddress ();
  Ipv4InterfaceAddress address = Ipv4InterfaceAddress (devIp, tapMask);
  ipv4->AddAddress (interface, address);
  ipv4->SetMetric (interface, 1);
  ipv4->SetUp (interface);

  //
  // Add a route to the ns-3 device so it can reach the outside world though the
  // TAP.
  //
  Ipv4StaticRoutingHelper ipv4RoutingHelper;
  Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4);
  staticRouting->SetDefaultRoute (tapIp, interface);

  //
  // Create the ping application.  This application knows how to send
  // ICMP echo requests.  Setting up the packet sink manually is a bit
  // of a hassle and since there is no law that says we cannot mix the
  // helper API with the low level API, let's just use the helper.
  //
  NS_LOG_INFO ("Create V4Ping Appliation");
  Ptr<V4Ping> app = CreateObject<V4Ping> ();
  app->SetAttribute ("Remote", Ipv4AddressValue (remoteIp));
  app->SetAttribute ("Verbose", BooleanValue (true) );
  node->AddApplication (app);
  app->SetStartTime (Seconds (1.0));
  app->SetStopTime (Seconds (21.0));

  //
  // Give the application a name.  This makes life much easier when constructing
  // config paths.
  //
  Names::Add ("app", app);

  //
  // Hook a trace to print something when the response comes back.
  //
  Config::Connect ("/Names/app/Rtt", MakeCallback (&PingRtt));

  //
  // Enable a promiscuous pcap trace to see what is coming and going on our device.
  //
  helper.EnablePcap ("fd-tap-ping", device, true);

  //
  // Now, do the actual emulation.
  //
  NS_LOG_INFO ("Run Emulation.");
  Simulator::Stop (Seconds (25.0));
  Simulator::Run ();
  Simulator::Destroy ();
  NS_LOG_INFO ("Done.");
}


运行结果:
请添加图片描述
请添加图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值