问题

AS之内的路由器在执行OSPF协议、建立本机转发用的IP路由表的过程中,是否、如何存储完整的路由信息?

回答
作为一名网络工程师,当谈到AS(自治系统)内部的路由器在执行OSPF协议,并据此构建本机转发IP路由表的过程时,路由信息的存储和利用,这绝对是一个值得深入剖析的环节。这不仅仅是简单地“存一下数据”,而是涉及了对网络拓扑、链路状态、邻居关系以及最优路径的动态理解和计算。

核心:OSPF的路由信息存储绝不是单一维度的“完整路由表”

首先要明确一点,AS内的OSPF路由器在构建其最终的IP转发用的路由表(Forwarding Information Base, FIB)时,并不会直接存储“完整的路由信息”的原始副本。OSPF的运作机制更加精妙,它分阶段、分层次地处理和存储信息,最终目的是计算出最优的转发路径,而不是把所有看到的东西都塞进FIB里。

那么,OSPF路由器在建立FIB的过程中,到底存储了哪些信息,又是如何存储的呢?我们可以从以下几个关键的数据库说起:

1. 邻接数据库 (Adjacency Database, AD / Neighbor Table):
存储什么: 这是OSPF路由器与直接相连的、并且也运行OSPF的邻居之间建立的通信状态信息。它存储了每个邻居的Router ID、其使用的OSPF接口以及邻居在TwoWay状态后所交互的数据库交换信息(比如Hello包中的一些标志位,确认了邻居关系)。
如何存储: 通常是以列表或哈希表的形式存储,键通常是邻居的Router ID或接口信息,值包含邻居的详细状态。
重要性: 这个数据库是OSPF邻居关系建立的基石。没有建立好的邻接关系,就无法进行后续的链路状态信息交换。它保证了路由器只与合法的、可通信的OSPF邻居进行交互。

2. 链路状态数据库 (LinkState Database, LSDB) / 拓扑数据库 (Topology Database):
存储什么: 这是OSPF协议的灵魂所在。它存储了AS内所有Router LSA(Router Link State Advertisement)、Network LSA、Summary LSA、ASBR Summary LSA以及External LSA(和NSSA External LSA)的副本。简单来说,它包含了AS内所有路由器发布的关于它们直接连接的网络(直连链路)、它们所连接的网段(Stub网络、Transit网络)、汇总的路由信息以及外部路由注入的信息。
如何存储: LSDB的存储是核心。它是一个以链路状态宣告 (LinkState Advertisement, LSA) 为基本单元的数据集合。每一条LSA都包含了特定的信息,例如:
Router LSA (Type 1): 由每个路由器生成,描述了该路由器连接到的所有网络(包括点对点链路、Stub网络)。它包含了Router ID、连接的网络信息(网络地址、掩码、度量值)以及连接类型。
Network LSA (Type 2): 由DR(指定路由器)生成,描述了一个多路访问网络段的成员(包括DR本身和其他连接到该网络的路由器)。它包含了DR的Router ID、网络地址、掩码以及该网络上的所有路由器ID。
Summary LSA (Type 3): 由ABR(区域边界路由器)生成,用于在区域之间传递路由信息。它汇总了其所属区域内其他路由器的信息,描述了一个目标网络(通常是另一个区域的内部网络或一个汇总地址)的路由。
ASBR Summary LSA (Type 4): 由ABR生成,用于告知其他区域内路由器如何到达ASBR(自治系统边界路由器)。它包含了ASBR的Router ID。
External LSA (Type 5): 由ASBR生成,用于将外部路由(来自其他IGP或EGP,如BGP)注入到OSPF域中。它包含了外部路由的目标网络、掩码、度量值以及外部路由协议的标签(Forwarding Address, External Forwarding Type)。
NSSA External LSA (Type 7): 在NSSA(NotSoStubby Area)区域中使用,用于将外部路由注入NSSA区域,避免生成Type 5 LSA,以减少区域内的LSDB大小。

