第1章 概述

1.1 什么是ns-3

ns-3(network simulator)是一款由C++语言编写的开源项目,主要运行平台是GUN/Linux(如CentOS、Ubuntu、Fedora等)。虽然Windows用户也可使用Cygwin或Visual Studio运行ns-3,但不能使用某些功能(如与物理网络交互)。ns-3同时也是一款自由软件。任何组织和个人均可免费下载、使用和修改ns-3源代码。

ns-3主要用于模拟计算机网络。它可以在一台计算机上模拟物理世界中各种类型和规模的网络结构。ns-3并没有一个图形用户界面。要使用其进行网络模拟,用户需要经过下载源代码、编译源代码、编写模拟脚本和运行模拟脚本4个基本步骤(在ns-3中,把用于构建虚拟网络的程序叫作模拟脚本)。从这点上讲,ns-3其实更像是一个程序库。它提供各种用于网络模拟的应用程序接口(Application Programming Interface,API)。用户在模拟脚本中调用这些API来构建自己的虚拟网络结构。目前ns-3的模拟脚本可以支持C++和Python两种程序语言。

那么ns-3是如何模拟出一个物理网络的呢?

这就要从网络的组成说起。大体来讲,一个计算机网络可以分为以下两个部分。

●由若干结点和连接这些结点的信道所组成的网络拓扑。

●运行在结点和信道中的网络协议。

首先,在ns-3模拟的虚拟网络中,网络拓扑中的结点和信道被抽象成各种C++类。结点和信道的连接操作被抽象成不同C++对象之间的关联。通过这种抽象,可以在ns-3程序中模拟出各种类型的网络拓扑,如有线网络中的点对点协议(Point to Point Protocol,PPP)与总线网络,无线网络中的无线局域网(基于IEEE 802.11系列标准)与长期演进技术(Long-Term Evolution,LTE)等。这些网络拓扑可以包含几十、几百甚至上千个网络结点。其次,对于网络协议的模拟,ns-3使用了一种名叫离散事件(Discrete Event)的模拟技术。简单地说,这种技术就是把物理世界中一个连续的过程抽象成了虚拟世界中的一系列离散的事件。这种技术使得ns-3可以非常逼真地模拟物理世界中的各种网络协议,如应用层的各种分组产生器、传输层的TCP和UDP、网络层的IPv4和IPv6协议、链路层和物理层的PPP、IEEE 802.11a/b/g/n和LTE协议等(见图1-1)。

图1-1 ns-3支持的网络协议

只能模拟物理网络还远远不够。为了帮助用户更加便捷地进行网络模拟,ns-3还提供了一系列的辅助功能。例如,trace生成功能使用户可以直接通过第三方软件(wireshark、tcpdump)对ns-3产生的数据进行分析。移动模块可以为结点自动分配起始位置和移动轨迹。此外,ns-3所构建的虚拟网络还可以与物理网络环境高度融合。一方面,ns-3中的虚拟结点可以利用物理网络收发数据;另一方面,物理结点也可利用ns-3构建的虚拟信道收发数据包。这样,用户就可以直接使用ns-3模拟大规模网络,进而对真实的网络协议代码进行测试,达到节省开发成本的目的。

至此可以看出,ns-3主要用于模拟网络拓扑和运行其中的网络协议。其关注的是协议行为。其他诸如结点内部的硬件延迟、CPU使用率等指标是不属于ns-3能力范畴的。

自2008年7月首个版本(ns-3.1)发布以来,ns-3一直保持着每年2~3个版本的发布速度[1]。截至本书完稿时,ns-3已发布至第29版本(ns-3.29)。目前,ns-3已被广泛应用在第五代移动通信(5G)、物联网、软件定义网络、数据中心等计算机网络的前沿研究领域。

1.2 Hello, world

在屏幕上输出“Hello, world”一直是各种编程语言的标准示例程序。ns-3也不例外。它自带了一个名为“hello-simulator”的C++模拟脚本,用以向屏幕上输出“Hello Simulator”字样。

先来看一下这个脚本的实际运行效果。下面的第一行代码是在Linux命令行中使用waf命令执行hello-simulator脚本(waf是ns-3项目中最常用的命令。它负责C++源代码编译和脚本运行)。第二行代码是执行结果,即在屏幕中显示“Hello Simulator”。

hello-simulator脚本的C++源代码如下。

可以看出,ns-3脚本和其他的C++程序一样,都有一个作为起始入口main函数。这里的NS_LOG_UNCOND是一个ns-3中的宏定义。它的作用就是打印括号中的字符串。此外,整个ns-3项目的源代码都受ns3名字空间保护。这样可以将ns-3项目与非ns-3项目隔离,便于与其他项目整合。

这个例子中的main函数只有一行代码。在真正的模拟脚本中,构建网络拓扑、配置参数、数据生成等操作均需要在main函数中完成。

1.3 ns-3社区

