PPP协议(TCPIP协议第二版)

  • Post author:
  • Post category:其他


为了实现移植LWIP连入GSM网络,需要理解PPP协议的每个字段信息,以下节选翻译自TCPIP协议第二版,与大家分享~

PPP表示点对点协议,这是一种很流行的方式用来携带IP数据包,无论是高速光学线路上还是用于低速拨号调制解调器。PPP协议被广泛用于DSL服务运营商,同时也被用于配置Internet系统参数,比如用于初始化IP地址和DNS服务器。

PPP实际上应当被视为一簇协议的集合而不是单个协议。它包括链路控制协议LCP,一簇网络控制协议NCPs,以及一些相关的协议如压缩控制协议CCP和认证协议等。

链路控制协议LCP

PPP的LCP部分负责建立和维持一个在点对点链路上的低层次两端交流通道,因此LCP的操作只需要关注单一链路的两端,而不需要像以太网和WI-FI那样处理多路访问而引发的问题。

通常,PPP协议,准确的说应该是LCP协议,只对基础的点对点链路有极少的要求。链路应当支持双向操作并且支持同步通信和异步通信。LCP用比特流建立一条链路,比特流的格式是基于高级数据链路控制协议HDLC。因为在PPP设计之时,HDLC已经是一个很完善的协议了。IBM将HDLC修改之后使之成为同步数据链路控制协议SDLC,并将SDLC作为它专有的系统网络架构协议栈SNA的链路层协议。HDLC同时也作为802.2里的LLC标准的基础。

通常情况下,类似于HDLC帧格式的的PPP帧如上图所示。PPP帧首尾都是一个标志字节0X7E,该字节标志着PPP帧的开始和结束。那么这里就有一个小问题,当PPP帧的有效数据部分出现0X7E怎么办?这里有两种解决办法。当PPP处于异步操作方式下,PPP使用字节填充的方式。当标志字节出现在帧的非首尾部分时,0X7E被替换为两个字节0X7D5E,0X7D是PPP的跳脱符。如果0X7D本身出现在了有效数据部分,那么0X7D被替换为两个字节的0X7D5D。在接收端,0X7D5E又被替换为0X7E,0X7D5D又被替换为0X7D。如果是处于同步操作方式下,PPP使用比特填充的方式。0X7E的二进制比特流为01111110,有连续6个0,比特填充的方法就是在连续5个1的地方插入一个0,除了标志字符(这样,数据0X7E有9比特,标志0X7E只有8比特)。虽然比特填充会导致有的字节超出8比特了,但是这样是没问题的,底层硬件会处理这个问题。比特填充的方式不适合异步操作的原因也是在这里。

PPP的地址域与控制域也是采用HDLC的格式。在HDLC中,地址域标示对应的站点,但是在PPP中是点对点链路,不存在对应哪个点的问题,所以地址域为固定字节0XFF(0XFF在HDLC中表示所有站点的意思)。HDLC的控制域表示帧序和重发行为,但是这些可靠性相关的实现机制不应该是PPP考虑的范围,因此PPP的控制域固定为字节0X03。正是因为这两个字节是固定的,因此可以在传输的时候被忽略,是否忽略取决于一个协商选项——地址域和控制域压缩选项AFAC。

链路层该提供多大的可靠性,这个问题曾经被争议好多年。以太网帧有高达16次的重发机制,但是PPP却没有任何重发。

PPP帧的协议域指示了该PPP帧的数据类型。协议太多,具体内容可参阅www.iana.org/assignments/ppp-numbers

为了保持与HDLC协议一致,高位字节的最低位为0,低位字节的最低位为1。0X0000-0X3FFF的协议号对应一些网络层协议,0X4000-0X7FFF协议号对应一些不太重要的协议,这些协议与NCP不相关,0X8000-0XBFFF对应一些NCP协议,0XC000-0XEFFF对应一些控制协议如LCP。如果协议压缩选项PFC在链路建立阶段协商成功,那么两字节协议可以压缩为一个字节。当然这是针对与大部分网络层协议,这些协议的协议号在0X0000-0X00FF之间,LCP协议的协议号无论何时都是不能被压缩的。

PPP帧的最后部分是16比特的FCS校验码,实际上是一种16比特的CRC校验码,多项式为10001000000100001。校验码覆盖除了FCS本身和标志字节0X7E之外的整个PPP帧。值得注意的是,校验码对应的是不包含字节填充或者比特填充的数据。如果在LCP中协商通过,FCS也是可以为32比特的,这时候就与以太网的32比特校验码产生方式完全一致了(使用一样的多项式)。

LCP操作

在PPP帧里面,LCP有一个简单的封装形式。如下所示:

PPP帧的协议域的协议号总是为0XC021,代表这是一个LCP帧。LCP的类型域表示该LCP帧的类型:

LCP类型

通常,ACK表示接受LCP协商选项,NACK表示拒绝部分选项,Reject表示拒绝全部。

LCP的编号域表示LCP请求帧的序列号,发送一个请求帧编号加1。如果是一个回复帧,编号域则填上被回复的那个帧的编号。这样请求端就能判断是哪个请求被回复了。

LCP长度域指示了LCP包的长度,不包含LCP协议号0XC021。长度的值不能超过最大接收单位MRU。

LCP的主要工作就是启动一个点对点链路的连接。配置信息使得两端都有一样的基础配置和一个共同接受的环境。终止信息是在完成通信之后清楚一个连接。LCP也提供一些额外的功能,请求/回复的回显信息(9,10)可以在任何时候被交换,以此来确认对端的操作。丢弃请求(11)可以用来进行性能测试,该LCP包命令对端丢弃该包并且不用回复。类型为验证和剩余时间的LCP包(12,13)被用于管理目的: 获取对端系统的信息并且指示该链路保持连接的剩余时间。

