分类: 嵌入式
2014-03-06 10:33:35
一、PPP协议介绍
1.PPP协议的组成
PPP协议包括两部分组成:一部分是数据链路控制协议(LCP);另一部分是网络控制协议(NCP)。
2.PPP链接的过程分析
PPP链接的建立过程分为三个阶段:创建,认证和网络协商阶段。创建阶段主要是工作是对基本的通信方式进行选择,链路两端的设备通过LCP向对方发 送配置信息分组,一旦配置信息分组被发送且被接收。就完成交换,进入LCP开启状态。认证阶段主要工作是客户机将自己的身份发送给远程的接入服务器,该阶 段使用一种安全的验证方式避免第三方窃取数据或冒充远程客户机服务器的链接。最常用的验证协议是(PAP)和(CHAP)。网络协商阶段的主要工作是调用 创建阶段协商的网络控制协议模块解决PPP链路上高层协议问题。
3.PPP包的封装格式
PPP的包封装格式为
其中协议字段决定了信息字段里信息的意义,协议字段包括:
0x0021——信息字段是IP数据报
0xC021——信息字段是链路控制数据LCP
0x8021——信息字段是网络控制数据NCP
0xC023——信息字段是安全性认证PAP
0xC025——信息字段是LQR
0xC223——信息字段是安全性认证CHAP
注意:在PPP包被封装在PPPOE中的时候,PPP包部分不包括F,A,C,FCS,F字段,即只有协议和信息字段。
二、PPPOE协议介绍
PADI:DUT向外广播,由PPPOE服务器接收的包,主要是完成PPPOE服务器的发现功能。
PADO:PPPOE服务器接收到DUT发来的PADI包后,解析PADI包中带点service name是否是PPPOE服务器可提供,如果是就向DUT回一个带有本机AC name tag的包。
PADR:当DUT接收到PPPOE服务器发来的PADO包,解析PADO包携带的AC name是否与DUT设置的AC name相同,如相同向PPPOE服务器发送一个session ID的请求包。
PADS:当PPPOE服务器收到DUT的session ID的请求包PADR后,向DUT发送带有session ID信息的包PADS。
PADT:终止PPPOE链接包。
其中:
版本,类型固定为0x01,代码根据不同阶段有不同的值。具体为:
0x00 PPP Session Stage
0x09 PPPOE Active Discovery Initiation (PADI) packet
0x07 PPPOE Active Discovery Offer (PADO) packet
0x19 PPPOE Active Discovery Request (PADR) packet
0x65 PPPOE Active Discovery Session-confirmation
会话ID是PPPOE服务器端分配给DUT的一个ID,在没有分配ID之前该字段为0000;长度域是指净载荷的长度,在discovery阶段净载荷部分的数据封装格式为:
其中类型为:
标记类型 标记说明
0x0000 表示PPPOE报文数据域中一串标记的结束,为了保证版本的兼容性而保留,在有些报文中有应用。
0x0101 服务名,主要用来表明网络侧所能提供给用户的一些服务。
0x0102 访问集中器名,当用户侧接收到了AC的回应的PADO报文时,就可获从所携带的标记中获知访问集中器的名子,而且还可以据此来选择相应的访问集中器。
0x0103 主机唯一标识,类似于PPP数据报文中的标识域,主要是用来匹配发送和接收端的,因为对于广播式的网络中会同时存在很多个PPPOE的数据报文。
0x0104 AC-Cookies,主要被用来防止恶意性DOS功击。
0x0105 销售商的标识符。
0x0110 中继会话ID,对于PPPOE的数据报文也同样可以像DHCP报文一样被中断到另外的AC上终结,这个字段则是用来维护另一个连接的。
0x0201 服务名错误,当请求的服务名不被对端所接受时,会在响应的报文中携带这个标记。
0x0202 访问集中器名出错。
0x0203 一般性错误。
长度为数据域长度。
在session阶段静载荷部分的数据封装格式为去掉F,A,C,FCS,F字段,即只有协议和信息字段的PPP协议数据单元。
三、内核空间中PPP与PPPOE实现
在内核中实现PPPOE链接的流程图为:
依照上图解释下各种数据包的的接收和发送流向,就pppoe連接來說主要有四種數據包,分别为pppoe discovery阶段数据包,pppoe session阶段数据包,ppp控制协议数据包和普通的数据包。下面就以上几种数据包流向做分析。
1.pppoe discovery阶段数据包
pppoe discovery阶段的所有包都是PPP守护进程通过包套接字直接eth驱动发送和接收pppoe数据包的,进而实现向网络适配器发送和接受pppoe 发现阶段的数据包。而对于数据包PADT有两种方式,当处于pppoe发现阶段时候是通过ppp守护进程操作包套接字实现PADT包的发送和接收的,当 pppoe链接处于session阶段的时候,PADT包是首先通过drivers/net/pppoe.c文件代表的PPPOE驱动接收和发送包,然后 ppp守护进程通过pppoe套接字与PPPOE驱动交互。
2.pppoe session阶段数据包和ppp控制协议数据包
对于pppoe session阶段和ppp控制协议数据包,如果该包是PADT和pppoe中继包,则该包通过PPPOE套接字发送给PPP守护进程。如果该包不是以上 两种包则给包会通过/drivers/net/ppp_generic.c文件代表的PPP驱动程序发送到PPP守护进程中。PPPOE套接字的各个功能 函数的创建过程为(drivers/net/pppoe.c):
pppoe套接字各个操作函数的注册过程
注:需要进步分析下用户空间的sock编程到此处注册的pppoe套接字的操作函数的调用流程.
PPP守护进程与PPP驱动程序的相互通信是通过/dev/ppp这个接口进行的,PPP通过open/read/write这些文件操作向ppp驱动发送和接受数据。
于是存在以下包的流程图:
PPP守护进程与通用PPP驱动之间的通信流程图
3.其他普通的数据包
对于其他普通的数据包,需要建立ppp0网络接口的支持。此时,PPPD守护进程会调用ioctl(PPPIOCNEWUNIT)创建一个网络接口 (ppp0),内核中的PPP协议模块(/deivces/net/ppp_generic.c)在处理PPPIOCNEWUNIT时调用 register_netdev向内核中注册ppp网络接口。于是通过ppp0接口从ip层向PPP驱动传递数据的流程图为:
IP层与PPP驱动之间的数据流动图
Ppp0接口的注册过程
实际的数据包在经过PPP驱动后(/drivers/net/ppp_generic.c),仍然需要经过pppoe驱动(/drivers /net/pppoe.c)然后传向eth驱动(/net/atm/br2684.c),最终从网络适配器将包发出去。因此需要解决PPP驱动与 pppoe驱动之间的包的传递和pppoe与以太网驱动之间包的传递流程。
PPP驱动与pppoe驱动间包的传递
Pppoe驱动与br2684驱动间的包的传递
四、用户空间PPP与PPPOE实现
用户空间pppoe实现流程图
如上图是pppoe在用户空间的实现流程图,从图中可以发现与内核中实现相比,在用户空间出现了pppoe的进程,以及伪终端主从设备。因此可以比较用户空间实现与内核空间实现的区别:
仿照上面内核空间实现分析下用户空间实现中各种数据包的流向,包括pppoe discovery,pppoe session,ppp建立链接阶段,ppp建立链接后等各个阶段。
1.pppoe discovery阶段
pppoe discovery阶段对应的函数为discovery(PPPoEConnection *conn)(rp-pppoe/discovery.c),此函数的作用是在pppoe discovery完成PADI,PADO,PADR,PADS及PADT包的发送与接收处理。此阶段是通过raw socket的形式直接把包发送到eth上的,也就是说此阶段只与pppoe进程有关,而与pppd进程无关。
2.pppoe session阶段
pppoe session阶段数据包的处理涉及两个方面pppd和pppoe进程。pppd进程负责生成ppp链接阶段需要的数据包,pppoe进程负责(rp- pppoe/pppoe.c中的session(PPPoEConnection *conn)函数)pppoe session阶段的数据包的处理,主要是从pppd进程那面接收数据,然后从通过raw socket从eth上发出去或者从eth上通过raw socket接收数据然后通过内核空间的tty驱动和PPP驱动的支持发送到pppd进程中。
3.ppp建立连接阶段
在ppp建立连接阶段数据包的处理主要是通过pppd进程,PPP驱动,tty驱动,pppoe进程协调进行的。首先pppd进程产生ppp链接阶 段的相关数据(在ppp/pppd/目录下对应每种ppp链接阶段的数据包都有相应的处理函数,以LCP阶段的数据为例对应的处理函数梭子的文件为 lcp.c,具体过程见下图),经过ppp驱动和tty驱动到达pppoe进程的session函数(rp-pppoe/pppoe.c中的 session(PPPoEConnection *conn)函数),在session函数中通过raw socket与eth相关联。
Pppd进程与pppoe进程之间的通信需要通过ppp驱动和tty驱动的,上图为发送的阶段的数据流程图。其中 ioctl(PPPIOCATTACH)将文件绑定到PPP接口单元上, 来读写PPP接口单元的输出帧,用ioctl(PPPIOCATTCHAN)将文件绑定到PPP传输通道上, 来读写PPP传输通道的输入帧。 ioctl(ppp_fd, PPPIOCCONNECT, &ifunit)是将ppp_fd和ifunit所对应的接口连接在一起,这样后终端和设备就连接到一起了,从PPP0端口出来的报文就发送到从 终端设备了,从终端设备上的数据也就传送到PPP0接口中去了。
4.ppp建立链接后阶段
ppp建立链接后应用层产生的数据包先经过ip层,经过路由找到ppp0接口,然后到达ppp驱动,在ppp驱动中对数据包进行ppp格式封装,完 成后经过tty驱动数据被传到pppoe进程的session函数,经过pppoe格式的封装后通过raw socket发往eth。
五、总结
以上是对pppoe内核空间实现和用户空间实现的代码分析,总的来说区别就是pppoe封装的位置,前者是在内核驱动中实现的,后者是在用户空间中 实现的。由此导致数据包的流动过程有很大差别。而且从上面分析可以看出在用户空间实现过程中由于ppp数据包要经过一个用户空间(应用程序/pppd进 程)-->内核空间(ppp驱动和tty驱动)----->用户空间(pppoe进程)-------->内核空间(raw socket)的过程,所以效率有所下降。如我们的datastore才采用的是用户空间实现的方式,如果改为内核空间实现理论上效率将有很大的提升。