摘 要:文章简要介绍了PPPoE协议的内容,对PPPoE在基于嵌入式操作系统uCLinux的网络机顶盒中传统的用户空间实现方案进行了分析改进,提出并实现了效率较高的内核空间实现方案。
关键词:引 言
PPPoE(PPPover Ethernet)是在以太网中传播PPP(point-to-pointprotocal)帧信息的技术。这种技术将以太网技术和点对点协议结合在一起,综合了以太网多用户接入、低成本和PPP协议可加密、动态认证、IP地址动态分配、流量控制等优点,为宽带网提供了一种简便、实用、安全的接入方式,目前在ADSL宽带接入技术中使用PPPoE正逐渐成为主流。uClinux嵌入式操作系统由于具备免费、开放性、稳定性、可裁减性和可移植性等优点,近年来在嵌入式领域(如机顶盒、PDA 等)中得到了广泛的使用。目前,在标准Linux操作系统上已经有了一些开源的PPPoE客户端拨号软件。这些软件按其实现机制可划分为用户空间实现方案和内核空间实现方案。由于用户空间实现方案中所有数据包的PPPoE协议头都在用户空间封装和解封装,效率很低,并且这些软件主要是针对PC机开发的,不适合在以多媒体为主要业务的嵌入式网络机顶盒中采用。本文针对uClinux和嵌入式网络机顶盒的特点,提出了PPPoE在嵌入式网络机顶盒中的内核空间实现方案。
PPPoE协议PPPoE的建立过程可以分为PPPoE发现阶段和PPP会话阶段。图1 是PPPoE的协议帧格式,其中PPPoE数据报文的净载荷是由零个或多个TAG组成的,TAG包括3部分,即类型、类型值长度和值内容。
PPPoE发现阶段在发现阶段,PPPoE客户端以广播方式寻找可以连接的所有的访问集中器(AC,Access Concentration),并获得其以太网MAC地址。然后根据各访问集中器能提供的服务或用户的预先的一些配置来进行相应的选择。其报文交互过程如图2。
PPPoE会话阶段
PPPoE客户端根据与访问集中器协商得到的PPPoE会话ID和MAC地址,在该PPPoE连接上发起PPP协商建立一个PPP会话。建立一个PPP会话一般需要经历3个阶段:①LCP(Link ControlProtocol)协商阶段,主要协商MRU(最大接收单元)、魔术字和验证方式等选项。②CHAP或PAP认证阶段,这一阶段是可选的。③网络层协商阶段,这个阶段完成后PPPoE客户端即可获取一个IP地址,就可在其上完成各种业务了。
PPPoE在网络机顶盒中的实现
PPPoE在网络机顶盒中的实现可以有两种实现方案:即位于用户空间或是位于内核空间。
PPPoE的传统用户空间实现方案
图3是位于用户空间的实现方案,描述了用户空间实现方案的基本架构以及不同阶段的数据报文在用户和内核空间的走向。从图中可以看出,PPPoE进程首先创建一个以太网原始套接字来完成PPPoE的发现阶段。发现阶段完成后便进入到PPP会话阶段,这时PPPoE进程会启动一个PPPD守护进程。在uClinux系统中,PPP的功能被分成了两个部分,一个是位于内核的低级的PPP驱动程序部分,另一部分则是处理各种控制协议(LCP、认证和NCP等)的用户空间的pppd后台程序。当PPPD启动后会将PPP驱动器和一个伪tty 设备链接起来,使得PPP帧通过伪tty 设备传输。同时也会将PPPoE进程和这个伪tty 设备链接起来,这样当有数据包通过PPP接口传来时,PPPoE进程的标准输入就变的可读,于是,PPPoE进程就从标准输入读取数据,并将数据收集起来直到形成一个完整的PPP帧;当PPP帧形成后,PPPoE客户进程就将PPPoE帧的头部(header)和尾部(CHECKSUM)加到PPP帧上形成PPPoE帧,然后,通过在会话阶段创建的以太网原始套接字发送出去。
反之,当以太网卡收到一个PPPoE帧时,PPPoE户进程的以太网原始套接字就变的可读,于是,PPPoE进程通过该原始套接字读取PPPoE帧,并将PPPoE帧的头部和尾部去掉形成PPP帧,然后,将PPP帧写入标准输出;这时PPP驱动或PPPD会从标准输出取走PPP帧,并对其进行处理,若是IP数据报文,则将其送入IP协议栈;若是LCP、CHAP或IPCP等PPP协议报文,则在PPPD内部进行处理。这种方案实现起来相对简单,但是,其中致命的弱点就是效率低。从上面的分析可以知道,数据包需要在用户空间和内核空间来回拷贝,大大降低了效率,这在需要支撑多媒体业务的网络机顶盒中会产生显著的影响。因此,为提高效率,笔者将PPPoE报文的解封装模块移至uClinux系统的内核空间去实现。
PPPoE的内核空间实现方案
图4 是位于内核空间的实现方案,描述了内核空间实现方案的基本架构以及不同阶段的数据报文在用户和内核空间的走向。从图中可以看出,PPPoE进程同样也是使用以太网原始套接字来完成PPPoE的发现阶段过程,当进入会话阶段时PPPoE进程会生成一个虚拟终端设备pppox0,然后PPPoE进程执行原来PPPD守护进程的功能,将其协议包输入/输出重定向到该虚拟终端设备。并且PPPoE进程还负责已经建立起来的PPP链接的LCP以及NCP协议的交互过程。在uClinux中,PPP内核模块包含PPP虚拟网络设备驱动程序和PPP线路规程(LinEdisci-pline)两部分。当PPP链接建立时,PPPoE进程将会创建一个PPP虚拟网络设备ppp0。从内核的角度看,ppp0 同其它与实际物理设备绑定的网络设备(如eth0)一样,会参与到内核选路以及其它的内核机制。PPP线路规程主要实现PPP协议头的封装和解封装。
PPPoX内核模块为PPPoX虚拟终端设备的驱动程序。其主要功能是实现PPP底层承载协议头的封装和解封装,在此即实现PPPoE协议头的封装和解封装。PPPoX内核模块在uClinux内核中注册了一个PPPoE会话阶段的报文处理函数,当系统收到来自网络设备的PPPoE会话阶段(协议域为0x8864)的报文时,会将此报文交给该处理函数。该函数将解析并去掉报文的PPPoE协议头,并将它交给PPP线路规程的接收函数。在这个函数中将对PPPoE数据报文的内容进行判断。如果其数据内容为PPP协议报文,该接收函数将其加入到PPPoX虚拟终端设备的本地缓冲队列中,等待用户空间的PPPoE进程来读取,该进程根据PPP协议报文的类型再作出相应的处理;如果其数据内容为IP数据报文,该接收函数将会去掉该数据报文的PPP协议头,并调用内核提供的接口函数将其提交给内核的TCP/IP协议栈。在内核看来,该数据报文来自ppP虚拟网络设备,将与来自其它网络设备一样被决定用户空间的应用程序或是经由其它网络设备转发。
基于内核空间方案的PPPoE协议的实现流程
(1)配置和编译内核。进入源代码目录uClinuxdist/linux-2.4.x,在通过makEmenuconfig配置内核的选项以后,在.confiG配置文件中添加:CONFIG_PPPOE=y,这是因为在makEmenuconfiG中没有PPPOE配置项,需要自己手动添加。然后执行makEdep;接着在includE/linux/autoconf.h 中增加宏定义#definECONFIG_PPPOE1,最后执行make,这样就得到了需要的二进制内核映像image.bin。
(2)PPPoE协议的实现流程。PPPoE协议的实现流程如图5 所示,当PPPoE发现阶段完成后,打开字符设备文件/dev/ppp,并得到相应的文件描述符fd,接着调用ioctL(PPPIOC-CONNECT)将fD连接到PPP接口单元上,这样就可以用fD来读PPP接口单元的输出帧;调用ioctL(PPPIOCATTCHAN)将fD绑定到PPP传输通道上,从而可以用fD来向PPP传输通道上写入输入帧。作好了这些初始化工作后,接下来就进入到PPP会话阶段。
性能分析
从以上分析可知,内核空间实现方案对用户空间实现方案的改进之处在于将PPPoE协议头的封装和解封装的功能模块从用户空间(PPPoE进程)移到内核空间(PPPoX内核驱动)来实现,减少了数据包在用户空间和内核空间之间的拷贝次数,从而大大提高了PPPoE的效率。经过笔者对比验证,在基于600MHzDSP处理器的网络机顶盒上播放视频时,与用户空间实现方案相比,采用内核空间实现方案使处理器的占用率下降了10 至15 个百分点,其效果是非常显著的。
结束语
本文的创新之处在于将嵌入式网络机顶盒中PPPoE的传统用户空间实现方式改为了内核空间的实现方式,减轻了嵌入式处理器在PPPoE进程上的开销,从而可以有更多的CPU资源用在对多媒体的数据处理上,这对嵌入式网络机顶盒的开发厂商有很大的借鉴意义和实用价值。