由于历史原因,有一个点对点连接的问题经常会产生——当对端是一个回环网络。电话公司常常利用回环模式来进行测试,数据从一个站点发出,发出数据的站点会从另一个站点收到一样的数据。这种方式也许对测试有利,但是对数据交流是不利的,LCP有一种解决方式。LCP会发送一个魔数,这个魔数实际上就是一个随机值,发送之后根据是否收到一模一样的数据来判断是否连上了一个回环网络。

下图显示了如何建立一个PPP链路。该图大致描述了包交换的时间线以及链路状态转换机制。

一旦底层协议指示联系已经处于活跃状态,比如调制解调器检测到了载体,那么就应该认为链路已经建立起来了。同时在这个阶段,包含链路质量的报告信息也应当已经交换完毕。如果链路要求认证,则需要额外交换认证信息,这在拨号上网的时候很常见,ISP运营商要求有认证。一旦底层协议指示载体丢失,或者发送一个链路终结请求并且收到回复之后,链路马上进入终止状态。

LCP选项

LCP在建立链路连接之后可以进行若干选项的协商,这些协商的目的是为了服务后续的NCPs。在这里介绍两种广泛使用的选项。异步控制符表ACCM定义了哪些字符需要被跳脱,比如小于0X20的的ASCII码,跳脱标志就是0X7D。跳脱意味着真实的数据没有被发送,取而代之的是一个0X7D以及真实数据与0X20进行逻辑或。实际上就是把真实字节的第5个比特改为1。比如XOFF字符(ASCII码为0X13)会被转换为0X7D33。当某些控制字符会影响底层硬件操作的时候,ACCM就必须使用。比如,如果软件流量控制启用XOFF/XON字符,当收到XOFF但是没有进行跳脱时,数据传输就会终止直到收到一个XON字符。ACCM选项通常指定为32比特,第n比特为1就表示n所表示的控制符需要被跳脱。比如XON(0X11)和XOFF(0X13)需要被跳脱,则ACCM为0X000A0000。0XFFFFFFFF表示所有控制符都要跳脱,虽然0XFFFFFFFF是默认值,但是现在很多链路可以安全的操作即使ACCM值设置为0X00000000(这里XOFF是控制字符19,十六进制表示为0X13)。

因为PPP没有长度域,理论上硬件也没有对PPP帧长度有限制。但是实际操作过程中,大部分PPP帧的的最大长度是由MRU给出。当主机发送一个MRU选项(类型为0X01),对端即被要求永远不发生超过MRU选项里指定长度的PPP帧。MRU里指定的长度是数据区字节的长度,不包括协议,FCS,标志字节等。典型值是1500或者1492,但是有可能达到65535。对于IPV6而言,最小为1280字节。在同一PPP链路上,当小包插入到长包时,由于大包占用了大部分带宽资源,这会造成对小包的损害,结果就是造成抖动,即延时产生波动。这种抖动会对交互应用产生负面影响,比如远程登陆和VoIP。采用小一点的MRU会缓和这种现象,代价就是发送了更多的冗余信息。

PPP支持交换链路质量信息、在选项协商阶段,配置信息可以包含请求链路质量信息的协议。16比特的选项被保留用于指定特定的协议,但是一般都用链路质量报告LQR,该协议的协议号为0XC025。如果这个协议被使能,则对端被要求周期性的提供LQRs。两个LQR之间最大的时间间隔会被写在一个32比特的协商选项中。对端产生LQR的速度可能会快于所要求的频率。LQR包含以下信息: 一个魔数,收到和发送的数据包的数量,收到和发送的字节数量,收到的有错误的数据包数量和被丢弃的数据包的数量,LQR交互包的总量。有些还提供了一种处理方式,当链路质量下降到一个阈值的时候链路会被终止。在PPP链路建立之后,LQR请求依然是可以的,LQR包含一个序列号,所以显示整个时间线的链路质量是可行的。

很多PPP执行支持callback功能。在一个典型的callback过程中,PPP拨号callback客户端呼叫一个PPP callback 服务器,认证信息提供之后,服务器断开连接并且返回去呼叫客户端。某些通行费是是对称的或者为了安全保障的场合下。这个功能是很有用的。用来协商callback的TCP类型为0X0D,如果协商通过,那么回叫控制协议CBCP会启用。

PPP使用的一些压缩和封装算法要求知道确定的块尺寸。当数据包的大小不够这个长度时,填充字节可能就会附加到这个数据包上,可能会使得这个数据包数倍于这个块尺寸。填充信息处于数据去之后,FCS之前。一种填充方式是自描述填充,填充的数据为非零,而且每个字节的值是相对于填充区的偏移值。因此填充的第一个字节为0X01,因此该方式最多能填充255个字节。自描述填充选项(类型10)指示对端填充的形式和最大填充数MPV。因为PPP帧缺少明确的长度域,所以接收者可以使用自描述填充法来判断需要裁剪多少填充数据。

为了减少发送帧头这些冗余信息造成的开销,一个叫做PPPMux的方法被提出。该方法的原理是把多个协议的数据包合在一个数据包进行发送。该复合帧的协议号为0X0059,代表这是一个复合帧,然后每个包的信息都一个一个插入到该帧。一般有1到4字节子帧头。每个子帧头有1比特(PFF)指示是否有协议域包含在子帧头,1比特(LTX)指示跟随的长度域是否是1或2字节的。除此之外,如果有协议域,那就使用和之前协议号一样的值。PFF为0是可能的,此时子帧就是链路建立时由PPPMux控制协议PPPMuxCP设置的默认的协议号。



版权声明:本文为u011354506原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。