网络层的主要功能有两个:转发和路由。按照是否预先建立连接,可以分为无连接服务模型和连接服务模型。其中无连接服务模型的代表是数据报模型。有链接的代表是虚电路网络模型。
特点是:复杂网络,简化边缘
VC模型是基于连接服务模型的,类似于传统的电话电路网络,会首先建立连接,然后依据该链接进行传输,最后在关闭该链接。其好处是数据流速的较好控制性能。如ATM(Asynchronous Transfer Mode异步传输模式)网络。
对于某次连接,VC会分配给该链接一个虚电路号VCid,该链接的数据都会携带该VCid进行传输,由每个中间点的路由器进行识别VCid并转发。值得注意的是:每段路由器间同一连接的VCid是不一样的,如下图所示。
当数据从源端到R1时,VCid为12,但是从R1到下一个路由时,VCid为22。因此,路由器除了转发数据包,还要进行的就是更换VCid。
由于目前的intel网络采用的是另一种数据报模型,因此VC在这里不做过多探讨。
特点是:简化网络,复杂边缘
目前Internet主要使用的是数据报网络。数据报网络采用的是无连接模式,每个数据包都携带由目的IP,每个路由器都会依据自身当时情况根据IP地址依次对每个数据包进行转发。因此会出现乱序的情况。由于对每个数据包都进行了IP判断,路由器需要维护一个IP地址转发表。
如上图所示,转发表实际上是采用了IP范围的方式,并且,当一个IP符合两个IP范围的时候就要选择更加精确的IP地址范围进行转发。
因为转发是基于IP范围的,因此IP的划分就显得十分重要,之后会讲解IP地址是如何划分的。
如上图所示,IP数据报主要由首部加数据组成。现在简要介绍下首部的各个数据。
版本号:4bit用于标识是IPv4还是IPv6;
首部长度:4bit,由于固定部分长度至少有5*32bit=20Byte,因此要用4bit来表示不现实,故首部长度的1各单位表示4Byte。如1000表示有8*4=32Byte。
总长度:IP数据报的总Byte数。由于只有16位,因此可以计算一个IP数据报的最大长度。
生存时间(Time To Live):由一开始的源主机设定,当经过一个路由,TTL减一,当减为零时,路由将其丢弃,并给源主机报错。
协议:上层结构的协议(TCP,UDP)代号。
首部校验和:同原来的,即求和后取反码。
拓展参考:TCP层的分段和IP层的分片之间的关系 & MTU和MSS之间的关系
由于在路由传输过程中,每个路由的传输能力不一样(用MTU最大传输单元衡量),当一个路由接到一个大于自身传输能力的IP数据报,他会将数据报分片,对每片IP数据报都加上首部(仅有第一片含有上层(TCP/UDP)的头部,其他部分没有。)。这里就用到了之前首部里面的标识,标志位和片偏移。
注意一点,路由只分不装,组装要在目的主机进行,如果目的主机没有收齐IP片,则丢弃当前保有的IP片,要求源主机进行重传。
标识:每次进行IP分片,此项加一。
标志位:有3个bit,1个保留,一个表示是否允许对该IP数据报分片,另一个表示该片是否是最后一片。
偏移量:由于位数较少,而数据报较大,因此这里的1bit代表了8Byte的数据量。
IP地址可以分为两个部分 ,一个是网络号NetID,一个是主机号HostID。在实际中,Internet采用有类编址的方式,如下图:
对第一位bit为0的我们成为A类地址,他占总IP地址量的一半。根据规定,A类地址的NetID部分为前8位bit为NetID,后24位为HostID。因此可以看出该类地址的特点是分组少,每个子网的IP数多。
B类以10开头。C类以110开头。且他们的NetID位数都不一样。C类地址的特点是分组多,每个子网的IP数少。D类IP地址第一个字节以“1110”开始 。它并不指向特定的网络,目前这一类地址被用在多点广播(Multicast)中。多点广播地址用来一次寻址一组计算机,它标识共享同一协议的一组计算机。E类IP地址保留。
从上图可以看出A类地址由于一个子网内有大量IP,因此可能存在着浪费的问题。为此我们提出了子网掩码的概念,以此进行子网的划分。
子网掩码的本质就是在某一确定子网内(NetID相同),利用向HostID借位来对子网划分。具体做法是利用了位与操作。已知1与任何数相与,可以起到保留该字段的作用。因此我们采用全1来作为子网掩码,然后将子网掩码和IP地址相与,就可以得到该IP地址属于当前子网掩码划分下哪个子网范围了。
举个例子:
如上图所示,假设已知IP地址172.32.1.112,我们可以计算出其属于B类IP地址,配合255.255.254.0的子网掩码,划分如下:
172.32.1.112 = 10101100 00100000 00000001 01110000 |------NetID----| |----HostID-----| 255.255.254.0 = 11111111 11111111 11111110 00000000 |------NetID----| |SubID||-HostID-|
可以看出经过子网掩码的求与操作,该子网IP下的NetID不变,HostID通过和子网掩码前7bit求与得以保留,可以继续划分出个分组,每组的IP数为子网掩码后面0的个数,即个。去掉HostID中全一和全零用于表示该子网和标记自身的IP,该子网实际可用的IP数为个。
因此,IP子网的划分和IP属于哪一类IP地址以及子网掩码1的个数有关。而要判断某一IP地址具体属于哪个小组,只需将其与子网掩码相与即可。
CIDR(Classless Inter-Domain Routing)无类别间域路由协议的目的是消除传统的A,B,C类IP地址的间隔。传统的IP地址需要配合子网掩码才能较好的适应子网大小的需求。为了改善这种情况,方便子网划分,出现了CIDR协议。即在原来的IP地址的基础上加上一个数字代表子网掩码全1的数量,并称之为Prefix。如下所示:172.32.1.112(255.255.254.0)可以表示为172.32.1.112/23
172.32.1.112 = 10101100 00100000 00000001 01110000 |------NetID----| |----HostID-----| 255.255.254.0 = 11111111 11111111 11111110 00000000 |---------Prefix--------||-HostID-|
这么做的好处是可以跨类组建超网如将两个C类IP组合在一起等。从而减小了路由器转发表的大小。
另一方面,如上图所示,通过合并子网,在路由器转发表中记录为上级子网的形式虽然减轻了转发表容量。但是一旦当某一个子网在另一个ISP中时(如图中的组织1),为保证不出现错误转发的情况,会将组织1的IP分组采用“或”的方式发送给上级路由转发表,因此这个时候先前讲述的最长前缀匹配优先规则就起到了作用。
即动态主机配置协议(Dynamic Host Configure Protocol)。
注意,该协议的实现是在应用层,但是由于其发挥作用于网络层,故属于网络层协议。
该协议的作用就是在一个子网内,通过设置一个DHCP服务器,提供给新加入的主机一个动态的IP地址。当新加入的主机推出Internet或者超时时收回该IP。其过程主要通过4次广播通信完成。如下图:
首先由客户机广播一条自身IP为0.0.0.0,目的地址为255.255.255.255的广播。然后DHCP server发现该广播后发出一条广播消息回复可以提供IP。接着,client继续广播请求该IP(广播意味着回绝其他提供server),server发出ACK确认消息。
网络地址转换协议,主要作用是解决IPv4的地址不够用的情况。但是其存在违反了端通信原则。因此,IPv4不够用的解决方案应该是IPv6。
原理如上图,即通过分配给路由器一个或者几个少数真实IP地址,而对于路由器下的子网统一使用内部IP地址,这些内部IP地址对外部是不可见的,因此,若想要通信,则需要通过该路由器进行IP替换(通过端口号识别,端口号由16bit,2的16次方个端口号表示内部client绰绰有余)。
由于NAT无形当中起到了隔离的作用,而对于需要穿透时,常采用3中方案:
静态配置NAT
利用uPnP
中继
ICMP
互联网控制报文协议(Internet Control Message Protocol)。
该协议用于保证在传输出错时,给端机提供差错报告。ICMP可分为两类:差错报告和网络探寻。
差错报告:
- 目的不可达(端口/IP地址不存在)
- 源抑制(在发生拥塞等情况时抑制源端机的发送速率,但在Internet中不常用)
- 超时/超期
- 参数问题
- 重定向(当路由器检测到一台机器使用非优化路由的时候,它会向该主机发送一个ICMP重定向报文,请求主机改变路由)
网络探寻报文:
- 回声请求/应答报文
- 时间戳请求/应答报文
例外情况
- 对ICMP差错报文的差错不继续发送ICMP差错报文
- 对除了第一个IP分片外的其他IP分片不发送ICMP差错报文
- 对多播地址不发送ICMP差错报文
- 对特殊IP不发送ICMP差错报文
ICMP消息格式如下:
ICMP内容如下,可以看出ICMP包含了差错IP的IP首部还有传输层的8个字节,考虑到TCP/UDP协议,这八个Byte只是TCP的端口号,但却是UDP协议的完整传输层首部信息。
前面讲解了路由器的转发规则,转发需要依据转发表,而转发表的构建则是路由器的另一个功能:路由来提供的。网络中的路由器的路由功能,可以通过人工设置,也可以通过计算产生。
要通过计算,我们很容易想到图算法里面的最短路径算法。在这里,依据是否采用全局图信息,我们把算法分为两类:链路状态(LS)路由算法和距离向量(DV)路由算法。
链路状态路由算法是基于Dijkstra算法设计的。其伪代码如下:
更加具体的可以参考:Dijkstra算法(三)之 Java详解
简单说下思想,就是建立一个完成的最短路径集合,该集合N’一开始只有原点u,接着建立一个优先队列集D,D中含有每个点到原点u的花费,无连接则花费为无穷,还有建立一个节点集合p(v)记录到达v点的最优路径的上一节点是啥。然后从进入循环,每次从D中取出cost最小的点w(w不在N‘中),对与w相连的每个点重新计算这些点到u的花费,如果比原来小,则更新D中数据,并更上一节点集合p(v)。循环直到所有点都被加进了N’中为止。要注意的是,不用担心N’中的点会被更新到最小值,因为Dijkstra算法的使用前提是cost都为正数。
在实际的转发表中,我们其实记录的只有u点的相邻节点,如下图:
震荡
链路状态路由算法也存在着不足,首先他需要获得全局的信息,其次他会产生所谓的震荡的可能性。震荡情况如下图:
距离向量路由算法是基于Bellman-Ford算法进行设计的,而后者的核心思想就是动态规划,也就是说当前路由器的最优解其实是由其他的最优解加上花费后进行权衡,取最小值得到的。状态转移方程如下:
距离向量路由算法有一个特点就是,好消息传播得快,坏消息传播得慢。
好消息传播快的原理如下:
坏消息传播慢的例子如下:
原因是当z->y->x采用的是y->x的原来的权重,当y->x权重变化后,z->y->x权重没变化,因此路由器会采取y->z->y(原)->x的路径,这样yz不停更新,自然会导致增长缓慢。
毒性逆转
为解决坏消息传播慢的问题,我们可以使用毒性逆转的方法,即:一个节点Z到某一节点X的路径是经过其邻居Y的,那么如果Y变化,则Z要告诉Y其到达X的距离为无穷大。如此便可较为快速的将坏消息传播出去。
最大度量
另一种解决坏消息传播慢的方式是最大度量。即定义一个最大跳步值,当超过这个跳步数量时,路由器认为该条路径的长度为无穷大。如下图所示。
由于Internet内路由数量巨大,因此单一将所有路由绘制成一张图是不可能的。为此,我们采用了层次化的方案。即通过将路由群分为不同的自治系统(AS),每个AS内部采用上节所述的路由算法进行管理,每个AS之间由各个AS内部的边缘路由进行通信。这些边缘的通信路由叫做网管路由器,其同时含有AS内部路由算法和AS间路由算法。网关路由会将本AS内所含有的IP域传给其他AS,也可能会帮忙传递传递与之相连的AS的IP域给另一些AS(可能性不大)。
热土豆路由
当一个AS1可以通过AS2或AS3到达AS4时,选择AS2还是AS3的依据就是热土豆路由原则,即谁离AS1的网关路由近(不管AS2,AS3的内部情况),就发给谁。
RIP
RIP(路由信息协议)采用的是路由向量算法,并且为了解决无穷计数问题,而引入了跳步数(为了计算最大跳步)和下一跳(毒性逆转原理)两个量。例子如下,当A向D通告后,D的路由表到达z的部分被修改了。
RIP的通告频率是固定的30s,因此时间一到,不管有无修改都会进行通告。当一个路由180s没收到邻居的通告时,默认该邻居失联。
注意:RIP的实现是在应用层中由route-d的进程进行的。但是考虑其功能是在网络层,故将其分为网络层协议。
OSPF
OSPF协议是采用链路状态路由算法,其通告方式是AS内部的网络泛洪。
相较于RIP,其优点如下:
- 安全性高,防止恶意路由入侵
- 有效均衡负载,可以同时选用多条费用相同路径
- 可以设置传输优先级
- 可进行单播/多播
- 可进行AS的再分层
如上图,AS再分层是利用将小子网的边界路由当作区边界路由器进行小子网IP地址汇总的方式运作的。对Backbone区路由器无需知道小子网内的具体连接情况,有效改善了性能。
BGP(Border Gateway Protocol)边界网关协议可以分为两个部分:
- eBGP:从邻居获取可达IP地址集合
- iBGP:向所在AS内部通告获得的其他AS可达IP集合信息
报文主要通过类似CIDR的方式告知IP地址集合,并且AS间的连接采用了半永久的TCP连接方式进行。
通告属性如下图所示,其中下一跳端口信息可以帮助路由决定用哪个网管路由器(通过热土豆路由选择)
注意:网关路由器的通告选择方案通常采用之前所说的人工的方式,原因是AS作为一个较大的集群,很可能会面临政策经济等相关因素影响,因此不采用自动设计路由路径的方式进行设置。