引 言
路由器最重要的工作是根据IP包头和路由、过滤规则转发IP包。其他功能还包括路由表的维护与路由器系统的维护。实际上路由器可以看成是一种针对IP网络路由需求而设计的专用计算机。随着因特网所承载的业务的演进,因特网对于路由器性能的要求也日渐提高。在交换式路由器中,包转发等绝大多数处理已经转移到以端口为中心的硬件中完成,只有路由规则的生成与维护、网络治理和系统维护等比较复杂的工作仍由软件部分完成。
实用中路由器所采用的操作系统可分为三大类:(1)以Cisco的IOS为代表的专用操作系统,常见于网络骨干节点;(2)以VxWorks为代表的嵌入式系统,常见于小型办公/家用接入设备上;(3)采用通用操作系统的则在骨干节点和用户接入设备上都有这类设备。例如Juniper的路由产品就采用Linux作为操作系统。通用操作系统上的各种路由、网管软件的开发已经有相当长时间,其功能、性能、稳定性和升级灵活性都很优秀,但这些软件仍然是针对传统路由器体系结构开发的,无法直接应用于新的路由器体系结构。本文提出在通用操作系统的驱动栈中插入一个中间层,这样对系统内核及和运行在其上的路由、网管等上层软件屏蔽了下层硬件的非凡性,从而把上层软件和高速硬件平台结合起来。该方案已经应用于高速边缘路由器中,并表现出了良好的实用性和可扩展性。
1 交换式路由器与传统路由器在体系结构上的差别
路由器工作在网络的第三层,其处理工作主要涵盖七层模型中的下三层,包括:物理接口处理、数据链路层处理、网络层的路由查找、转发以及队列治理等[1]。在传统的路由器体系结构中,硬件部分只实现物理层的处理,其余工作需要消耗系统计算资源完成:包括CPU周期、内存容量和总线带宽等,因此性能也受限于这些资源。而在交换式路由器中,路由处理机仅处理系统维护、路由表维护等少量工作,数据流的处理都由相对独立的硬件完成,不再受限于系统计算资源,因此其性能远优于传统路由器[2]。如图1所示。
传统路由器和交换式路由器在体系结构方面有明显的区别:在传统路由器中,所有的物理接口直接挂接在总线上,内核可以通过总线直接访问这些接口;而在交换式路由器中,只有控制卡是直接挂接在总线上的,内核必须通过控制卡间接访问各个接口。这导致操作系统内核中代表网络接口的驱动对象的区别:在传统路由器中,内核存在若干网络设备驱动对象实例,每个实例通过总线直接维护一个端口,为内核及其上面的上层软件提供基本操作支持。而在交换式路由器中,普通的网络设备驱动对象无法直接维护端口,也无法支持系统内核和上层软件操作。因此,交换式路由器体系结构的非凡性使得通用操作系统和上层软件无法直接应用。针对这个问题有两种解决办法:(1)大量修改内核和各种相关软件的源代码以适应新的体系结构。这种做法存在开发工作量大、周期长、局限性强的缺点,丧失了使用通用操作系统的灵活性;(2)在驱动栈中增加一个中间层,支持普通网络驱动对象所能支持的一切操作,这样系统内核和上层软件基本上不必修改就可以运行在交换式路由器上。这就是本文所提出的中间层方案。这种方案克服了第一种方法的复杂性,在保持灵活性的基础上,可以快速地把通用操作系统及上层软件移植到交换式路由器的硬件平台上。
2 中间层设计
中间层功能包括数据通信和控制两个方面。从数据通信方面考虑,每个端口的功能都等效于传统路由器中的一个网络接口,所以每个物理端口在内核中都应有对应的网络驱动实例。这样才能支持各种上层软件运行,满足数据通信功能的需要。
从控制功能方面考虑,对上要把每一种可能的逻辑操作映射成硬件操作;对下要能够和多个设备通信。上层应用包括系统维护、路由软件、网管软件;下层设备包括处理引擎和端口。控制功能的具体实现和硬件平台有关。考虑到多种应用可能同时操作一个硬件设备,一种应用也可能同时操作多个设备,在实现时必须考虑到对于多并发操作的支持。
基于上述考虑,中间层由控制卡驱动模块和若干网络驱动实例组成。在图2(a,b)中分别给出了传统路由器的结构与驱动方式以及本文所提出的中间层所处的位置与驱动方式。
控制卡驱动模块作为中间层的核心,维护控制卡上所有的端口、内存映射、中断和循环缓冲队列资源。它实现了数据通道和控制通道。对下直接驱动控制卡、与各个端口、处理引擎通信;对上,一方面通过内核调用陷阱方式提供控制通道接口;另一方面向虚拟网络驱动实例提供数据通道接口。虚拟网络驱动实例在操作系统内核为各个物理端口实现网络驱动实例。它们工作在控制卡驱动模块的基础上,并不直接控制硬件,故称为虚拟网络驱动实例。虚拟网络驱动实例封装控制卡驱动模块提供的数据传输功能,并为内核和上层软件提供与普通网络驱动实例相同的调用接口。下面分别给出数据通道和控制通道的实现方案。
2.1 数据通道的功能与实现
虚拟网络驱动实例和物理端口是一一对应的。内核数据收发的功能包括3个方面:
(1)发往某虚拟网络驱动实例的数据包应该由其对应端口输出;
(2)这个端口所收到的包也通过该虚拟网络驱动实例向系统内核提交;
(3)中间层也可以对虚拟网络驱动实例进行流控操作,以避免因拥塞导致数据丢失。
注重到图2(b)中的交换结构以定长信元交换数据,其格式如图3所示,其中信元头占4字节,包括处理引擎号和端口号域。对于收/发信元,处理引擎号和端口号分别为该信元的源端口的和目的端口的对应值。
根据图2(b)所示的系统结构可知:由处理引擎号和端口号可以确定端口的物理位置。控制卡驱动模块在其内部的驱动信息数组中维护虚拟网络驱动实例和端口之间的对应关系。
发送数据时,虚拟网络驱动实例从内核网络部分获取待发送的数据,偕同指向该实例自己的指针一起提交给控制卡驱动模块。一方面,控制卡驱动模块通过这个指针可以对虚拟网络驱动实例进行流控设置;另一方面,控制卡驱动模块根据虚拟网络驱动实例指针查驱动信息表得到目标端口物理位置信息,包括处理引擎号和端口号。端口物理位置信息将被填充到所有用来承载待发送数据包的信元头中。控制卡驱动模块通过控制卡把信元送到交换结构,而交换结构和处理引擎分别根据处理引擎号和端口号将信元转发到到目标端口。最后端口从接收到的信元中恢复出原始数据发出。
接收数据时,端口也会将数据拆分到若干信元中逐级上传。考虑到交换结构的循环优先机制,一个数据包上传的过程可能被来自其他端口的数据抢断。所以控制卡驱动模块对于接收到的信元按源端口位置信息(包括处理引擎号和端口号)保存到不同的缓冲区中。当接收到该数据包相关的全部信元,控制驱动模块即可重组该数据,并根据源端口位置信息查驱动信息表以得到指向该端口对应虚拟网络驱动实例的指针,进而激活该虚拟网络驱动实例接收数据。虚拟网络驱动实例从控制卡驱动模块中获取数据后,按照网络驱动的常规方式调用netif-rx接口向内核提交数据。数据收发实现结构如图4所示。
值得注重的是,在交换式路由器中,处理引擎通过交换结构交换的是IP包;而通用操作系统中网络驱动通常处理链路层的帧。即控制卡驱动模块数据通道对上对下的数据格式是不同的。因此,在发送数据时控制卡驱动模块需要从得到的链路帧中提取IP包再转发到端口;而接收数据时则对来自端口的IP包进行链路帧封装再向上提交。以以太网为例,需要恢复的包括源和目标站的物理地址、载荷类型和帧校验[3]。对于承载IP包的以太帧,显然其目标站物理地址和载荷类型[4]都是已知的。实现时采用的操作系统是Linux,通过在虚拟网络驱动源代码中进行设置可以使内核不进行帧校验[5]。所以只有源站物理地址未知。假如要求硬件给出真实的源站物理地址,则增加了硬件的复杂度;而若在控制卡驱动模块中伪造源物理地址,则可能导致内核的ARP治理混乱。为简化硬件设计,实现时采用了在控制卡驱动模块中伪造源物理地址的办法,同时修改虚拟网络驱动源代码,重载帧头处理函数[6]。这样内核ARP表就不受伪造地址的影响,其获取和刷新通过查询端口ARP记录实现。
2.2 控制通道的功能与实现
控制功能的通信也是基于信元的,其操作包括维护治理和表同步两类。维护治理主要是进行各种查询,通常通过若干次双向通信完成。每次通信有效载荷都只有几个字节,由一个信元即可承载。而表同步则是将上层软件维护的表复制到相关硬件中,包括ARP表、路由和分类表等。表同步操作涉及大量数据传输,需要由多个信元承载。控制功能都是针对设备进行的,所以在控制/反馈信元中也必须包括目标设备的物理位置信息。
在实际运行期间,所有的上层应用和设备之间的控制通信复用控制通道,其特点为:
(1)不同的应用可能同时访问同一设备;
(2)一个应用也可能同时访问多个设备;
(3)同一应用对于同一个设备的操作一般都是顺序的。
为支持这种复用操作,所有承载控制信息和反馈信息的头部除包括目标硬件的物理位置和操作指令外,还包括命令类型、应用类型信息。控制/反馈用信元结构如图5所示。
图5中:处理引擎号和端口号,确定设备的物理位置;收/发信元分别为该信元的源端口的和目的端口的对应值;命令码在设备和应用之间定义。每种可能的操作分配一个代码;应用码在控制卡驱动模块和上层应用之间预定义。每种可能的应用分配一个代码。这些应用包含网管、路由维护、硬件维护和ARP信息获取等。
上层应用通过内核调用陷井(IOCTL)发起控制通道操作,同时给出目标设备物理位置、命令类型代码和应用类型代码。控制卡驱动模块把这些信息填充到控制信元中再将其发往设备。设备把这些代码直接复制到反馈信元中,再在后面追加上反馈信息。控制卡驱动模块为每一种应用分配一个循环缓冲区,把收到的反馈根据应用类型排入相应队列中。上层应用从其所对应的循环缓冲区中读取反馈信元,然后根据信元中的物理位置信息、命令码就可以确定该反馈对应的原始命令,从而对反馈数据进行适当处理。这样就实现了各种控制功能对控制通道的复用。如图6所示。
3 结论
鉴于传统路由器体系结构和交换式路由器体系结构的区别,通用操作系统及在其上开发的路由软件无法直接应用于交换式路由器。本文提出的中间层方案可以有效地解决这个问题。该方案全面考虑了数据通信和治理维护方面的需求,为上层提供了与原有模型基本相同的接口,并使得路由软件在不损失其灵活性和可升级性的条件下直接应用于交换式路由器中。虽然该方案只是在特定的平台和特定的操作系统上得到了实现,但是不难看出,这种思路对操作系统并没有非凡的依靠性,完全可以移植到其他通用操作系统上。本文提出的方案已经在国家863项目实用化综合接入系统的高速边缘路由器的研制中取得了良好的实际效果。本文为国产高性能路由器的软件开发提出了一种高效快捷的解决方案,该方案具有良好的应用前景。