Design the network device driver for Linux

Source: Internet
Author: User
Article title: design a network device driver for Linux. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
Author: Li Weigang
  
Linux network device drivers are an important part of Linux operating system network applications. Analyzing its running mechanism is helpful for designing Linux network applications. We can do some special things related to applications at the network driver level, such as when designing a Linux firewall and network intrusion detection system, you can intercept network data packets based on the network driver and analyze them. Since Linux is open-source, it provides us with an excellent opportunity to analyze and transform the network driver and satisfy special applications. This article discusses the network drivers in Linux kernel in detail, and provides an important process, an implementation mode, and a specific example for implementing the Linux network driver.
  
  
Operating mechanism
  
  
1. Architecture
  
The architecture 1 of the Linux network driver is shown in. It can be divided into four layers: protocol interface layer, network device interface layer, device driver function layer that provides actual functions, and network device and network media layer. When designing a network driver, the main task is to complete the device driver function layer so that it meets the features we need. In Linux, all network devices are abstracted as an interface. This interface provides a set of operations on all network devices. The data structure struct device indicates the running status of the network device in the kernel, that is, the network device interface. It includes both software-only network device interfaces, such as Loopback, and hardware network device interfaces, such as an Ethernet card. It centrally manages all network devices by using the device linked list with the dev_base as the header pointer. Each element in the device linked list represents a network device interface. There are many device methods for system access and protocol layer calls in the data structure device, including the init function for device initialization and registration to the system, the open and stop functions for enabling and disabling network devices, the hard _ start_xmit function for processing data packets, and the interrupt processing function. For more information about the device data structure (net_device in the kernel), see/linux/include/linux/netdevice. h.
  
   
2. initialization
  
Network device Initialization is mainly completed by the initialization function specified by the init function pointer in the device data structure. When the kernel starts or loads the network driver module, the initialization process is called. This process first checks whether the network physical device exists. It detects the hardware features of a physical device and then configures resources for the device. After completing these steps, you must construct the device data structure and use the detected values to initialize the variables in the device. This step is important. Finally, register the device with the Linux kernel and apply for memory space.
  
3. send and receive data packets
  
