ns3使用-4
应用层:
应用层协议主要负责数据分组的发送,处理和接收。可以将其看作物理网络中应用程序的网络传输部分。
应用层协议中,分组生成部分按照一定的统计规则发送分组。分组处理部分负责接收来自下层协议的分组并对分组相关信息(分组接收时间,字节大小)进行记录。这两部分都是通过套接字实现交互。接口可以分为两类,一类是基于POSIX套接字的原语函数,如Bind(),Listen(),Recv(),Send()等,主要用于建立下层协议连接,发送和接收分组。第二类是回调函数,主要用于接收下层协议的事件通知。
ns-3支持四种套接字类型:与传输层协议交互的流套接字(stream packet),数据报文套接字(datagram socket)。与网络层协议交互的原始套接字(raw socket)和与链路层交互的Packet套接字(packet socket)
脚本中创建应用层协议实际上就是制定分组收发规则和调用套接字API这两部分操作。
1 | //创建客户端 |
ns-3中的内置应用可以分为以下两类:第一类是分组产生器,Application和network模块的应用都属于这一类。第二类是以internet-app模块为代表的具有信令交互行为的内置应用,如Ping,DHCP(动态主机配置协议),路由广播守护协议等。
CBR(Constant BitRate) 固定码率
传输层
Socket
是传输层和应用层的交互接口,类似于传输层的大脑,负责传输层的各种核心算法,比如TCP
的拥塞控制算法。IpL4Protocol
是传输层和网络层交互的接口,负责分组的实际发送。
端点是传输层通信连接的起始点。当应用层创建一个Socket
后,系统同时也在传输层创建一个与之匹配的端点对象。这个对象存储了本地和通信对端的套接字地址,一个传输层套接字地址由IP地址和端口号两部分组成。同一个节点的不同套接字,IP地址可以相同,但是端口号必须是唯一的,所以套接字地址是Socket
对象的唯一标识。
ns-3利用多路复用和分解实现分组转发功能。
多路分解:即接收分组流程。根据IP分组头中的协议号判断应该转发到哪个传输层IpL4Protocol的子类对象。接着IpL4Protocol的子类对象判断分组属于哪一个端点。这时会提取分组头部中的IP地址和端口号信息,将其和每个端点中存储的套接字地址相匹配。之后分组会被转发给与之匹配的端点,端点通过回调函数转发给Socket对象。
注意:一个IpL4Protocol的子类对象不能连接两个本地端口号相同的端点。
多路复用:即发送分组流程。Socket发送分组给IpL4Protocol时,首先提取源点对象的源目的地址和端口,然后把这些信息和负载一起发送给IpL4Protocol,IpL4Protocol为分组添加传输层分组头,并把分组发送到网络层。
注意:端点只用于分组接收,不用于分组发送。
实际上Socket是IpL4Protocol的子类,这两个类都是虚类。
传输层处理都集成在了InternetStackHelper中。
1 | InternetStackHelper Stack; |
这样就为节点安装了TCP和UDP。
TCP
ns-3实现了TCP的核心算法,支持原生TCP和Cradle TCP。前者是TCP在ns-3中的实现,后者可以让ns-3运行Linux内核中的TCP协议栈,但只支持较早版本的Linux内核。
它的Socket和IpL4Protocol子类分别是TcpSocketBase和TcpL4Protocol
默认配置下,TcpSocketBase实现以New Reno拥塞控制算法为基础,结合使用选择性应答(SACK)和窗口扩大等选项的TCP协议。
TCP拥塞控制算法之NewReno和SACK - 爱码网 (likecs.com)
TCP的属性和变量主要集中在3个核心类中:
- TcpSocket:定义了一些基本的TCP属性。
- TcpSocketBase:窗口管理,拥塞控制等主要TCP算法。
- TcpL4Protocol,与网络层的接口,也负责创建TcpSocketBase。
1. 关键属性:
SocketType:不同场景对应的不同的TCP拥塞控制算法,ns3::TcpL4Protocol/SocketType
MSS:最大分组长度,ns3::TcpSocket/SegmentSize
2. 关键trace:
拥塞控制窗口大小:ns3::TcpSocketBase/CongestionWindow
1 | //回调函数 |
也可以使用TcpSocketBase的分组发送和接收trace变量。
TCP分组头结构由TcpHeader类定义,使用TcpHeader::Print()可以打印除校验位之外的所有TCP分组头信息。
TCP的两个重要窗口:发送端的拥塞窗口和接收端的接收窗口。前者用于防止网络拥堵,后者反应结点接收分组的能力(流量控制)。
接收窗口:直接相关的参数为ns3::TcpSocketBase/AdvWND和ns3::TcpSocketBase/RWND,ns3::TcpSocketBase/RevBufSize可以模拟终端的最大接受缓存。
- AdvWND表示接收端实际可以接受的最大字节数,
- RWND表示发送端从ACK消息中获取的接收端接收窗口。
拥塞窗口:可以由ns3::TcpSocketBase/CongestionWindow trace变量获得。由两部分组成:已发出但未收到ACK的分组(可以由ns3::TcpSocketBase/BytesInFlight trace获取);另一部分是可以发送但尚未发送的总字节大小。
拥塞控制主要包括慢启动,拥塞避免,快速重传和快速恢复这几种算法。
TCP的拥塞控制算法:慢启动、拥塞避免、快重传、快恢复_咖啡与乌龙的博客-CSDN博客_tcp慢启动和拥塞避免
当出现没有收到ACK时(RTO超时)会重发分组,将RTO超时时间加倍,把拥塞窗口设为1*MSS,重新进入慢启动阶段。
UDP
UDP相较TCP支持广播和多播,其主要属性和trace如下:
- ns3::UdpSocket/RcvBufSize属性:接收端缓存,单位是B。没有发送端缓存,传输层从应用层接收后直接发给IP。
- ns3::UdpSocketImpl/Drop trace变量:分组丢失trace。当接收端缓存满了之后,就会丢失新接收的UDP分组。
UDP分组头结构由UDPHeader类定义,使用UDPHeader::Print()可以打印除校验位之外的所有UDP分组头信息。
网络层
传输层提供的是端到端服务。在实际传输中,不同结点间的通信路径上往往存在着多个中间结点(路由器,交换机,无线基站等)
ns3网络层的主要基类如下:
- Ipv4:定义了IPV4协议的接口函数。
- Ipv4L3Protocol:定义了IPv4协议的主要算法。
- Ipv4Interface:网络层和链路层交互的媒介,每一个NetDevice都对应唯一的Ipv4Interface对象,Ipv4Interface内部保存着所属NetDevice的一个或多个IP地址。必要时Ipv4Interface还可以通过ARP协议获取目标节点的链路层地址。
- Ipv4RoutingProtocol:Ipv4路由协议的基类,ns-3中的各种路由都是它的子类。
下行分组:Ipv4L3Protocol获取下一跳IP地址,确定将分组发送到哪一个Ipv4Interface对象。Ipv4Interface会检查NetDevice接口状态,如果接口可用会直接把分组转发给NetDevice对象。必要时Ipv4Interface还可以通过ARP协议获取目标节点的链路层地址。
上行分组:NetDevice通过回调函数把分组传给Node对象中的handler向量数据结构,这个结构用于确认一个分组是IPv4还是IPv6协议,从而确定将分组转发到Ipv4L3Protocol还是Ipv6L3Protocol。ns-3中新添加的网络层协议都需要在handler结构中注册,才可以正常的接收分组。最后Ipv4L3Protocol提取分组头的协议号确定将分组发送给哪一个传输层协议对象。
在脚本中,网络层的创建包括在结点中安装网络层协议栈和地址分配两部分。
安装网络层协议栈通过InternetStackHelper::Install()函数,其除了安装传输层协议架构外,还会为指定节点安装Ipv4L3Protocol和Ipv6L3Protocol协议对象,并建立他们与路由协议之间的关联。
1 | InternetStackHelper stack; |
ns-3地址分配支持手动和DHCP自动两种地址分配方式。分配地址的助手类是Ipv4AddressHelper和Ipv6AddressHelper。分配好的IP地址存在Ipv4Interface或Ipv6Interface中。
1 | Ipv4AddressHelper address; |
Ipv4AddressHelper::Assign()会按照索引顺序为容器devices中的NetDevice对象依次分配地址。
自动分配IP地址:DHCP
通过使用DhcpHelper助手类,用户可以在脚本中指定DHCPv4服务器,为安装了DHCP客户端的结点分配Ipv4地址。
图10-1没有标出流量管理层(Traffic Control layer)。TC层位于网络层和链路层之间,对于下行分组来说,其位于Ipv4Interface和Netdevice之间。对于上行分组来说,它位于node handler和Ipv4L3Protocol之间。
TC层可以通过不同队列算法控制分组的收发行为。目前只实现了对下行分组的流量控制,支持先入先出,随机早期检测,控制延时等算法。
脚本配置和trace
最常见的网络层配置是路由协议,使用OLSR路由协议(专门为Ad hoc网络设计)的实例如下:
1 | OlsrHelper olsr; |
trace
trace变量名 | 含义 |
---|---|
Tx | 成功发送IP分组 |
Rx | 成功接收IP分组 |
Drop | 丢弃IP分组 |
SendOutgoing | 成功产生IP分组 |
LocalDeliver | 成功接收IP分组 |
UnicastForward | 转发IP分组 |
发送分组trace:Tx必须成功发送到Ipv4Interface才产生trace记录。SendOutgoing只要发送就会记录trace。
接收分组trace:Rx只要从一个开启状态的接口接到分组,就产生trace,无论分组是否发往本地。LocalDeliver只记录发到本地的分组。Rx可以看作Local Deliver和UnicastForward的集合。
路由协议
每一个安装了网络层的结点都会维护一个路由表,当结点发送一个分组时,Ipv4L3Protocol对象通过查询路由表确定分组的下一跳结点地址。路由协议负责路由表项的创建,更新和维护。
路由都是Ipv4RoutingProtocol的子类。默认情况下使用的是列表路由,即可以为一个结点配置多个路由协议,并为其设置优先级,每个路由协议都维护一个路由表。
链路和物理层
有线网络
ns-3目前主要支持的有线网络底层传输协议有PPP(点对点)和CSMA(载波侦听多路访问)。PPP用于两个结点之间的点对点分组传输。CSMA用于多个结点接入的总线网络。ns-3目前只实现了两个协议中最核心的功能。
种类 | PPP | CSMA |
---|---|---|
链路层 | PointToPointNetDevice | CsmaNetDevice |
物理层 | PointToPointChannel | CsmaChannel |
助手类 | PointToPointHelper | CsmaHelper |
PPP和CSMA软件架构完全相同。
发送端,来自网络层的分组会存入一个缓冲队列。待信道可用后,发送端队列才会开始向外传输分组。
接收端,默认状态下分组会被直接转发到上层协议,但用户可以在脚本中选择配置一个错误模型,用来模拟信道中的分组丢失行为。只有错误模型判断为可以接收的分组才会被转发至上层协议。
PPP和CSMA的区别在于PPP只要信道没在传就可用。CSMA需要先载波侦听,如果信道正在传,就等待一会再重传,(退避算法),传输次数越多,等待时间越长。次数超过一定阈值,丢弃分组。
无线局域网:Wi-Fi
Wifi网络采取了模块化的设计思路。其架构如下:
- WifiNetDevice:Wifi网络设备和上层通信协议的接口。
- WifiMac:Wifi协议的MAC层实现。支持关联、探测、信标、分组重传、RTS和CTS
- RemoteStationManager:速率控制,根据网络环境选择最佳数据速率。
- WifiPhy:Wifi协议的物理层实现,支持计算发射功率、传输延时、接收功率阈值等。
- Channel:模拟Wifi信道,也属于物理层的一部分。结合传播(Propagation)和移动(Mobility)模型,计算每一个分组的接收功率,传播延时等变量。