1.5. ARPANET的路由

        1983年初NCP向TCP/IP迁移时,两个社群在使用ARPANET:军事行动和大学/企业研究员。特别是在第二个社群中,大批的毕业学生正在以那些将很快影响商业社群的方式学习使用网络。他们也用网络做一些明显非科研性的活动,如打游戏。大量和持续增长的用户数导致的结果是,国防部开始担心安全问题,并决定把他们的节点挪到一个叫MILNET的隔离的网络去。但他们又希望能继续访问ARPANET节点,所以两个网络仍通过一个网关保持连接。隔离实际上只是提供了独立的管理控制;两个网的用户都感觉不到区别。向TCP/IP的迁移使这次分割成为可能。
 
       在美国和欧洲,其他的网络开始出现并互联起来。最重要的且最具深远影响的是NSFNET,1985年由国家科学基金会(National Science Foundation)建立。其原本计划是以56kbps的链路将五个超级计算机站点互联起来,而1988年链路升级到了T1,1990年又升级到了T3。NSFNET连接遍布全国的大学和企业;更重要的是,它为国内涌现的区域性网络提供免费连接。ARPANET的低速链路、古老的IMP和TIP以及限制性的访问策略意味着到了1980年代末,大部分用户接入了其他网络。DARPA认为该是这个有20年寿命的网络退役的时候了。其站点一个接一个转入了区域网络或MILNET,到了1990年ARPANET不复存在了。
 
 
        但正如简短的历史回顾所展示的那样,几乎所有我们使用至今的互联网络技术都是源于ARPANET。包括本书的主题,路由技术。到1980年代中期,涌现出许多公司,他们销售被称为路由器的商业版网关:3Com, ACC, Bridge, Cisco, Proteon, Wellfleet等。他们都使用在ARPANET上率先使用的路由算法。有趣的是,BBN的工程师试图说服公司进入商业路由器领域,但其市场部门断定这东西是没有前途的。
 
 
        ARPANET上使用的第一个路由协议是由BBN当初的IMP团队成员Will Crowther于1969年设计的。就像所有路由协议一样,它基于数学图论--在本协议中是Richard Bellman和Lester Randolph Ford的算法。Bellman-Ford算法形成了某种路由协议的大部分具体实现的基础。这种路由协议多年来被称为距离矢量协议。Crowther的协议是一种分布式自适应协议--即,它是为适应快速变化的网络特性而设计:能调整所使用的链路度量值(自适应),路由器协同工作以计算通向某目的地的最优路径(分布式)。
 
 
        Crowther的路由协议使用延时作为度量值。每个IMP通过每隔128毫秒对每条附属链路上排队的报文数量进行计数来估算延时。一个表示最小成本的常量加到计算出的数目上以避免某条空闲链路的度量值被计为零[21]。测算队列长度的次数越多,IMP能越快地检测和适应变化的链路延时。理论上,结果是流量应该在通向某目的地的所有出口链路上非常均衡地分布。
 
[21] 尽管可能与路由无关,Bellman-Ford算法的一个优于Dijkstra算法之处是,Bellman-Ford能为一个图形的支路赋予负成本值,而Dijkstra不能。
 
        每当有了新的计数时,IMP就更新路由表,然后把路由表通告给邻居。邻居一收到此通告就估算到发通告的IMP的延时,把结果同接收到的表中的信息相加,然后以其总和来更新本机的路由表中那些要经通告者才可达的目的地的信息。更新完成后,邻居就把本机路由表通告给它们自己的邻居。路由计算的分布式特性就源于全网中反复进行的路由表通告和更新。
 
 
         最初的协议在其头十年很好地服务于ARPANET。在低流量负载情况下,路由决策主要决定于那个加到估算延时上的常量。在中等流量负载情况下,网络中某些隔离的区域可能会出现拥塞;在这些区域,测算出的队列长度就成为主要因子,这样流量就从拥塞处被转移了。
 
         但是随着ARPANET越变越大和流量负载越来越重,这个协议开始出现越来越多的问题。其中一些问题与度量值的决定方式有关:
 
·         队列报文计数是瞬间测量。在一个繁忙的网络中,队列长度会经常而且快速地变化,从而导致度量值的极大波动和由此带来的路由表震荡。
·         对队列中的报文进行计数没有把可用链路速度考虑进去。即使一条高速链路的队列中报文更多,它的延时也比低速链路小。
·         队列延时并非影响整体延时的唯一因素。报文长度、IMP处理时间和其他因素都会导致延时。
 
       另外,距离矢量方法本身的问题开始出现:
 
