首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于Linux内核模式的PPPoE优化与实现(1)

基于Linux内核模式的PPPoE优化与实现(1)

PPPoE(Point.to.Point Protoeol over Ethernet)是将PPP协议封装在以太网帧上进行传输,它的通信过程分为探测(Discovery)和PPP会话(Session)2个阶段。PPPoE Discovery阶段主要是客户机确定AC(Access Concentrator)以及客户机与AC协商Session ID。而PPPoE Sess-ion用于完成数据包的接收与发送,同时它也用于完成PPP链路的协商(LCP),以及网络层的控制协商(IPCP)等。
传统的PPPoE先会用Raw socket读取数据,然后采用用户态程序对其封包解包,然后再发送给内核。但是这种方法会引起大量的内核空间与用户空间的上下文切换,从而带来不必要的开销。而对于实现于内核态的PPPoE,它会把所有的封包以及解包实现于内核,这样就大大提高PPPoE的效率。
1 PPPoE协议概述
1. 1 PPPoE Discovery阶段
在PPPoE Discovery阶段,客户机首先广播一个PADI(0x09)帧。收到PADI帧的一个或多个服务器会发送PADO(0x07)帧,这个包中包含了服务器的各种标识。然后,客户机会选择其中一个服务器发送PADR(0x19),表明主机选择了这个服务器。最终,收到PADR(0x65)帧的服务器会为新的会话分配资源并向客户机发送PADS(0x65)。当此阶段完成,这两次的对话完成了SESSION_ID以及双方物理地址,为后续数据会话打好基础。
同时PPP协议还提供了一个PADT请求,该请求用于结束这次PPPoE会话。这个请求可以由任何一方发出,同时代表这次回话的结束,图1描述整个discovery过程。

1.2 PPPoE Session阶段
PPPoE Discovery阶段是为整个PPPoE会话获取双方物理地址以及Session_ID,这个Session_ID就成为了双方的通信凭证,在整个会话过程中保持不变。PPP帧数据被封在以太帧中,它在以太帧的标识为0x8864,当碰到0x8864时,就认为是一个PPPoE包。
在PPPoE Session阶段,PPPoE除数据传输以外,还提供了链路的协商(LCP),以及网络层的控制协商(IPCP)等其他服务。对于LCP,它主要用于配置和测试数据通信链路,用来协商PPP协议的一些配置参数选项;处理不同大小的数据帧:检测链路环路和一些链路的错误;终止一条链路,其作用类似于IP层的ICMP协议。而对于IPCP,它主要用于动态地协商客户机与服务器双方IP,实际的数据报文交换过程中主要涉及Config-Request、 Config-Ack、Config-Nak和Config-Re-ject。图2描述IPCP协商IP的过程。

2 PPPOE设计实现
从上述PPPoE协议描述中,了解到整个PPPoE会话包括Discovery、链路协商和数据传输3种交互。这3种数据中,数据传输最重要,数据量最大。对于用户空间模式的PPPoE,数据包收发需要通过pty,由用户空间的PPPoE进程处理PPPoE包头后通过Raw socket收发。也就是说所有的PPPoE数据封包结果都在用户空间执行,这样就大大增加了内核空间与用户空间数据切换的次数。为了减少这种开销。这里采用一个内核模块来处理数据的封包解包,这样就大大减少了内核空间与用户空间数据切换的次数,提高效率。所以对内核空间模式的PPPoE的处理策略是:Discovery以及链路协商交互全部在用户空间完成,而数据的封解包则通过一个内核模块在内核空间完成。
2.1 PPPoE会话初始化
PPPoE的初始化包括整个Discovery阶段以及Session阶段的IPCP和LCP等其他链路协商过程,所有的工作都在用户空间完成,图3描述了整个初始化的流程。

首先通过Raw socket发送PADS、PADR、PADO、PADI,当这个请求完成后,得到远端服务器的MAC地址以及双方建立起来的Session_ID。由于后面的内核封包需要用到这些数据,所以需要将这些数据切换到内核空间去。由于数据量较小,则采用proc文件系统完成内核空间与用户空间的数据切换。
对于proc中的数据,设计以下数据格式:接口名词SMAC DMAC SESSION_ID RX TX。
其中“接口名词”为接口名称,设计中不再用虚拟PPP接口传输数据,而是将数据迁移到物理网卡上,这样在某种程度上减轻了路由模块的负担,但需要去proc文件读取接口名称以此判断该物理接口是否启用PPPoE拨号。“SMAC”和“DMAC”参数为双方的MAC地址,在内核封包中用到。 “SESSION_ID”双方建立起来的Session_ID,也用于内核封包。而“RX”和“TX”是用于记录最后一次解包与封包的时间点,该数据用于按需拨号。
在建立好PPP连接后就进行IPCP协商,这个过程将为协商到双方的IP的地址,并将这个IP地址配置到物理口上,而这些数据将通过PPP口通信。除此之外,还需要为PPPoE链路配置相应的路由、更新ARP列表以及获取相应的DNS服务器地址。
2.2 PPPoE数据接收
PPPoE数据接收主要是对数据进行解包,其全部动作在内核空间完成。当一个PPPoE数据包从网卡驱动里面读出来时,是一个完整的PPPoE 包。而上层模块无法识别这样的包,所以需要将中间的那些PPP协议数据从包中剥离出来,使其变成一个普通的IP数据包,图4描述了PPPoE接收数据的整体流程。

当从网卡驱动上读取数据时,也就是获取数据的SKB,首先需要判断这个SKB是否有效,然后再判断该网卡是否起动了PPPoE服务,很显然这里需要读取proc的接口信息。如果已经PPPoE拨号服务,还需要判断该包是不是一个LCP或者IPCP等其他协商数据,也就是判断协议域的数据是不是 0X0021。因为如果是协商数据,则不需要解包,而直接将其转发到PPP虚拟接口上。对于具体的解包过程将进行代码分析。解完包以后该数据包就属于普通的IP包,后续流程与普通的IP包处理相同。
返回列表