热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PPPOE源码分析

一、PPPOE协议简介1、Discovery阶段此阶段用来建立连接,当一个用户主机想开始一个PPPoE会话时,首先必须进行发现阶段以识别PPPoESer

一、PPPOE协议简介

1Discovery阶段

  此阶段用来建立连接,当一个用户主机想开始一个PPPoE会话时,首先必须进行发现阶段以识别PPPoE Server的以太网MAC地址,并建立一个PPPoE会话标识(Session ID)。

1-1 Discovery阶段的基本工作流程

 

如图1-1所示, Discovery阶段由四个步骤组成,下面将介绍它的基本工作流程。

 

  • PADI:如果要建立一条PPPoE连接,首先PPPoE客户端就要以广播的方式发送一个PADI(PPPoE Active Discovery Initiation)数据包,PADI数据包包括客户端请求的服务。
  • PADO:当PPPoE服务器收到一个PADI包之后,它会判断自己是否能够提供服务,如果能够提供服务的话,就会向客户端发送PADO(PPPoE Active Discovery Offer)数据包来进行回应。PADO数据包包括PPPoE服务器名称和与PADI数据包中相同的服务名。如果PPPoE服务器不能为PADI提供服务,则不允许用PADO数据包响应。
  •  PADR:由于PADI是以广播的形式发送出去的,PPPoE客户端可能收到不止一个PADO数据包,它将审查所有接收到的PADO数据包并根据其中的服务器名或所提供的服务选择一个PPPoE服务器,并向选中的服务器发送PADR(PPPoE Active Discovery Request)数据包。PADR数据包包括客户端所请求的服务。
  • PADS:当PPPoE服务器收到客户端发送的PADR包时,它就准备开始一个PPPoE会话,它为PPPoE会话创建一个唯一的PPPoE会话ID,并向客户端发送PADS (PPPoE Active Discovery Session- confirmation)包作为响应。

 

  当发现阶段正常结束后,通信的两端都获得会话标识(Session ID)和对方的MAC地址,它们一起唯一定义一个PPPoE会话。

 

2PPP会话阶段

PPPoE进入PPP会话阶段后,客户端和服务器将进行标准的PPP协商,PPP协商通过后,数据通过PPP封装发送。PPP报文作为PPPoE帧的净荷被封装在以太网帧内,发送到PPPoE链路的对端。Session ID必须是Discovery阶段确定的ID,且在会话过程中保持不变,MAC地址必须是对端的MAC地址。

 

Rp_pppoeppp实现pppoe协议的过程

 

 

二、rp-pppoe代码简释

1、首先,我们会运行一个pppoe-server的程序,该程序主要建立pppoe链路,处理各种pppoe包。其中有以下代码:

for (i = 0; i

       interfaces[i].eh = Event_AddHandler(event_selector,

                                       interfaces[i].sock,

                                       EVENT_FLAG_READABLE,

                                       InterfaceHandler,

                                       &interfaces[i]);

#ifdef HAVE_L2TP

       interfaces[i].session_sock = -1;

#endif

       if (!interfaces[i].eh) {

           rp_fatal("Event_AddHandler failed");

       }

    }

为每个物理接口绑定事件,当有数据包到来时就执行InterfaceHandler函数,该函数调用serverProcessPacket函数,处理收到的各种pppoe相关的包。

 

switch(packet.code) {

    case CODE_PADI:

       processPADI(i, &packet, len);

       break;

    case CODE_PADR:

       processPADR(i, &packet, len);

       break;

    case CODE_PADT:

       /* Kill the child */

       processPADT(i, &packet, len);

       break;

    case CODE_SESS:

       /* Ignore SESS -- children will handle them */

       break;

    case CODE_PADO:

    case CODE_PADS:

       /* Ignore PADO and PADS totally */

       break;

    default:

       /* Syslog an error */

       break;

    }

 

其中对PADR处理,调用processPADR函数,向客户端发回一个PADS后,就调用PPPD:

 

sendPacket(NULL, sock, &pads, (int) (plen + HDR_SIZE));

startPPPD(cliSession);

 

