Linux2.6 kernel PPP Analysis

Source: Internet
Author: User
Tags time in milliseconds

1 Overview

The PPP protocol (Point-to-Point Protocol) is widely used in dial-up networks and is gradually replacing the slip protocol.

PPP data packet format: | Protocol code | load | fill character

There are four types of PPP protocol codes:

1 0x0001-0x3fff Network Layer Protocol (IPv4, IPv6, IPX, appletalk)

2 0x4001-0x7fff no network layer protocol involved in small load transfer (low rectification)

3 0x8001-0 xbfff is used to configure sub-protocols (network control protocols, such as ipcp) at the network layer)

4 0xc001-0 xFFFF sub-protocols used to establish PPP connections (Link Layer Control protocols, such as LCP, pap, chap)

2. Structure of PPP protocol implementation

Network Application

IP/TCP protocol stack

PPP network protocol-|
| -- PPP kernel implementation
PPP connection procedure-|

Modem

Pppd is an application process that communicates with the PPP kernel through sub-devices.

3. PPP data sending and receiving process

A. send data

There are two ways to send data through the PPP protocol: one is to send data through the network protocol stack, and the other is to directly send control protocol data through pppd.

B receives data

After the PPP connection procedure unreceives the data, it puts the data according to the Data Type: If it is negotiation protocol data, it is placed in the sub-device queue to wait for pppd to read; if it is network layer data, it calls netif_rx into the network stack.

4. Code Analysis

A initializes the PPP device. The PPP character master device number is 108.

Static struct file_operations ppp_device_fops = {
. Owner = this_module,
. Read = ppp_read,
. Write = ppp_write,
. Poll = ppp_poll,
. IOCTL = ppp_ioctl,
. Open = ppp_open,
. Release = ppp_release
};

# Define ppp_major 108

Static int _ init ppp_init (void)
{
Int err;

/* Register the character device. The device name is PPP */
Err = register_chrdev (ppp_major, "PPP", & ppp_device_fops );
If (! Err ){
/* Create udev */
Ppp_class = class_create (this_module, "PPP ");
If (is_err (ppp_class )){
Err = ptr_err (ppp_class );
Goto out_chrdev;
}
Class_device_create (ppp_class, null, mkdev (ppp_major, 0), null, "PPP ");
}

Out:
If (ERR)
Printk (kern_err "failed to register PPP device (% d)/n", err );
Return err;

Out_chrdev:
Unregister_chrdev (ppp_major, "PPP ");
Goto out;
}

What is class_create used?

After a Linux kernel version of 2.6, devfs no longer exists. udev becomes a replacement for devfs, and udev is the application layer.
Adding support for udev is simple. In the driver initialization code, call class_create to create a class for the device and call class_device_create to create the corresponding device for each device. The general usage is as follows:

Struct class * myclass = class_create (this_module, "my_device_driver ");
Class_device_create (myclass, null, mkdev (major_num, 0), null, "my_device ");

When such a module is loaded, udev daemon will automatically create the my_device file under/dev.

/* Character device PPP file structure:
*---------------------
* |... |
*----------------------
* | F_op |
*----------------------
* |... |
*----------------------
* | Private_data | ----------> struct ppp_file
*----------------------

Struct ppp_file {
Enum {
Interface = 1, Channel
} Kind;
Struct sk_buff_head XQ;/* pppd transmit queue */
Struct sk_buff_head RQ;/* receive queue for pppd */
Wait_queue_head_t rwait;/* For poll on reading/dev/PPP */
Atomic_t refcnt;/* # refs (incl/dev/PPP attached )*/
Int hdrlen;/* space to leave for headers */
Int index;/* interface unit/Channel Number */
Int dead;/* Unit/channel has been shut down */
};

Struct PPP {
Struct ppp_file file;/* stuff for read/write/poll 0 */
Struct file * owner;/* file that owns this unit 48 */
...
};

Struct channel {
Struct ppp_file file;/* stuff for read/write/poll */
Struct list_head list;/* link in all/new_channels list */
Struct ppp_channel * Chan;/* public channel data structure */
Struct rw_semaphore chan_sem;/* protects 'chan' during Chan IOCTL */
Spinlock_t downl;/* protects 'chan', file. XQ dequeue */
Struct PPP * PPP;/* PPP unit we're re connected */
Struct list_head clist;/* link in List of channels per unit */
Rwlock_t upl;/* protects 'ppp '*/
...
};

