Pppoe user space implementation
One Terminal
Terminal Introduction
A terminal is a type of terminal device. It has multiple types and generally uses tty for short. The following figure shows the connection between the computer system and the terminal.
The main function of the Terminal Driver is to transmit data between the program and related devices. Within a Linux kernel, the terminal basically includes two main software parts: Device Drivers and line rules (see ).
A device driver is a low-level software written to a specific hardware that allows computers to interact with terminals.
A row rule is used to perform logical processing of a series of input and output data, and map a series of characters to others.
Pseudo Terminal
A Pseudo Terminal (Pseudo Terminal) is a pair of logical terminal devices. It creates a Pseudo Terminal Device on a Linux system and uses the "Pty master" method, such as/dev/ptm3, the corresponding end is automatically created as/dev/pts/3.
The data input from the Pseudo Terminal is the input from the master device of the Pseudo Terminal, and vice versa.
Ii. pppoe Overview
The pppoe protocol is based on the PPP protocol. The PPP protocol is not implemented in the pppoe application. The PPP protocol is implemented by the pppd user space program, the pppoe program only implements Part Of The pppoe protocol code. When appropriate, the pppd program implements the PPP protocol.
After connecting the pppoe user program to the pppoe server, he will establish a ppp0 device, which is carried out in the pppd program. If the connection is successful with the server, he will always exist, this device is the same as a normal Nic device, but it is a virtual device. When data from this device is sent, it is still sent from the interface of the real Nic device, but this has been converted in the system.
Tripppd
As mentioned above, pppd is the Implementation Program of the PPP protocol. The implementation of PPP consists of four parts.
The pppd program will first perform initialization and read parameter setting parameters. This is very important and will be analyzed during code reading.
Then the protocol is started. The Code flow is shown below:
Main. C-> main ()
{
Read Parameters
Set parameters
Starting from the LCP protocol, this is the beginning of the entire protocol, and the state machine starts to launch
Lcp_lowerup (0 );
Lcp_open (0);/* Start Protocol */
Below
While (phase! = Phase_dead ){
Handle_events ();
Get_input (); wait for the data packet to enter and process the packet according to the state machine
............
............
}
}
The PPP protocol has an important relationship with pppoe. However, the connection Establishment of the PPP protocol is not the focus of the discussion. Therefore, we will focus on the packet flow of data after successful pppoe connection and how the data is processed.
4 pppoe
Pppoe code analysis
The main pppoe file is pppoe. C, and the entry function is main ()
In the main function, we mainly do two things:
In the Discover phase of the pppoe protocol, the processing function is Discovery (). This function establishes a raw socket, sends packets, waits for a response, and continues processing, after successful completion, the configuration status enters the session stage. For the code snippet, see:
Do {
...........
Sendpadi (conn); send packets
Conn-> discoverystate = state_sent_padi;
Waitforpado (Conn, timeout); wait for response
...........
} While (Conn-> discoverystate = state_sent_padi );
Do {
.............
Sendpadr (conn); send packets
Conn-> discoverystate = state_sent_padr;
Waitforpads (Conn, timeout); waiting for response
.............
} While (Conn-> discoverystate = state_sent_padr );
Conn-> discoverystate = state_session; set the state to session, and then enter the session stage
In the session phase of the pppoe protocol, the processing function is SESSION (). This function establishes a raw socket, reads data from the pppd, and sends the data with pppoe, then the received data is sent to the pppd program for pppd to process. After processing, the pppoe connection is established, the ppp0 port is also established, and the IP address is allocated from the server. From the above analysis, we know that pppoe only performs forwarding at this stage. After establishing a connection, pppoe has been doing forwarding.
For (;;){
.........................
Receive data from pppd and forward it
If (fd_isset (0, & readable )){
If (Conn-> synchronous ){
Syncreadfromppp (Conn, & Packet );
} Else {
Asyncreadfromppp (Conn, & Packet );
}
}
The data is received from the NIC port and sent to pppd.
If (fd_isset (Conn-> sessionsocket, & readable )){
Do {
If (Conn-> synchronous ){
Syncreadfrometh (Conn, Conn-> sessionsocket, optclampmss );
} Else {
Asyncreadfrometh (Conn, Conn-> sessionsocket, optclampmss );
}
} While (bpf_buffer_has_data );
}
}
Trend of data packets after pppoe establishes a connection
If you receive pppoe data from ETH:
First, the data is received by raw socket data in pppoe. pppoe unlocks the pppoe header that arrives at the data packet, and then transmits the data to the master device of the Pseudo Terminal, that is, to the slave device of the Pseudo Terminal, then, the data in the kernel runs to the ppp0 interface, which is a device. It will process the package through the driver and send it to the upper layer;
If data is to be sent out:
First, we know that the port to be sent is on the port of the ppp0 device based on the route, and the data reaches the ppp0 port. ppp0 transfers the data to the Pseudo Terminal from the device, that is, to the master device of the Pseudo Terminal, after arriving at pppoe, The pppoe program is configured with a pppoe header and then sent from the ETH port through the raw socket.
The preceding figure shows the trend of data packets after a PPP connection is established.
5. Difficulties in pppoe implementation
After pppoe is connected, the protocol stack is as follows:
In this way, the message is first encapsulated by PPP, then encapsulated by pppoe, and then added with the Ethernet header. This process is both direct and efficient, however, the data flow chart drawn from the analysis on the pppoe user space program is not like this. The data is transmitted from the ppp0 interface in the kernel to the terminal device, and then sent to the pppoe for packaging and sending, why is it so good to encapsulate pppoe packets instead of from ppp0? But this is not the case here, the pppoe kernel space implementation will be the best state mentioned above. In user space, this mechanism is to avoid disrupting the interface implemented by the original terminal in the Linux kernel, because the Linux kernel uses the serial device as the terminal device.
Next we will discuss how the ppp0 port is connected with the terminal of the slave device.
1) a PPP device is a kernel network interface device that uses PPP frames for group exchange between point-to-point physical links. Since the Linux kernel uses a serial device as a terminal device, therefore, the PPP end-to-end procedure is introduced to implement interfaces between terminal devices and PPP devices. according to the different physical transmission characteristics of the terminal equipment, the PPP procedure is divided into two types: asynchronous procedure (n_ppp) and synchronous procedure (n_sync_ppp.
2) in the PPP driver, each tty terminal device corresponds to a PPP transmission channel (chanell), and each PPP network device corresponds to a PPP interface unit ). the data streams received from the terminal device are decoded through the PPP transmission channel and converted to PPP frames for transmission to the PPP Network Interface Unit. The PPP interface unit then converts the PPP frame to the receiving frame of the PPP device. when a PPP device transmits a data frame, the transmitting frame is converted to a PPP frame through the PPP interface unit and transmitted to the PPP channel. The PPP channel is responsible for encoding the PPP frame and writing it to the terminal device.
The file descriptor corresponding to the slave terminal is ttyfd.
IOCTL (ttyfd, pppiocgchan, & chindex)
Obtain the channel of the device from the terminal
Ppp_fd = open ("/dev/PPP", o_rdwr );
IOCTL (ppp_fd, pppiocattchan, & chindex)
Bind ppp_fd to the terminal to read and write the input on the terminal.
The ppp0 port and ppp_dev_fd are bound together. We read and write the ppp0 output through ppp_dev_fd.
IOCTL (ppp_fd, pppiocconnect, & ifunit) is to connect the interfaces of ppp_fd and ifunit together, so that the terminal and the device are connected together, packets sent from the ppp0 port are sent to the slave terminal device, and the data on the slave terminal device is transmitted to the ppp0 interface.