·         当网络节点数增加时,路由表的交换会开始消耗很大一部分可用带宽。
·         测算延时和更新路由表的频率,连同瞬间队列测算,会导致网络对真正的拥塞反应不够快,而对轻微的、不重要的队列变化又反应过快。
·         分布式计算本质上收敛慢,易受持续性路由环路和不准确性影响(坏消息传得比好消息快)。(第2章讨论距离矢量协议的典型弱点。)
 
 
       1979年BBN部署了一个由John McQuillan, Ira Richer和Eric Rosen设计的新的ARPANET路由协议。[22]新协议与原来的相比,引入了三个重要变化:
 
[22] John M. McQuillan, Ira Richter, and Eric C. Rosen, "The New Routing Algorithm for the ARPANET," IEEE Transactions of Communications, Vol COM-28, No. 5, pp. 711719, May 1980.
·        尽管协议仍使用基于测算延时的自适应度量值,但度量值变得更准确和更少瞬间性。
·        更新频率和更新包大小明显减小,占用更少带宽。
·        路由算法从基于接收到的数据库的分布式计算变为基于接收到的度量值的IMP本地计算。
 
        改进后的度量值决定方法意味着更少的路由震荡。IMP给每个到达的包打上到达时间戳,而不是计算队列中的包数目。然后当发送数据包的第一个比特时,再打上发送时间戳。当收到包的确认信息后,从发送时间中减去到达时间。然后一个代表线路传播延时的常量(称为偏差)[23]和一个代表传输延时(基于包长和线路速度)的变量与到达时间和发送时间之差相加。得到的值是真实延时的一个更准确的测量结果。每10秒对各条链路上测量到的延时取一次平均值,这个平均值就是链路的度量值。通过取平均值,使用瞬间测量所带来的问题就被避免了。
 
 
[23] 与前一个协议一样,常量避免了为空闲链路赋零成本值的可能性。
        第二个变化,减少更新频率,通过设置一个始于64毫秒的阈值来完成。当计算出平均延时后,将结果同上次结果相比较。如果差异没有超过阈值,不发更新,下次对比时阈值要减去12.8毫秒。如果超过阈值就发更新,阈值重置为64毫秒。衰减的阈值保证了大的度量值改变能被快速通告,而小的改变更慢地被通告。如果度量值没有变化,阈值会在50秒后衰减到0,从而导致即使度量值没有变化也会发出更新。新算法的结果是,更新频率及其带宽消耗极大减少。
 
        更新包的内容同样重要。IMP只发送它的本地链路的度量值给邻居,而不发路由表了;更新在全网范围发送(设计者称这个过程为“泛洪flooding”),每个IMP在数据库里保存一份更新的拷贝。IMP不用在转发更新之前进行本地计算。这有两个好处:更新包本身很小--平均176比特,进一步减少了带宽消耗;由于更新在100毫秒内很快泛洪到所有IMP,网络可以更快地对变化做出反应。序列号、寿命和确认包的使用保证了泛洪的度量值的准确性和可靠性。[24]