在自由软件领域,社区(community)的重要性不言而喻。一个成熟的社区环境是自由软件健康发展的必要保障。同时,社区也是开发者、用户工作、学习和交流的平台。ns-3组织并未对其社区做出任何官方定义。为了便于读者理解,编者结合ns-3文档和多年的开发经验,把ns-3社区划分为核心社区和延展社区两部分(见图1-2)。

图1-2 ns-3社区组成

核心社区包括围绕ns-3项目本身的一系列参与方,如ns-3用户、开发者和维护者等。延展社区是ns-3项目的外延,包括与ns-3紧密相关的学术会议、面向学生群体的实习项目和其他一些ns-3的关联项目。延展社区对ns-3的普及和可持续发展至关重要。ns-3联盟(ns-3 Consortium)是由华盛顿大学和法国国家信息与自动化研究所(INRIA)于2012年10月创立的一个组织机构。它负责社区的统一规划、组织协调、资金筹集等一系列长期性战略问题,为ns-3社区的发展提供基础支持。

ns-3是一个由不同模块(model)所组成的项目。每一个模块负责实现一个重要网络功能。例如,LTE模块负责实现LTE网络协议栈。Internet模块负责实现TCP/IP协议栈。Wi-Fi模块负责实现IEEE 802.11系列协议。在核心社区中,每一个模块都有至少一名维护者。该模块的未来扩展、补丁发布、文档更新及邮件列表答疑等事项均由该维护者负责。这些维护者大多是该模块的主要开发人员。

文档系统和邮件列表系统则是用户、开发者和维护者进行问题讨论、技术交流的主要平台。

首先来看一看ns-3文档系统。它主要包含以下几部分内容[1]

●ns-3 tutorial:ns-3的基本概念和使用方法。适合地毯式阅读以了解基本概念。

●ns-3 manual:深入讲解ns-3的架构、设计原理和ns-3核心模块中的主要技术细节。适合想进一步了解ns-3原理的读者。

●Model library:由各个模块的开发者编写而成的文档,分别讲解每个模块的背景知识、设计架构以及使用方法。适合在编写某一模块的脚本或二次开发时使用。

●Doxygen:从源代码中生成的在线文档。用户可以在Doxygen网页中浏览源代码、查询ns-3中C++类、函数和变量的定义,了解类与类之间的继承关系等程序细节信息。Doxygen是一个很好的工具网站,在编写模拟脚本和进行扩展开发的过程中非常有用。

●ns-3 wiki主页:安装指南、代码提交流程、版本发布等辅助性信息[2]。ns-3 wiki主页同时也维护着一些没有整合入主程序的模块与补丁。读者可以从中查找自己所需的相关代码,避免重复工作。

如果在这些文档中无法找到解决方案,则读者可以尝试在邮件列表发问。

ns-3社区成员遍布世界各地。人们主要通过邮件列表沟通交流。这也是很多自由软件项目所常用的方式。ns-3社区中使用频率最高的邮件列表有两个:Google ns-3用户组和ns-3开发者邮件列表[3]。前者是用户就ns-3安装、脚本编写、模块原理等使用问题进行咨询、讨论的平台。用户组里经常有各个模块的维护者对相关问题进行答疑。后者则是开发者交流意见的主战场。开发者们在此会探讨一些新功能的实现、新版本发布、bug修改等技术问题。这里需要特别提醒读者的是,在邮件列表发送邮件之前一定要先做好自己的功课,确保查阅文档、wiki主页和搜索邮件列表历史都没有得到满意的答案之后再发问。这也是每一个自由软件人的基本素质体现。

再来看看ns-3延展社区。

首先是学术会议。与ns-3直接相关的学术会议主要有两个:ns-3研讨会(ns-3 workshop)和EAI Simutools。这两个会议中的论文往往涉及一些ns-3的新功能。此外,ns-3研讨会每年还会提供培训课程[4]。这些课程涉及范围很广,从基本概念到新扩展,且往往配有视频和幻灯片,与ns-3文档形成很好的互补。

其次是夏季项目。ns-3的夏季项目主要面向擅长程序设计的学生群体,意在培养未来潜在的开发者。ns-3夏季项目主要有以下3个。

●Google编程之夏(Google Summer of Code):Google公司主办的年度带薪程序设计项目[5]

●欧洲航天局太空编程之夏(Summer of Code in Space):欧洲航天局举办的面向航天航空领域的年度带薪程序设计项目[6]

●夏季指导项目(Mentored Summer Projects):ns-3组织自己推出的不带薪指导项目。主要针对没有入选前两个编程之夏项目,但仍有意愿为ns-3社区贡献代码的学生[7]

参与这3个项目的学生会在ns-3资深开发人员的指导下完成指定课题。今天很多ns-3模块最初就是从这些夏季编程项目衍生而来的。编程之夏对ns-3的后续发展帮助很大。对此感兴趣的朋友可以跟踪编者维护的“编程之夏”微信公众号(微信号:codesummer,二维码见本书勒口。)。编者在2.9节还会对这一项目做更为详细的介绍。

