pppoe

所分析的代码:rp_pppoeV3.11; ppp 2.4.4;

rp-pppoe 会创建sock与client进行会话;这个sock是普通的sock,而没有用到pppoe内核模块提供的新的sock。 收到PADS后会调用stratPPPD()来启动pppd,这有两种方式,一种是用户态调用,另一种是kernel态调用,由启动pppoe时的选项-k控制。

pppoe调用的pppd和我们平时用的不一样,并不是pppdttyS0 …这种。 而是pppdplug-in “nic-eth0”  rp-pppoe-session。 这样其实是用到了pppd的plugin功能。ppp2.4.4里面有个plugin目录里面有pppoe、radius等。rp-pppoe也有一个plugin.c。 比较了一下和pppd里面的plugin几乎一样,如果编译pppd时打开plugin的话应该用的是pppd的plugin。

在linuxkernel里也提供了对pppoe的支持。具体的在pppoe.c文件中。 在这个文件里提供了一套pppoe的socket; 同时还把对pppoe报文的处理函数(pppoe_rcv())挂到了ptypeall上。ip_rcv()也是挂在ptypeall上的。

pppoe_rcv()会根据pppoe的头,根据po = get_item(ph->sid,eth_hdr(skb)->h_source, dev->ifindex);找到相应的sock,然后调用sk_receive_skb(); 这个函数里:

                if(!sock_owned_by_user(sk)) {

                                /*

                                 * trylock + unlock semantics:

                                 */

                                mutex_acquire(&sk->sk_lock.dep_map,0, 1, _RET_IP_);

 

                                rc= sk->sk_backlog_rcv(sk, skb);

 

                                mutex_release(&sk->sk_lock.dep_map,1, _RET_IP_);

                }else

                                sk_add_backlog(sk,skb);

!sock_owned_by_user(sk)) 是什么意思还没完全清楚!!    rc = sk->sk_backlog_rcv(sk, skb); 就是pppoe 内核模块初始化时定义的sk->sk_backlog_rcv= pppoe_rcv_core;


pppoe_rcv_core() 会根据这个sock的状态调相应的处理函数:

如果sk->sk_state& PPPOX_BOUND则进入ppp_input();

如果sk->sk_state& PPPOX_RELAY,则__pppoe_xmit()转发出去; 

其它情况调用sock_queue_rcv_skb()进入标准的socket处理(其实就是放到sock的rx队列尾部,即skb_queue_tail(&sk->sk_receive_queue,skb);标准的sock函数会读取这个数据 )。 

PPPOX_BOUND这个是在要建立相应的ppp interface时设置的。如ppp0,ppp1时。也就是说:只要pppx接口建立了,数据就全部走ppp_input()了。

 

ppp2.4.5的plugin里面的pppoe提供了类似pppd里面tty.c的功能。 它用了pppoe内核模块创建的sock(AF_PPPOX),是标准的sock操作,如先创建sock,在connect,然后rx/tx等; 而tty.c则是open一个ttyS0这种串口来建立连接。

下面就是这个plugin函数提供的类似tty.c的功能。

struct channel pppoe_channel = {

    options: Options,

   process_extra_options: &PPPOEDeviceOptions,

    check_options:pppoe_check_options,

    connect:&PPPOEConnectDevice,//创建sock,并connect。其实调用pppoe_connect。

    disconnect:&PPPOEDisconnectDevice,

    establish_ppp:&generic_establish_ppp,

    disestablish_ppp:&generic_disestablish_ppp,

    send_config: NULL,

    recv_config:&PPPOERecvConfig,

    close: NULL,

    cleanup: NULL

};

PPPOEConnectDevice,//创建sock,并connect。其实调用pppoe_connect。在pppoe_connect()中调用ppp_register_channel()把pppoe_chan_ops注册到pppgeneric层中。

static struct ppp_channel_ops pppoe_chan_ops = {

                .start_xmit= pppoe_xmit,

};

pppoe_xmit最终会调用dev_queue_xmit(skb);来发送数据。



rp_pppoe V3.11 里面的pppoe_server.c是pppoe的server端的代码。下面是pppoe server main()的主要的代码:

main()

{

初始化;

参数解析:

  -i:   指明使用哪个interface 一般类似 eth0;

  -k:   是否用ppp的内核模式在调用pppd是会有些不同;

    /* Open all theinterfaces */

    for (i=0;i<NumInterfaces; i++) {

                interfaces[i].mtu= 0;

                interfaces[i].sock= openInterface(interfaces[i].name, Eth_PPPOE_Discovery, interfaces[i].mac,&interfaces[i].mtu); //创建sock

}

 

………….

   /* Create event handler for each interface */

   for (i = 0; i<NumInterfaces; i++) {

            interfaces[i].eh= Event_AddHandler(event_selector,

                                                                                interfaces[i].sock,

                                                                                EVENT_FLAG_READABLE,

                                                                                InterfaceHandler,

                                                                                &interfaces[i]);//处理函数InterfaceHandler

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值