概述
快乐虾
http://blog.csdn.net/lights_joy/
欢迎转载,但请保留作者信息
NS3支持实时仿真,且可以将NS3模拟生成的数据包通过主机上真实的网卡发送出去,本节尝试运行NS3中自带的fd-emu-ping示例,使用NS3模拟一台设备,再通过主机上的网口ping一台网络上的真实设备。
// Allow ns-3 to ping a real host somewhere, using emulation mode
//
//
+----------------------+
//
|
host
|
//
+----------------------+
//
|
ns-3 simulation
|
//
+----------------------+
//
|
ns-3 Node
|
//
|
+----------------+
|
//
|
|
ns-3 TCP
|
|
//
|
+----------------+
|
//
|
|
ns-3 IPv4
|
|
//
|
+----------------+
|
//
|
|
FdNetDevice
|
|
//
|--+----------------+--+
//
|
| eth0 |
|
//
|
+------+
|
//
|
|
|
//
+----------|-----------+
//
|
//
|
+---------+
//
.---------| GW host |--- (Internet) -----
//
+---------+
这个模型很清楚地表达了NS3实现这个功能的层次结构。
NS3最后的实际收发包操作是由FdNetDevice这个类来完成的,其实现方式为raw socket,但在windows下,raw socket只支持ip层以上的包收发,而不支持mac层数据的收发,因此NS3的代码无法直接在windows下使用。
观察FdNetDevice完成的操作可以发现,它只需要将NS3生成的包发送出去,再将收到的包通过下面的函数扔给NS3就可以了:
FdNetDevice::ReceiveCallback (uint8_t*buf, size_t len)
因此我们引入winpcap库完成收发包的操作,放弃rawsocket方式。
首先在StartDevice时创建winpcap的接收线程:
void
FdNetDevice::StartDevice (void)
{
......
if (m_fd < 1000)
{
m_fdReader = Create<FdNetDeviceFdReader>();
// 22 bytes covers 14 bytes Ethernet header with possible 8 bytes LLC/SNAP
m_fdReader->SetBufferSize(m_mtu + 22);
m_fdReader->Start(m_fd, MakeCallback(&FdNetDevice::ReceiveCallback, this));
}
else
{
// use pcap
pcap_t* ph = (pcap_t*)m_fd;
m_hPcapThread = CreateThread(NULL, 65536, PcapThread, this, 0, NULL);
}
}
在此接收线程中循环调用pcap的接收函数:
DWORD WINAPI FdNetDevice::PcapThread(_In_
LPVOID lpParameter)
{
FdNetDevice* pDev = (FdNetDevice*)lpParameter;
pDev->m_bPcapRun = true;
pcap_t* pc = (pcap_t*)pDev->m_fd;
while (pDev->m_bPcapRun)
{
pcap_dispatch(pc, 1, (pcap_handler)packet_handler, (u_char*)pDev);
}
return 0;
}
然后在收到数据包后调用ReceiveCallback就可以了:
/* Callback function invoked by libpcap for every incoming packet */
void FdNetDevice::packet_handler(void *_param, const void *_header, const void *_pkt_data)
{
const struct pcap_pkthdr *header = (const struct pcap_pkthdr *)_header;
FdNetDevice* dev = (FdNetDevice*)_param;
uint8_t* pkt = (uint8_t*)malloc(header->len);
memcpy(pkt, _pkt_data, header->len);
dev->ReceiveCallback(pkt, header->len);
}
当有数据包需要发送的时候,相应地改用pcap发送:
bool
FdNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
{
.....
size_t written = 0;
if (m_fd < 1000)
written = cyg_write(m_fd, buffer, len);
else
{
pcap_t* ph = (pcap_t*)m_fd;
pcap_sendpacket(ph, buffer, len);
written = len;
}
......
return true;
}
貌似很简单的样子。
当我们在Linux下运行此示例时使用的是eth0这样的网络名称,在windows下我们需要使用一长串的名称,不过这个名称很容易用winpcap获取:
再修改一下目标机的IP,运行示例:
轻松搞定!!!
最后
以上就是大方画笔为你收集整理的NS3网络仿真(8): 实时仿真的全部内容,希望文章能够帮你解决NS3网络仿真(8): 实时仿真所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复