LSDB的存储结构是一个共享的、一致的集合。当一个路由器收到一条LSA时,它会进行校验(CRC),并将其存储在本地的LSDB中。然后,它会将这条LSA通过SPF计算中使用的特定OSPF接口泛洪(flood)给所有邻居。
重要性: LSDB包含了生成SPF计算所需的所有原始链路状态信息。它描绘了整个OSPF域(或区域内)的完整拓扑结构,从每个路由器的角度来看都是一致的。

3. SPF树数据库 / 最优路径表:
存储什么: 这是Dijkstra算法计算后得到的结果。路由器根据LSDB中的信息,以自己为根节点,运行Dijkstra算法,计算出到达AS内所有网络的最短路径。这个结果通常以SPF树的形式存储,其中包含了到达每个目的网络的最优路径的下一跳信息(包括下一跳的IP地址和出接口)。
如何存储: SPF树可以理解为一种树形结构,其中每个节点代表一个路由器或一个网络,边代表最优链路。存储时,可能以类似于图的表示方式,记录每个目的网络的最优路径所对应的下一跳路由器IP和出接口。
重要性: 这是从原始链路状态信息向转发路径信息转化的关键中间步骤。它体现了OSPF的核心优势——基于全局拓扑的最优路径计算。

4. IP路由表 (Forwarding Information Base, FIB):
存储什么: 最终的IP路由表,用于指导数据包转发。它存储了到达各个目的网络(Network Prefix)的最优下一跳(NextHop IP Address)和出接口(Outgoing Interface)。
如何存储: 通常是以哈希表或特定优化数据结构的形式存储,以便快速查找。每一条目都对应一个目的网络前缀,并指向最佳的下一跳和出接口。
重要性: 这是实际执行数据包转发的“行动指南”。路由器的转发引擎(如ASIC或线卡上的查找引擎)会直接利用FIB中的信息来决定数据包的去向。

AS内OSPF路由信息的存储和构建流程:

1. Hello包交互与邻接建立: 路由器发送Hello包,发现并与直接相连的OSPF邻居建立邻接关系。在这个阶段,维护了邻接数据库。一旦邻居状态达到Full,就开始交换LSA。

2. LSA泛洪与LSDB同步: 路由器发送自己的LSA(基于接口状态和连接的网络),并通过邻居关系泛洪给其他路由器。同时,接收来自邻居的LSA,校验后更新本地的链路状态数据库(LSDB)。这个LSDB会逐渐在整个区域内(对于Type 1、2)甚至整个OSPF域(对于Type 3、4、5)保持一致性。

3. Dijkstra算法计算SPF: 当LSDB中的LSA发生变化(新增、老化、改变)并被所有路由器同步后,每个路由器都以自身为根节点,在本地的LSDB上独立运行Dijkstra算法。
算法的输入是:LSDB(描述了网络拓扑和链路成本)和所有已建立邻居的接口信息。
算法的输出是:SPF树,即到达AS内每个网络的最优路径(包括下一跳和出接口)。

4. SPF树到路由表的转换: 路由器根据SPF计算的结果,将最优路径信息填充到其本地的IP路由表(FIB)中。
对于直接连接的网络(LinkState type为PointtoPoint或Stub Network),下一跳通常是邻居路由器,出接口是连接到该邻居的接口。
对于通过其他路由器间接连接的网络,下一跳是SPF树计算出来的、通往该网络的第一个中转路由器,出接口是连接到该下一跳的接口。
对于不同区域之间的路由(Type 3 LSA),ABR会将其汇总的路由信息转换为本地路由表条目。
对于外部注入的路由(Type 5/7 LSA),ASBR或代理ASBR会将其转换为本地路由表条目。

关键点总结:

LSDB是基石: 路由器存储了完整的LSA集合,这构成了其对AS内部拓扑的认知。
独立计算: 每个路由器独立运行Dijkstra算法,基于其本地LSDB计算最优路径。
SPF树是中间结果: 计算出的SPF树是直接用于生成路由表的信息,它包含了指向每个目的地的最优路径。
FIB是最终的转发决策: 最终的IP路由表(FIB)只包含最优路径的下一跳和出接口信息,并不包含完整的LSA或拓扑结构。它是一个高度优化的、用于快速查找的结构。