Packet sending and receiving are two of the most critical processes in implementing the Linux network driver. The processing of these two processes will directly affect the overall operating quality of the driver. The transmission process of network data packets is also clearly stated. First, when the network device driver is loaded, the system calls the network device initialization function through the init function pointer in the device field to initialize the device. If the operation is successful, you can use the open function pointer in the device field to call the open function of the network device to open the device, and then use the hardware header function pointer hard_header in the device field to create the hardware header information. Finally, the hard_start_xmit function pointer in the device domain is called through the protocol interface layer function dev_queue_xmit (for details, see/linux/net/core/dev. c) to send data packets. This function sends data stored in the socket buffer to the physical device. This buffer is represented by the data structure sk_buff (for details, see/linux/include/linux/sk_buff.h.
  
Packet receipt is completed through the interrupt mechanism. When data arrives, an interruption signal is generated. The driver function layer of the network device calls the interrupt processing program, that is, the data packet receiving program, to process the data packet reception. Then, the network protocol interface layer calls the netif_rx function (for details, see/linux/net/core/dev. c) to transmit the received data packets to the upper layer of the network protocol for processing.
  
Implementation mode
  
There are two main ways to implement the Linux network device driver function: one is to load through the kernel. When the kernel starts, it starts to load the network device driver. after the kernel starts, the network driver function is implemented immediately, and then the module is loaded. Compared the two, the second form is more flexible. The module loading mode is discussed here.
  
The module design is a special technology in Linux, which makes Linux kernel functions easier to expand. Using modules to design Linux network device drivers is easy and can form a fixed mode. Anyone who designs according to this model can design excellent network drivers. First, we will briefly introduce the design steps for loading network drivers based on modules. later, we will also explain them with specific examples. First, the module load command insmod is used to insert the network device driver into the kernel. Then, insmod first initializes the init function pointer of the network device by calling the init_module () function, and then registers the network device in the Linux system by calling the register_netdev () function. If it succeeds, call the network device initialization function referred to by the init function pointer to initialize the device and insert the device data structure to the end of the dev_base linked list. Finally, you can run the rmmod command to call the cleanup_module () function in the network driver to uninstall the network driver module. The specific implementation process is shown in.
  
The network interface initialized by the module is recorded as a module when the kernel is compiled. The system does not know the existence of this interface at startup. you need to go to/etc/rc. d. write commands in the initial startup script defined in the directory or manually insert modules into the kernel space to activate the network interface. This also gives us flexibility when to load the network device driver.
Application instance
  
  
Taking the NE2000 compatible Nic as an example, we will introduce the design process of the module-based network driver. See linux/drivers/net/ne. c and linux/drivers/net/8390.c.
  
1. module loading and unloading
  
The module loading function of the NE2000 Nic is completed by the init_module () function. The specific process and explanation are as follows:
  
Int init_module (void)
{
Int this_dev, found = 0;
// Cyclically detect network device interfaces of the ne2000 type
For (this_dev = 0; this_dev <MAX_NE_CARDS; this_dev ++)
{
// Obtain the net-device structure pointer corresponding to the network interface
Struct net_device * dev = & dev_ne [this_dev];
Dev-> irq = irq [this_dev]; // initialize the interrupt request number for this interface
Dev-> mem_end = bad [this_dev]; // initialize the end position of the receiving buffer
Dev-> base_addr = io [this_dev]; // initialize the I/O base address of the network interface
Dev-> init = ne_probe; // initialize init as ne_probe. This function is described later.
// Call registre_netdevice () to register the network interface with the system. In this function, the network interface will be assigned to the system only.
. Add the network interface device to the dev-base linked list of system management for management.
If (register_netdev (dev) = 0 ){
Found ++;
Continue ;}
... // Omitted
}
Return 0 ;}
  
  
  
The module uninstallation function is implemented by the cleanup_module () function. As follows:
  
Void cleanup_module (void)
{
Int this_dev;
// Traverse the entire dev-ne array
For (this_dev = 0; this_dev <MAX_NE_CARDS; this_dev ++ ){
// Obtain the net-device structure pointer
Struct net_device * dev = & dev_ne [this_dev];
If (dev-> priv! = NULL ){
Void * priv = dev-> priv;
Struct pci_dev * idev = (struct pci_dev *) ei_status.priv;
// Call the function pointer idev-> deactive to disable the active Nic.
If (idev) idev-> deactivate (idev );
Free_irq (dev-> irq, dev );
// Call the function release_region () to release the I/O address space occupied by this Nic
Release_region (dev-> base_addr, NE_IO_EXTENT );
// Call unregister_netdev () to cancel the net_device () structure
Unregister_netdev (dev );
Kfree (priv); // release the priv space
}
}
}
  
  
  
2. network interface initialization
  
This function is implemented by the ne_probe () function. As mentioned above, it is used in the init_module () function to initialize the init function pointer. It detects network adapters and initializes network device information in the system for sending and receiving network data. The specific process and explanation are as follows:
  
Int _ init ne_probe (struct net_device * dev)
{
Unsigned int base_addr = dev-> base_addr;
// Initialize the dev-owner member. because the module driver is used, the dev-owner is directed to the modules structure pointer of the object.
SET_MODULE_OWNER (dev );
// Check whether dev-> base_addr is valid. If yes, execute the ne-probe1 () function detection process. No, automatic detection is required.
If (base_addr> 0x1ff)
Return ne_probe1 (dev, base_addr );
Else if (base_addr! = 0)
Return-ENXIO;
// If an ISAPnP device exists, call ne_probe_isapnp () to detect this type of Nic.
If (isapnp_present () & (ne_probe_isapnp (dev) = 0 ))
Return 0;
... // Omitted
Return-ENODEV;
}
  
  
  
The difference between the two functions ne_probe_isapnp () and ne_probe19 () lies in the detection of the interrupt number. In PCI mode, you only need to specify the I/O base address to automatically obtain IRQ, which is automatically allocated by the BIOS. in ISA mode, you need to obtain idle interrupted resources for allocation.
  
3. enable and disable network interface devices
  
When a network interface device is enabled, it activates the network interface so that it can receive and transmit data from the network to the network protocol stack. It can also send data to the network. If the device is disabled, the operation is stopped.
  
In the NE2000 network driver, the network device is enabled by dev_open () and ne_open (), and dev_close () and ne_close () are enabled by the device. They call the underlying functions ei_open () and ei_close () accordingly. The implementation process is relatively simple.
  

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.