[24] 这个协议使用循环序列号,如2.2.2节所述。想知道两个序列号的简单损坏如何导致ARPANET在1980年10月27日崩溃的有趣故事的话,阅读Eric C. Rosen, "NCP协议的脆弱性:一个例子," RFC 789, 1981.
 
        第三个显著变化,也是对本书最重要的一个变化,是这个协议基于图论专家 Edsger Dijkstra发明的算法计算路径,而不再用Bellman-Ford算法。每个IMP使用其他IMP泛洪来的度量值的数据库,在本地计算到所有其他IMP的最短路径。这个处理方式极大减少了前一个路由协议下开始困扰ARPANET的环路问题。McQuillan、Richer和 Rosen称他们的基于Dijkstra的算法为最短路径优先算法(SPF,shortest-path-first)。这是第一个大规模应用在包交换网络的链路状态协议。
 
 
         第二个路由协议在ARPANET上用了8年,直到问题再次出现--此算法对持续的网络成长可扩展能力不足。但这一次,SPF算法没被变动,只是自适应度量值的计算出了问题。
 
        前一个协议计算延时所用的三个因子是队列延时(由发送时间和到达时间之差表示)、链路传播延时(基于常量)和链路发送延时(基于数据包长度和线路速度)。在低流量负载时,队列延时的影响可以忽略不计。在中等负载时,队列延时变得重要,导致流量的适当变化。而在高负载时,队列延时成为计算度量值的主要因子。这时,队列延时会引起路由震荡。
 
         以图1.2为例。两条链路A和B,连接网络的两个地区。东西两个地区之间的所有流量都必须使用其中一条。如果多数路径选择A链路而且链路负载很高,则那条链路的队列延时变高,一个高延时值将被通告给所有其他节点。由于其他节点基本是在同一时间运行SPF算法,它们会同时得出相同结论:A超负荷了,B是更好的路。所有流量就切换到B,导致B产生高延时;在下一次测量时,B的高延时被通告,所有路径又切换回当前使用不足的A。A现在又超负荷,流量再次切换到B,如此下去。震荡会无限进行。在每次切换时,链路负载导致链路度量值的大变动,而且导致一个结果--在发生切换时,导致切换的度量值就作废了。
 
图1.2ARPANET第二个路由协议最初的自适应度量值计算会导致平行链路(如图中A和B)之间发生路由震荡。
        为了解决此问题,1987年部署了Atul Khanna, John Zinky, 和BBN的Frederick Serr设计的新度量值算法。新算法还是自适应,也还采用10秒测量平均延时。在轻负载和中等负载时,它的行为跟前个度量值算法没有太大区别。改进之处是看这个算法在高负载时如何运作。度量值不再是延时,而是延时的方程式,且度量值变化范围受限。从而使在一个同构网络中,两个基本平等的路径的相对度量值的变动不能超过两跳。即,不能为绕过拥塞链路把流量路由到超过两跳以外。这是链路利用率的一个方程。当利用率低时,此算法计算度量值好像是基于延时的,而当利用率增加时,它计算度量值就像是基于容量的。
[25] Atul Khanna and John Zinky, "The Revised ARPANET Routing Metric," Proceedings of the ACM SIGCOMM Symposium, pp. 4556, September 1989.
       虽然ARPANET的度量值计算算法变了,SPF算法却只有一点小变化:路径被逐渐从过度使用的链路上移走,而非同时全部移走,减轻了重度路由震荡的隐患。
 
        A度量值计算算法本身对本书没有什么实用意义,一些关于自适应路由算法概述也是:分布式自适应算法要起作用,涉及了相当的复杂性。结果是,当代包交换网络的多数自适应算法提供的诸如流量工程等功能是集中式而非分布式。从早期ARPANET实践中成长出来的链路状态路由协议使用固定而非自适应的度量值。
 
 

互联网有父亲么?

 
当听到美国大众称乔治华盛顿为“国父”时我总是很厌烦。作为一个约翰亚当斯的狂热崇拜者,我认为约翰亚当斯的革命工作及后来的外交努力应为他赢得这个头衔(尽管公认亚当斯不是一个很好的总统)。其他人可能会对富兰克林或杰斐逊有同样的强烈感情。如果我们一定要用家庭式语言,“建国父辈”这个词更公平。这个称号公平地承认美国诞生于许多人的努力,而不是一个人。
对互联网而言也是这样。比起其他任何人来,可能Vint Cerf被更多人称为了“互联网之父”,但J. C. R. Licklider、Larry Roberts、Len Kleinrock、Bob Kahn、Jon Postel和另外一些人也已被冠以孤独的父亲身份。然而单单挑出某一个人的努力成果极不公平地轻视了其他很多人的努力。互联网并非只有一个父亲,而是有一个相当庞大的父亲团和一些母亲们。
在本章我介绍的简短历史中,没有被提到的互联网创建者比提到的更多。我写这段历史时从很多来源引用了资料,但最有用的参考是Katie Hafner和Matthew Lyon著的Where Wizards Stay Up Late: The Origins of the Internet(术士们熬夜的地方--互联网络传奇)[26]。如果你想更多地了解互联网的诞生和获得荣誉者,我强烈推荐这本有趣的、增长见识的书。
 
[26] Katie Hafner和Matthew Lyon, 术士们熬夜的地方--互联网络传奇, Simon & Schuster出版社, 1998.