所以,与其说路由器存储了“完整的路由信息”,不如说它存储了构成完整拓扑的“链路状态信息”(LSDB),并利用这些信息计算并存储了通往AS内所有已知目的地的最优路径(在SPF树和最终的FIB中体现)。它并不需要把每一条可能存在的路径都保存在FIB里,这是OSPF高效性的体现。这种分层存储和计算机制,使得路由器能够快速响应网络变化,并做出最优的转发决策。

网友意见

user avatar

题主应该是没做过路由器或者交换机,所以把路由器想象成一个类似于APP之类的东西。

实际上,路由器相当于一台计算机,而OSPF相当于计算机里的一个程序。同时,BGP,RIP,报文转发,IP路由表维护等等,这些都类似于一个一个独立的程序。

在OSPF内部,是存储了当前OSPF路由协议范围内的拓扑信息的,这个拓扑信息,只要OSPF建立起邻居关系就有了,并且一直存在。

在IP路由表这个模块程序里,它是不负责存储任何拓扑结构的,IP表里只有一个的东西,就是某个目的地址的下一跳是哪里——也就是路由表。

在路由器里,各种路由协议都是独立运行的,甚至某个路由协议还有多个实例(OSPF多实例),每个路由协议根据自己协议的情况获取网络拓扑情况,并计算出协议内的最优路由表,然后把这个路由表通告给IP路由模块。

IP路由模块可能会同时收到不同协议下、不同结果的路由信息,IP路由模块唯一的工作就是根据优先级选路,以及计算递归路由。

IP路由模块计算完最终生效的路由表以后,会下发给二层模块,二层模块会根据下一跳信息计算出具体报文要经过哪个二层接口(可能是虚拟的,也可能是物理的)发出,同时还要考虑到负载平衡等因素。

二层处理完这些信息以后,会通知物理层驱动去操作硬件,完成路由表写入硬件的动作。

所以:

1. IP路由表里不储存完整路由和拓扑信息,它只负责选路;

2. 各个协议内部自己维护自己的路由表,这个路由表跟IP层看到的,不一定相同,这些信息一般情况下都保存在内存中,可能是链表,可能是数组,也可能是其它形式;

3. 不存在“执行协议”这个动作,不同层次的驱动做不同的事情。


不知道题主是不是要实现OSPF协议,事先说明,OSPF协议非常复杂,即使实现基本功能,也需要大量的代码(几万行),这还不包括协议的支撑部分(核心路由管理)。

OSPF路由表的数据结构是一个route_entry的结构:

1. 需要一个指针指向一个二叉树(或者就是一个树),二叉树里是具体的路由结构。为什么是个二叉树呢,因为路由是可能合并的。
2. 需要一个path的vector,也就是路径节点。
3. 需要一些辅助信息,比如metric,distance等。
4. 需要一个selected_path指向一个path_entry的结构,也就是选路的具体信息。

path_entry里需要包含的成员有:

1. 各种辅助信息,比如类型、flag、metric之类
2. area号
3. 一个vector成员记录着下一跳信息
4. 一个vector成员记录着对应的lsa信息
5. 一个path_entry指向最终的、翻译后的path

以上是路由表的结构,需要route_entry和path_entry两套。

同时,LSA这些还需要额外的数据结构。

一套商业的OSPF代码大概需要5-10万行代码才能实现。不包含底层驱动,不包含核心表。


评论区有人推荐用zebra,我查了一下,这个东西就是我评论里提到的ZebOS的开源版本,在这里:

Zebra - Free Software Directory

可以下载到一个副本(页面右侧链接),貌似现在这个版本维护的比较少了。我做路由协议这一块是十几年前的事情了,对最新的技术状态不是特别了解。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有