一 概述
IP协议是TCP/IP协议簇中最核心的协议,所有的TCP、UDP、ICMP以及IGMP数据都以IP数据报格式传输。IP协议提供不可靠、无连接的数据传输服务。不可靠的意思是它不能保证IP数据报能成功到达目的地。IP仅仅提供最好的传输服务。意思就是,我尽我所能传输数据,实在没传过去,也不要怪我。当发生某种错误时,比如某个路由器的缓冲区慢了,此时路由器不能接收新的数据,直接丢弃处理,然后发送ICMP消息给信源端,告诉他我尽力了。如果需要可靠的传输,必须由上层协议来提供,比如TCP协议。无连接的意思是IP并不维护任何关于后续数据报的状态信息。每个数据报的处理时相互独立的。也就是说,IP数据报不一定按照发送的顺序接收。比如某一信源向同一个信宿发送两个连续的数据报(先发A,再发B),信宿收到时,可能B在A之前收到,因为A和B并不是通过同一个路径发送,他们是相互独立的。除此之外,IP数据报在传输途中,还有可能被复制,或者遇到某些错误时数据被更改,这都是有可能的。而这些问题都需要通过上层协议去解决。
二 IP首部
如图所示,IPv4数据报格式。IPv4首部正常大小是20字节,如果有一些选项(options)需要设置的话,会大于20字节,但是这种情况比较少见。IPv6首部大小是IPv4的两倍,但是IPv6首部没有选项(options),因此它的大小是固定的。然而IPv6可能会有扩展首部,我们将在后面讨论。
关于字节序:有两种类型,小端字节序(little-endian)和大端字节序(big-endian)。两者的区别是,小端字节序是将低位字节放在内存的低地址段,高位字节放在内存的高地址段;大端字节序是将高位字节放在内存的低地址段,低位字节放在内存的高地址段。举个例子,对于0x12345678,最高字节是12,最低字节是78,因此按照小端模式存储顺序为:0x78,0x56,0x34,0x12。按照大端模式存储的顺序为:0x12,0x34,0x56,0x78。
在所有的TCP/IP协议首部中,数据传输都是按照大端进行传输的,这也叫做网络字节序。但是在很多PC机上,存储方式是小端存储,因此,在传输数据时需要进行转换。
在IP首部的图中,我们可以看到,左边是从0bit开始,代表高位,右边是31bit,代表低位。在传输过程中,4字节的传输顺序是,0-7bit先传,然后是8-15bit,接着是16-23bit,最后是24-31bit。
我们来看看IP首部。
最开始的4个bit是协议版本字段。4代表IPv4,6代表IPv6。我们看到,在IPv4和IPv6的首部里,都是这样的。说明无论是用IPv4还是IPv6,每个IP数据报首部最开始的4bit要么是4要么是6。
Internet Header Lenght(IHL)字段表示IP首部所占32bit的数目。一般为5,这时IP首部长度是5个32bit,也就是20字节。因为IHL占用4bit,因此IP首部最大长度为60字节。IPv6首部中没有这个字段,因为IPv6首部固定为40字节。
接下来是6bit的DS字段和2bit的ECN字段,在IPv4和IPv6中都是一样的,在数据报传输的过程中,这两个字段发挥着特殊的作用,我们后面再讨论。
接下来是Total Length字段,表示IPv4数据报的总byte数。通过该字段和IHL字段,我们就能知道IP数据报的数据部分(除了首部的其他部分)从哪儿开始,并且有多大了。因为该字段占用16bit,因此,IPv4数据报(包括首部)最大值为65535byte。之所以需要Total Length字段,是因为在低层次的协议中,比如以太网帧中包含IP数据报,如果IP数据报太小,则需要在其后面填充0,这样以太网就没法判断有效的IP数据报到底是哪些了。
尽管最大的IPv4数据报是65536byte,但是由于各种限制,往往不能传输这么大的数据。当要传输大数据时,需要进行分片(fragment)。分片以后,Total Length字段代表的是每个分片的长度(而不是分片之前数据报总长度)。
在IPv6中,首部不支持分片,而IPv6数据报长度是由Payload Length字段表示的。该字段表示除首部之外的IPv6数据。
Identification字段用来标志从发送端发送的每个IPv4数据报。因为每份数据都是不一样的,因此该标志的值也是不一样的,没发送一份数据,该值加1。显然,这个字段与它后面的两个字段一样,都是和分片功能息息相关的。我们后面再讨论。
Time-to-Live(TTL)字段,表示IPv4数据报的生存期。在IPv4数据报发送出去时,有个初始值,在转发的过程中,没经过一个路由,该值减1,如果该值变为0(还没到达目的地),它将被丢弃,然后想发送者返回一个ICMP消息。这样做是为了防止某些数据在网络中无线循环的传递,这样会导致网络拥塞。
协议(Protocol)字段表示IPv4数据报的有效载荷部分的数据类型,比如17代表这是UDP数据,6代表TCP数据。通常情况下都是封装的上层协议的数据,但是也有例外。
Header Checksum字段计算IPv4首部的长度,并不包括有效载荷部分,这就意味着封装在IPv4数据报里面的上层协议的数据IP层不负责检查它的正确性,所以我们说IP层提供的是不可靠的传输服务。因此,几乎所有封装在IP数据报中的协议(ICMP,IGMP,UDP和TCP),这些协议的数据中都包含有各自的检测字段,没办法,IP协议不提供,只能自己想办法了。奇怪的是,IPv6并没有提供checksum字段。
用来计算checksum的算法,我们称之为Internet checksum。这个算法是值得讨论的,它并不像以太网中的数据校验,在这里有个特殊的情况,比如IPv4首部中的TTL字段,它是变化的,所以checksum就不能是简单的校验。然而我并不太关心这个,所以我就不说了。
当然,在IP首部中不可缺少的是源地址和目的地址,IPv4中是32bit,IPv6中是128bit。目的地址可能是多播或者广播。
我们回过头来看看DS字段和ECN字段。之前我们说,在IPv4中,这两个字段是在数据转发过程中起到特殊作用的,我们现在来看看到底起什么作用。IP数据报从源主机发送到目的主机的过程,要经过很多个路由,有很多条路径可以选择。把这两个字段设置成某些值之后,这些数据报和普通的数据报在转发的时候会有不同的策略。它能让数据在转发时拥有不同的排队延时,以及其他的影响。
DS字段中的值称为Differentiated Services Code Point(DSCP),它实际上是一个事先商定好的值,代表着数据报的优先级。通常,这个值在传输过程中不会改变,但是也会有例外。
两个bit的ECN字段是用来做什么的呢?当一个数据报经过一个比较拥塞的路由器时,ECN字段将会被设置,作为一个拥塞指示器。有什么用呢?想象一下,当目的主机收到一个ECN字段被标记的数据报,它就能知道某个路由刺客发生拥塞,那么某些协议(比如TCP)将会降低传输数据的速率,以此来缓解拥塞的路由。
DS字段和ECN字段的位置一开始是用来放置Type of Service(ToS)字段,在IPv6中是Traffic Class字段。尽管他们没有得到广泛的使用,但是现在的DS字段仍然能够向后兼容。我们从ToS字段开始说起吧。
ToS字段内容如上图所示,D、T、R分别代表延时(delay)、吞吐量(throughput)和可靠程度(reliability)。当置1时,代表着更好的性能,更低的时延,更大的吞吐量和更高的可靠性。Precedence部分的值从000到111,分别代表一般优先级和网络控制优先级,也就是最低优先级和最高优先级。具体对应关系如下表:
在设计DS字段的时候,为了向后兼容,precedence被考虑进来。我们来看看DS字段的内容:
标准情况下,DS0的值都是0。其他五位去不同值的时候,代表着不同的优先级,具体如下图:
我们看到,最开始的八行,跟之前Tos字段表示的含义是一样的,这就是向后兼容。不同的数据报拥有不同的优先级,这里的优先级是指,在转发的时候,会享有不同的特权。比如有的能优先转发。
正常情况下,IPv4首部总共20字节,我们已经都讨论过了。但是IPv4首部中还有可能添加一些额外的选项(IP Options)。这些选项有各种各样的用途,但是他们很少用到,我们不再详述。
三 IPv6扩展首部
IPv6是一个还在发展和完善中的协议。有机会单独拿出来整理。
四 IP路由选择
IP路由选择是IP协议里面非常重要的一部分,也是非常复杂的一部分内容。但是,对于发送端来说,这个过程非常简单。如果目的端和发送端直接相连(点对点连接),或者在一个局域网(比如以太网),这时候发送端只需要将数据报直接发送给目的端即可,不需要路由器。否则,发送端将数据发送到默认路由器,然后让该路由器将数据报发送给目的端。大多数情况下,就是这么简单。
当然,情况可能会更加复杂,我们从路由表开始谈起。
1.路由表(Forwarding Table)
路由表或者说转发表,是每个路由器都会存储的那么一张表,就像ARP协议里每个接口都会有一个ARP高速缓存一样,它记录了一些信息。路由表记录的信息就是,当路由器接收到一个数据报,它能通过路由表记录的这些信息,知道把该数据报往哪儿发。每条信息包括以下几点
(1) 目的地址(Destination)。可以是一个完整的主机地址,也可以是一个网络地址。如果主机号为0,将发给指定网络的所有主机,否则,发给某个特定的主机。
(2) 掩码(Mask)
(3) 下一跳(Next-hop)
(4) 接口(Interface)
我发现,在看上面这些词汇的信息的时候,我似懂非懂,看了后面的例子之后,立马明白了,所以不要在意这些定义和解释,直接看后面的例子就懂了。
我们需要知道的是,IP数据报在转发的过程中,是一跳一跳的,从一个路由器跳到另外一个路由器,直到到达目的地或者被丢弃。它只知道下一跳往哪儿走,不知道整个的路径是什么样的。并且总是假设下一跳里目的地更近。有的人对这个事情很费解,它怎么就一定会到达目的地呢?这个是由专门的路由算法来保证的,比如RIP,OSPE等。
2 IP路由转发过程
当路由器接收到一个IP数据报,到它将该数据报发往下一跳,这个过程就是IP路由转发过程。具体如下:
接收到数据时,路由器提取目的IP地址D,将D与该路由器的路由表中每一个条目中的mask按位做与运算,得到的结果中含有1最多的,即为最佳匹配结果。那个mask对应条目中的下一跳就是该数据报应该前往的下一跳。
3 例子
举两个例子,直接传输和间接传输。直接传输就是在同一局域网,或者直接相连的,间接传输显然就是另外的情况了。
下面是间接传输的例子,非常清楚明白。