9.4 Implementation in the Linux Kernel

   


Together with kernel Version 2.4, PPPoE support was integrated in the pppd daemon, and the kernel was expanded by a connection between the generic PPP driver and the Ethernet network card.

Figure 9-5 shows the interaction between these components. The PPPoE driver assumes several functions within the kernel. To the lower layer (i.e., the Ethernet card and the driver software), the PPPoE driver plays the role of a layer-3 protocol. As we will see later in more detail, incoming Ethernet packets are allocated to a protocol matching the type identifier in the Ethernet frame (e.g., the IP protocol or the PPPoE protocol for the ethertype values 0x8863 and 0x8864 mentioned earlier). Towards the higher-layer generic PPP driver, which was described in the previous chapter, the PPPoE driver behaves much as does the asynchronous PPP driver. In contrast to that driver, however, the PPPoE driver does not implement a tty operating mode.

Figure 9-5. Communication between pppd and the PPP and PPPoE drivers.

graphics/09fig05.gif


To initiate the PPPoE discovery stage of pppd in the user space, it is additionally necessary to have the PPPoE driver and pppd communicate directly. Section 9.4.2 discusses this communication in detail.

9.4.1 Changes to the Kernel

The PPPoE driver, which is included in kernel Version 2.4 and higher in experimental form, consists of the file drivers/net/pppoe.c. In addition, there is a file called drivers/net/pppox.c, which is intended to harmonize present and future PPP implementations in the kernel. General functions that previously were used only by the PPPoE implementation were moved to the file pppox.c, and other PPP implementations over other networks should be available in the future.

Functions and Data Structures of the PPPoE Driver

In the first step, the PPPoE driver registers the PPPoE protocol with the kernel. This can be seen in the following piece of source text:

pppoe_init()

drivers/net/pppoe.c


 { Use a function from drivers/net/pppox.c to register the PPPoE protocol: int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); if (err==0) {         dev_add_pack(&pppoes_ptype);         /*Add a packet handler         for incoming packets of type ETH_P_PPP_SES         (PPPoE session packets), which points to pppoe_rcv */         dev_add_pack(&pppoed_ptype);         /*Add a packet handler for incoming packets of type         ETH_P_PPP_DISC (PPPoE connection setup packets), which         points to pppoe_disc_rcv */         register_netdevice_notifier(&pppoe_notifier);         /*Add to netdevice notification chain */         proc_net_create("pppoe", 0, pppoe_proc_info);         /*Generate an entry in the proc directory */ } return (err); } 

Subsequently, the PPoE driver provides functions that can be used by pppd to access the PPPoE protocol functionality over a PPPoE socket. The structure struct proto_ops pppoe_ops in driver/net/pppoe.c is used to bind the functionality of the PPPoE socket to general socket functions (e.g., connect(), sendmsg(), rcvmsg(), and bind()). Chapter 26 includes a more detailed description of how sockets are implemented in the Linux kernel.

pppoe_create()

drivers/net/pppoe.c


This function is invoked whenever a new PPPoE socket is opened. The function is exported and announced over the structure pppoe_proto and the function register_pppox_proto().

pppoe_connect()

drivers/net/pppoe.c


This function calls connect() at the PPPoE socket interface. If the call is successful, then PPPoE packets that have previously been sent or received over the specified Ethernet card can be accessed over the PPPoE socket in the application layer.

pppoe_sendmsg()

drivers/net/pppoe.c


The function pppoe_sendmsg() is used to pack data sent by pppd to the PPPoE socket into PPPoE packets and send them over the Ethernet.

pppoe_rcvmsg()

drivers/net/pppoe.c


This function serves to receive PPPoE packets over the PPPoE socket. However, only packets belonging to the discovery stage of the PPPoE protocol are processed; all other packets are instead forwarded to the generic PPP driver. Information about whether the PPPoE protocol is in the discovery stage or in the session stage is saved in sk->state.

Finally, once the PPPoE discovery stage is completed, incoming packets are forwarded to the generic PPP driver. (The case of PPPoE relay is not discussed here.) Various functions can be used to receive packets:

pppoe_rcv()

drivers/net/pppoe.c


This function is executed within the NET_RX tasklet. It handles error cases and passes packets to the function pppoe_rcv_core() for further processing.

pppoe_rcv_core()

drivers/net/pppoe.c


This function determines the dependency on the phase of the PPPoE protocol stored in sk->state, which means that an incoming packet is either forwarded to the generic PPP driver (by the function ppp_input()) or appended to the queue of the PPPoE socket by the function sock_queue_rcv_skb(), where it will be further processed by the above mentioned function pppoe_rcvmsg().

pppoe_disc_rcv()

drivers/net/pppoe.c


This function is invoked whenever a packet of the PPPoE discovery stage was received (ethertype 0x8863 or ETH_P_PPP_DISC, as defined in linux/if_ether.h). However, the function pppoe_disc_rcv() serves only to receive PADT packets; all other packets are rejected. If an incoming packet is a PADT packet, then the PPPoE connection is disconnected and the socket is released.

pppoe_xmit()

driver/net/pppoe.c


This function is invoked by the generic PPP driver. It serves as wrapper for the function __pppoe_xmit().

_pppoe_xmit()

driver/net/pppoe.c


This function is used to pack transmit data of the generic PPP driver into a PPPoE frame and send it over the specified Ethernet network card.

9.4.2 Tasks of the ppp Daemon

A data connection is established in several phases. The phase of the PPPoE discovery stage is fully handled by the ppp daemon, avoiding the pppoe driver. Special packet sockets are included in kernel Version 2.4 (see Chapter 26) and can be used to send or receive packets specified in RFC 2516 directly to or from the network card. If the discovery stage is successful, then the ppp daemon sets up a ppp interface in the kernel. The ppp daemon achieves this by opening a PPPoE socket and binding this socket to the PPPoE driver. Finally, the ppp daemon uses an ioctl() call with the parameter PPPIOCGCHAN (implemented in driver/net/pppox.c) to set the field sk->state to PPPOX_BOUND.

As was described in the previous section, this causes the PPPoE driver to forward all incoming packets to the generic PPP driver, except for the PPPOE relay case, which is not considered here, and for PADT packets, which are handled by the function pppoe_disc_rcv() (as already described). The ppp daemon can use different ioctl() calls over the PPPoE socket to change other parameters. However, the data path always leads over the generic PPP driver, from which the PPPoE driver now accepts PPP packets (data and control packets); it packs them and, eventually, passes them to the network card.

9.4.3 Configuration

To be able to use PPPoE in Linux from kernel Version 2.4 and higher, the option PPPoverEthernet and the option Packet Socket have to be activated in the kernel configuration upon compilation (via activation of the support for experimental drivers). If the PPPoE support is compiled as a module, then we additionally have to add the line "alias net-pf-24 pppoe" to the file /etc/modules.conf. This line is used to allocate the protocol with identifier 24 to the pppoe module. A package that integrates PPPoE extensions is available for pppd. All we have to do is to complete the file /etc/ppp/options by adding the line plugin pppoe; pppd can then be started with pppd eth0. [Ostr01] includes more installation instructions.


       


    Linux Network Architecture
    Linux Network Architecture
    ISBN: 131777203
    EAN: N/A
    Year: 2004
    Pages: 187

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net