PPP/PPPOE源码阅读笔记

一.缘起

       本人工作与网关产品有关,经常会接触到pppoe协议,但对ppp和pppoe是如何实现的不甚了解。在网上查找相关的文章大多是描述ppp/pppoe协议的具体内容和数据流大的流程,而未过多的涉及内核中pppoe驱动和ppp驱动代码实现的细节,正好这段时间在看毛德操和胡希明老师的《Linux内核源代码情景分析》,看了内核中的终端驱动,遂决定仔细学习一下PPP/PPPOE驱动这一块的内容并将这段时间的收获记录下来,以便以后翻阅同时也与大家分享。

二.关于本文

      本文不会涉及ppp协议和pppoe协议本身,即不会讨论如LCP,PAP,CHAP,IPCP,  PADI等这些报文的格式等内容,如果您仅仅想了解的是ppp和pppoe协议本身,那这篇文章并不适合你。

     如果你想了解ppp和pppoe驱动,想了解ppp程序是怎么建立起ppp网络接口的,以及ppp网络接口如何将数据通过具体的网络接口(比如eth0)发送的,具体的网络接口(比如eth0)收到数据后是怎样将数据给ppp网络接口的那这篇文章正好适合你。

    阅读本文时建议将各个部分的流程图先复制下来保存在一个文档中,然后对照着流程图来看代码。

三.代码链接

ppp代码下载链接 http://mirrors.aliyun.com/ubuntu/pool/main/p/ppp/ppp_2.4.7.orig.tar.gz

Linux-2.4.0代码下载链接https://mirrors.edge.kernel.org/pub/linux/kernel/v2.4/linux-2.4.0.tar.gz

四.代码分析

1.内容预览

       pppd命令

       ppp代码创建ppp网络接口

       pppoe驱动建立channel

       ppp驱动建立ppp网络接口并与pppoe建立的channel关联

      ppp网络接口和ppp程序收包过程

      ppp程序和ppp网络接口发包过程

2.pppd命令

pppd plugin /usr/lib/rp-pppoe.so nic-pon0.30 linkname internet nodefaultroute noipdefault noauth default-asyncmap hide-password nodetach usepeerdns mtu 1492 mru 1492 noaccomp nodeflate nopcomp novj novjccomp user aaa lcp-echo-interval 20 lcp-echo-failure 10 nopersist

3.ppp代码创建ppp网络接口

 

[ppp-2.4.7]main.c中

[ppp-2.4.7]options.c

[ppp-2.4.7]options.c 中general_options

 

 

4.pppoe驱动建立channel

 

the_channel->connect()为PPPOEConnectDevice,这个函数比较长我们分段来看

 Linux代码

 

上图中proto[protocol]->create即为pppoe_create,因为协议为PX_PROTO_OE,在pppoe_init中注册

 

 

回到PPPOEConnectDevice函数(续1)

 在openInterface中会创建socket并绑定接口,如下两图所示

 

 

 创建socket成功后回到PPPOEConnectDevice函数会调用discovery()函数进行pppoe协议的交互

接着看PPPOEConnectDevice函数(续2),会调用connect函数

connect函数会调用内核中的pppoe_connect,这个函数包含在pppoe_ops中,在pppoe_create中设置到sock->ops,即与我们conn->sessionSocket相关的参数中,这一过程可回看上面。

 ppp_register_channel函数会生成struct channel *pch,把pch->chan 设成 chan,并把pch放到all_channels中

5.ppp驱动建立ppp网络接口并与pppoe建立的channel关联

回到ppp的auth.c的函数start_link中the_channel->establish_ppp()为generic_establish_ppp

需要注意函数中的fd有改变开始时fd为PPPOEConnectDevice函数的返回值conn->sessionSocket,对它调用ioctl 会走到linux的

pppox_ioctl函数,该函数返回PPPOEConnectDevice[ppp代码中的plugin.c]函数调用connect创建的channel的index

接着来看 generic_establish_ppp中对fd为"/dev/ppp"调用PPPIOCATTCHAN,make_ppp_unit和PPPIOCCONNECT的动作

 

调用ioctl会调用ppp_ioctl函数

 PPPIOCATTCHAN时回去找channel,很显然就是找到之前pppoe在connect创建的那个channel

 

ppp中make_ppp_unit会调用PPPIOCNEWUNIT

 

 

 

通过网络接口ppp0(假设为这个名字)发送数据时就会调用ppp_start_xmit,后面再看这个函数。

generic_establish_ppp函数中接着会调用PPPIOCCONNECT,通过ppp_connect_channel就将pppoe创建的channel和

ppp网络设备联系在一起了

 

6.ppp网络接口和ppp程序收包过程

回到ppp的main函数中看ppp程序是如何接收ppp协议的数据的  

 

 

 

内核接收数据过程

 

 

 

 

 

 

 

 

 

通过ppp_receive_nonmp_frame函数大家可以看到根据收到的数据包的协议是ppp控制包还是普通网络包比如ipv4包,走不同的分支,如果是ppp协议控制包就将其放到ppp->file.rq中,我们的ppp程序会收到这个包,如何是普通的网络包就通过netif_rx进入网络协议栈。

7.ppp程序和ppp网络接口发包过程

 

    

 

这个pch->chan->ops->start_xmit(pch->chan, skb)调用的是pppoe_xmit,接下来我们看为什么是pppoe_xmit

这个channel是通过pppoe套接字然后调用connect方法创建的,创建时po->chan.ops = &pppoe_chan_ops;所以start_xmit就是pppoe_xmit

 

 

  • 6
    点赞
  • 2
    评论
  • 14
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 2 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

kh815

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值