最后是关联项目。ns-3关联项目分为两类:由ns-3组织维护和由外部机构维护。由ns-3组织维护的关联项目有以下几个。

●Direct Code Execution:一个能够让Linux协议直接运行在ns-3中的软件框架。

●Netanim:一款能够以动画显示模拟过程的软件。

●Bake:一个方便用户一次性安装多个ns-3关联项目的工具程序。

此外,也有很多ns-3项目由外部机构开发[8]。比较著名的有西班牙CTTC研究所开发的LTE模拟器[9]和芬兰Magister Solution公司开发的卫星通信模拟器SNS3[10]等。由于ns-3主程序库有严格的测试程序,因此这些项目目前尚未或仅部分并入ns-3发行版。但其均与ns-3社区保持有密切联系。附录B列举了几个开发状态比较活跃、且符合目前计算机网络研究热点的第三方ns-3项目。

1.4 ns-3简史

ns系列共有3款模拟器:ns-1、ns-2和ns-3。ns-2向前兼容ns-1。而ns-3则是一款全新的模拟器,不向前兼容。尽管如此,ns-3和其前身依然有着深厚的历史渊源。

ns-3的历史最早可追溯至1988年发布的REAL模拟器[11]。该模拟器由当时还在加州大学伯克利分校攻读博士的Srinivasan Keshav编写。20世纪90年代中期,REAL被拓展成为ns-1。1996年,ns-1的tcl代码被OTcl语言代替,进而演化成ns-2模拟器[12]。此后的10年间,计算机网络技术突飞猛进,ns-2也迎来了黄金的发展期。先后有美国国防高级研究计划局(DARPA)、南加州大学信息科学研究所(USC/ISI)等多所大型研究机构参与到ns-2项目的开发中来。

但是,随着时间的推移,ns-2软件架构中的一些问题也逐渐暴露出来,如其缺乏对真实数据包和多接口结点的支持、不友好的网络结点IP地址设计、C++和OTcl分离式对象模型的性能问题和整个ns-2项目分支过多导致的碎片化等。2005年2月22日,华盛顿大学的Tom Henderson(本书序的作者)在ns-2开发者邮件列表中发表了标题为“new ns-2 development discussion on this list”的帖子[13],意在讨论ns-2的未来发展。讨论中Tom所列出的一些重要议题对日后ns-3的定位产生了深远影响。这些议题包含以下几个重要条目。

●重新审视网络结点的软件架构。

●更好地与其他开源软件(如Ethereal,即现在的Wiredshark)整合。

●更好的可扩展性,如重新审视ns-2的分离式对象模型。

●IPv6支持。

●让用户在纯模拟、虚拟实验床和物理网络之间灵活迁移。

●更容易让学生使用。

今天,这些议题很多已经在ns-3中实现。此后,从2005年2月至2006年7月,关于ns-3项目的前期讨论就一直在ns-2邮件列表进行着。除了Tom,当时还在法国尼斯大学攻读博士学位的Mathieu Lacage是这些讨论中的另一个关键人物。Mathieu当时正在基于ns-2实现一个802.11模块。因为不满于ns-2的某些架构设计(如网络结点地址),他于2006年1月发布了一个叫作Yans的模拟器。Yans拥有全新设计的内核,完全用C++实现,并放弃了ns-2中分离式的对象模型。Yans的设计理念和Tom早先提出的议题不谋而合。

两股力量聚合在一起。2006年7月3日,Tom在ns-2邮件列表宣布ns-3项目正式成立。ns-3重用了部分Yans的代码。Mathieu成为ns-3早期开发者之一。有趣的是,ns-3项目正式发布后立即引来了广泛的讨论。这些讨论既包括使用Java还是C++、是否向前兼容ns-2等这类基础性问题,也包括文档系统生成工具、脚本语言选择等全新功能的讨论。这些讨论促进了ns-3项目的进一步完善。

2008年7月,ns-3首个正式版本发布(ns-3.1)。到2018年11月为止,10年时间,ns-3已连续发布29个版本。而ns-2目前则基本处于维护状态,其最新版本至今还停留在2011年发布的ns-2.35。今天,ns-2开发者邮件列表继续被ns-3组织所使用着,只不过已鲜有与ns-2相关的讨论。

1.5 写作习惯

为了避免阅读时的混淆,这一小节列举了本书在写作用词方面的一些习惯。

1.文档英文

为了便于读者查阅文档,本书对manual、tutorial和model library三个文档名不进行翻译。

2.函数表示

函数的表示形式是“函数名()”。函数的形参列表只有在需要特殊说明时才会添加。

3.分组名称

分组(packet)在不同的协议层有不同的叫法。例如,人们一般习惯把传输层分组称为报文(segment),把网络层分组称为数据报(datagram),把链路层分组称为帧(frame)。为了便于叙述,本书中统一使用分组这个名称。

4.默认目录

2.4节及以后所有目录、文件的默认根目录均为ns-3主目录(如ns-3.28/)。


[1] 2017年除外。