Struct ppp_channel {
Void * private;/* channel private data */
Struct ppp_channel_ops * OPS;/* operations for this channel */
Int MTU;/* max transmit packet size */
Int hdrlen;/* Amount of headroom channel needs */
Void * PPP;/* opaque to channel */
/* The following are not used at present */
Int speed;/* Transfer Rate (Bytes/second )*/
Int latency;/* overhead time in milliseconds */
};

Static int ppp_open (struct net_device * Dev)
{
// Allocate the HDLC device object
Hdlc_device * HDLC = dev_to_hdlc (Dev );
Void * old_ioctl;
Int result;

Dev-> priv = & HDLC-> state. PPP. syncppp_ptr;
HDLC-> state. PPP. syncppp_ptr = & HDLC-> state. PPP. pppdev;
HDLC-> state. PPP. pppdev. Dev = dev;

Old_ioctl = Dev-> do_ioctl;
HDLC-> state. PPP. old_change_mtu = Dev-> change_mtu;
Sppp_attach (& HDLC-> state. PPP. pppdev );
/* Sppp_attach nukes them. We don't need syncppp's IOCTL */
Dev-> do_ioctl = old_ioctl;
HDLC-> state. PPP. pppdev. sppp. pp_flags & = ~ Pp_cisco;
Dev-> type = arphrd_ppp;
Result = sppp_open (Dev );
If (result ){
Sppp_detach (Dev );
Return result;
}

Return 0;
}

Static ssize_t ppp_read (struct file * file, char _ User * Buf,
Size_t count, loff_t * PPOs)
{
Struct ppp_file * pF = file-> private_data;

// If no data exists, wait in the queue
Declare_waitqueue (wait, current );

Ssize_t ret;
Struct sk_buff * SKB = NULL;

Ret = count;

If (pF = 0)
Return-enxio;
Add_wait_queue (& PF-> rwait, & wait );
For (;;){
Set_current_state (task_interruptible );
SKB = skb_dequeue (& PF-> rq); // obtain data
If (SKB)
Break;

// No data in the queue
Ret = 0;
If (PF-> dead)
Break;
If (PF-> kind = interface) {// Network Device
/*
* Return 0 (EOF) on an interface that has no
* Channels connected, unless it is looping
* Network traffic (demand mode ).
*/
Struct PPP * PPP = pf_to_ppp (PF );
If (PPP-> n_channels = 0
& (PPP-> flags & SC _loop_traffic) = 0)
Break;
}
Ret =-eagain;
If (file-> f_flags & o_nonblock)
Break;
Ret =-erestartsys;

// Set pending to suspend the current process
If (signal_pending (current ))
Break;

// Reschedule to stack
Schedule ();
}
Set_current_state (task_running );
Remove_wait_queue (& PF-> rwait, & wait );

If (SKB = 0)
Goto out;

Ret =-eoverflow;
If (SKB-> Len> count)
Goto outf;
Ret =-efault;

// Copy data to the user space
If (copy_to_user (BUF, SKB-> data, SKB-> Len ))
Goto outf;
Ret = SKB-> Len;

Outf:
Kfree_skb (SKB );
Out:
Return ret;
}

// Send data
Static ssize_t ppp_write (struct file * file, const char _ User * Buf,
Size_t count, loff_t * PPOs)
{
Struct ppp_file * pF = file-> private_data;
Struct sk_buff * SKB;
Ssize_t ret;

If (pF = 0)
Return-enxio;
Ret =-enomem;

// Allocate SKB
SKB = alloc_skb (count + PF-> hdrlen, gfp_kernel );
If (SKB = 0)
Goto out;
Skb_reserve (SKB, PF-> hdrlen );
Ret =-efault;

// Copy data from the user space
If (copy_from_user (skb_put (SKB, count), Buf, count )){
Kfree_skb (SKB );
Goto out;
}

Skb_queue_tail (& PF-> XQ, SKB );

Switch (PF-> kind ){
Case interface:
Ppp_xmit_process (pf_to_ppp (PF); // sent through the network interface
Break;
Case channel:
Ppp_channel_push (pf_to_channel (PF); // send it through the procedure interface
Break;
}

Ret = count;

Out:
Return ret;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.