rp-pppoe包中有个pppoe.c的文件,这个是pppoe的客户端,这个pppoe.c分两个阶段处理:discovery阶段和session阶段。Discovery阶段,客户端的pppoe跟服务器的pppoe-server打交道(发送PADI,接收PADO,发送PADR,接收PADS),让pppoe-server调用pppd建立ppp接口;session阶段,服务器在建立了ppp接口后,pppd根据协议会调用pppoe,生成一个服务器端的pppoe(根据判断,直接跳过discovery阶段),跟远端的pppoe进行session阶段的通信。

Pppoemain函数最后,调用了session函数,该函数实现session阶段数据的读写操作:

session(&conn);

 

session函数调用两个读函数来进行数据的传输工作:

asyncReadFromPPP:从ppp接口读取数据,并发送到以太网

asyncReadFromEth:从以太网读取数据,并发送到ppp

 

ppp——客户端pppoe——以太网——服务器pppoe——ppp

 

Pppoe好像起到转发的作用,其实际是打包与拆包。

 

 

Pppoe流程如下图:

2、现在说下pppd的过程

首先说说pppd的相关读写原理

应用程序通过socket 接口发送TCP/IP数据包,pppdmake_ppp_unit函数中 调用ioctrl(PPPIOCNEWUNIT)创建一个网络接口(如ppp0),内核中的PPP协议模块在处理PPPIOCNEWUNIT时,调用 register_netdev向内核注册ppp的网络接口,该网络接口的传输函数指向ppp_start_xmit

当应用程序发送数据时,内核根据IP 地址和路由表,找到ppp网络接口,然后调用ppp_start_xmit函数,此时控制就转移到PPP协议处理模块了。ppp_start_xmit 用函数ppp_xmit_process去发送队列中的所有数据包,ppp_xmit_process又调用ppp_send_frame去发送单个数据 包,ppp_send_frame根据设置,调用压缩等扩展处理之后,又经ppp_push调用pch->chan->ops-> start_xmit发送数据包。

pch ->chan->ops->start_xmit是具体的传输方式了,比如说对于串口发送方式,则是 ppp_async.c: ppp_asynctty_open中注册的ppp_async_send函数,ppp_async_sendppp_async_push函数调用 tty->driver->write把数据发送串口。

 

Ppp在调用tty时,会根据协议,调用其他协议脚本来进行封装,pppd就是在这里调用pppoe,让其产生服务器端的pppoe,把ppp封装成pppoe包,与客户端的pppoe进行session阶段的通信。


推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
  • 本文详细解析了 Android 系统启动过程中的核心文件 `init.c`,探讨了其在系统初始化阶段的关键作用。通过对 `init.c` 的源代码进行深入分析,揭示了其如何管理进程、解析配置文件以及执行系统启动脚本。此外,文章还介绍了 `init` 进程的生命周期及其与内核的交互方式,为开发者提供了深入了解 Android 启动机制的宝贵资料。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 本文探讨了 Kafka 集群的高效部署与优化策略。首先介绍了 Kafka 的下载与安装步骤,包括从官方网站获取最新版本的压缩包并进行解压。随后详细讨论了集群配置的最佳实践,涵盖节点选择、网络优化和性能调优等方面,旨在提升系统的稳定性和处理能力。此外,还提供了常见的故障排查方法和监控方案,帮助运维人员更好地管理和维护 Kafka 集群。 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在Kohana 3框架中,实现最优的即时消息显示方法是许多开发者关注的问题。本文将探讨如何高效、优雅地展示flash消息,包括最佳实践和技术细节,以提升用户体验和代码可维护性。 ... [详细]
  • MySQL数据库安装图文教程
    本文详细介绍了MySQL数据库的安装步骤。首先,用户需要打开已下载的MySQL安装文件,例如 `mysql-5.5.40-win32.msi`,并双击运行。接下来,在安装向导中选择安装类型,通常推荐选择“典型”安装选项,以确保大多数常用功能都能被正确安装。此外,文章还提供了详细的图文说明,帮助用户顺利完成整个安装过程,确保数据库系统能够稳定运行。 ... [详细]
author-avatar
joyjz
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有