Linux network device driver development (III)-basic principles and framework of network device drivers

Source: Internet
Author: User

Linux network device driver development (III)-basic principles and framework of network device drivers

I. Protocol Stack layer comparison

 

Ii. Linux network subsystem

At the top of the Linux network subsystem is the system call interface layer. It provides a socket Method for applications provided by the user space to access the kernel network subsystem ). Under it is a protocol-independent layer, which provides a common method to use the transport layer protocol. Then the implementation of specific protocols, including kernel protocols TCP, UDP, and IP in Linux. Then there is the device-independent layer, which provides a common interface for communication between the Protocol and the device driver. The bottom is the device driver.


Device-independent interfaces connect protocols with various network drivers. This layer provides a set of common functions for the underlying network device drivers to operate on the high-level protocol stack. To generate data from the protocol layer to the device, you need to call the dev_queue_xmit function. This function queues the data and submits it to the hard_start_xmit method of the underlying driver for final transmission. The netif_rx is usually used for receiving. When the underlying device program receives a packet (which is interrupted), it will call netif_rx to upload the data to the device-independent layer.


3. Architecture from device independent layer to driver layer

Architecture from device independent layer to driver layer

 

1) The network protocol interface layer provides a unified packet receiving and receiving interface to the network layer protocol. No matter the upper layer protocol is ARP or IP, data is sent through the dev_queue_xmit () function and through netif_rx () the function accepts data. The existence of this layer makes the Upper Layer Protocol Independent from specific devices.
2) the network device interface layer provides a unified structure net_device for describing the properties and operations of specific network devices to the Protocol interface layer. This structure is the container of functions in the device driver function layer. In fact, the network device interface layer plans the structure of the device driver function layer for specific hardware operations from a macro perspective.
3) The functions at the device driver function layer are specific members of the net_device data structure at the network device interface layer. They are the programs that drive the hardware of the network device to complete the corresponding actions. They use hard_start_xmit () the function starts the sending operation and receives the operation through the interruption trigger on the network device.
4) the network device and media layer are physical entities that complete packet sending and receiving, including network adapters and specific transmission media. The network adapter is physically driven by functions in the driver function layer. For Linux systems, both network devices and media can be virtual.

 

1. Network Protocol Interface Layer:

Here we mainly send and receive data packets. The function prototype is as follows:

dev_queue_xmit(struct sk_buff *skb);int netif_rx(struct sk_buff *skb);  
Here we use a skb_buff struct, which is defined in include/linux/skbuff. h. It refers to "Socket buffer" and is used to transmit data between different layers of the Linux network subsystem. He is a two-way linked list. In the old kernel, there will be a list domain pointing to the sk_buff_head, that is, the linked list header, but it does not exist in the Linux 2.6.30.4 kernel I studied, for example:

 

Important data member in sk_buff

Struct device * dev; the device that is processing the package

_ U32 sadd; r // IP address

_ U32 daddr; // IP address

_ U32 raddr; // IP router address

Unsigned char * head; // start of space allocation

Unsigned char * data; // start of valid data

Unsigned char * tail; // end of valid data

Unsigned char * end; // end of the allocated space

Unsigned long len; // The length of valid data


Sk_buff operation
A -- allocate: allocate a sk_buff structure for the protocol stack code.

struct sk_buff *alloc_skb(unsigned int len, int priority);struct sk_buff *dev_alloc_skb(unsigned int len);  

Allocate a buffer. The alloc_skb function allocates a buffer and initializes skb-> data and skb-> tail as skb-> head. The len parameter is the space size of the data buffer. It is usually aligned with lw.cache_bytes bytes (32 for ARM), and the priority parameter is the memory allocation priority. The dev_alloc_skb () function assigns skb with the GFP_ATOMIC priority.

B -- release:

void kfree_skb(struct sk_buff *skb);void dev_kfree_skb(struct sk_buff *skb); 

The Linux kernel uses the kfree_skb () function, while the network device driver uses dev_kfree_skb ().

The important member in sk_buff is the pointer to the data in the data packet, as shown in:


A pointer used to address data in a data packet. head points to the beginning of allocated space, data points to the beginning of valid octet, tail points to the end of valid octet, and end points to the maximum address that tail can reach. If this is not done, a buffer with a fixed size will be allocated. If the buffer is not enough, a larger buffer will be applied for, copied to it, and increased. This reduces the performance.


3) Changes

Unsigned char * skb_put (struct sk_buff * skb, int len); move the taill pointer Back To The len Length and return the value before tail moves. Adds data to the end of the valid data area of skb. Unsigned char * skb_push (struct sk_buff * skb, int len); move the data Pointer Forward The len Length. And return the value after moving. Adds a data header to the front end of the valid data area of skb ). Unsigned char * skb_pull (struct sk_buff * skb, int len); void skb_reserve (struct sk_buff × skb, int len );
They correspond to the four functions respectively. After reading this figure, we can understand the functions of these four functions.

 

 

2. network device interface layer:

The main function of the interface layer of network equipment is to define a uniform and abstract data structure for ever-changing network devices. The net_device structure is the same, so that various hardware can be unified at the software level.

 

Each network device is described by struct net_device. The following kernel functions can be used for dynamic allocation.

struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void(*setup)(struct net_device *))

Sizeof_priv indicates the size of the private data zone. mask indicates the device name and setup indicates the initialization function. When registering the device, this function is called. That is, the init member of net_deivce.

struct net_device *alloc_etherdev(intsizeof_priv)
The difference between this function and the above function is that the kernel knows that it will treat the device as an Ethernet device and perform related initialization.

 

The net_device structure can be dividedGlobal Member, hardware Member, interface member, device method member, and Public Member

A -- main global Member

Char name [INFAMSIZ] device name, for example, eh % dunsigned long state device status unsigned long base_addr I/O base address unsigned int irq interrupt number

B-main device Methods

// First, check the function for enabling and disabling network devices: int (* open) (struct net_device * dev); // open the interface. When ifconfig is activated, the int (* stop) (struct net_device * dev) interface is enabled; // stop the interface, when ifconfig eth % down is called // note that ifconfig is short for interface config. Generally, input: // ifconfig eth0 up in the user space to call the open function. // Input in the user space: // ifconfig eth0 down will call the stop function here. // When you use ifconfig to assign an address to an interface, you need to execute two tasks. First, it assigns the Address through ioctl (SIOCSIFADDR) (Socket I/O Control Set Interface Address), and then uses ioctl (SIOCSIFFLAGS) (Socket I/O Control Set Interface Flags) set the IFF_UP flag in dev-> flag to open the interface. This call will call the open method of the device. Similarly, when the interface is closed, ifconfig uses ioctl (SIOCSIFFLAGS) to clear the IFF_UP flag and then calls the stop function. Int (* init) (struct net_device * dev) // initialization function. This function is called during register_netdev to initialize the net_device structure int (* hard_start_xmit) (struct sk_buf * skb, struct net_device * dev) // data sending function int (* hard_header) (struct sk_buff * skb, struct net_device * dev, unsigned short type, void * daddr, void * saddr, unsigned len); // This method creates a hardware header int (* rebuild_header) (struct sk_buff * skb) based on the previously retrieved source and target hardware addresses ); // The mac address of the Ethernet is fixed. for efficiency, the first packet will ask the mac address. Save the mac address for the cache. In the future, you don't need to ask about the package. Copy the package address directly. Void (* tx_timeout) (struct net_device * dev); // If the packet fails to be sent within the time-out period, this method is called. This method should solve the problem of failure, and start sending data again. Struct net_device_stats * (* get_stats) (struct net_device * dev); // this method is called when the application needs to obtain interface statistics. Int (* set_config) (struct net_device * dev, struct ifmap * map); // modify the interface configuration, such as changing the I/O port and interrupt number, this method is usually not required for current drivers. Int (* do_ioctl) (struct net_device * dev, struct ifmap * map); // It is used to implement custom ioctl commands. It can be NULL if not required. Void (* set_multicast_list) (struct net_device * dev); // this method is called when the multicast list of the device changes or the device flag changes. Int (* set_mac_address) (struct net_device * dev, void * addr); // this function can be implemented if the interface supports mac address change.

 

3. Device Driver Interface Layer:

The net_device struct member (Attribute and function pointer) must be assigned by the specific value and function of the device driver function layer. For specific settings xxx, engineers should compile functions at the device driver function layer, such as xxx_open (), xxx_stop (), xxx_tx (), xxx_hard_header (), xxx_get_stats (), xxx_tx_timeout.

 

4. network device and media layer:

The network device and media layer correspond directly to the actual hardware device.

 

Network device registration

The registration method of a network device differs from that of a character driver because it does not have a primary/secondary device number and uses the following function to register a device.

 

int register_netdev(struct net_deivce*dev)
Logout of network devices
void unregister_netdev(struct net_device*dev)

 

4. Driver implementation

1) initialization (init)

Device Detection is carried out in the init method. Generally, a function called probe method is called.

During initialization, the system checks the device, configures and initializes the hardware, and finally applies for these resources from the system. In addition, fill in the dev structure of the device. We call the ether_setup method provided by the kernel to set some default Ethernet settings.

 

2) open)

Open this method is called when the network device is activated in the network device driver (that is, the device status changes from down to up)

In fact, a lot of initialization work can be done here. For example, resource application and hardware activation. If dev-> open returns a value other than 0, the hardware status remains down,
Register for interruptions, DMA, etc.; Set registers, start devices; start sending queues

Generally, registration interruption is performed in init, but most of the registration interruptions in the NIC driver are registered in open, because the NIC should be closed and restarted frequently.

 

3) stop)

The stop method is opposite to the open method.

Some resources can be released to reduce the burden on the system.

The stop operation is called when the device status changes from up to down.

 

4) Send (hard_start_xmit)

When the system calls the driver's hard_start_xmit, the data sent is placed in a sk_buff structure. The general driver is sent to the hardware. Some special devices, such as loopback, make up the data to receive data and directly discard the data to the system or dummy device.

If the message is sent successfully, the hard_start_xmit method releases sk_buff. If the device cannot be processed temporarily, for example, if the hardware is busy, 1 is returned.

 

5) receive

The driver has an acceptance method. When data is received, the driver calls the netif_rx function to deliver the skb to the device-independent layer.

Generally, an interruption occurs when the device receives the data. In the Interrupt Processing Program, the driver requests a piece of sk_buff (skb) to read the data from the hardware to the buffer of the application number.

Then fill in some information in sk_buff.

The interruption may be due to the receipt of data or the completion of sending. The interrupt processing program should judge the interruption type. If the interruption is due to the receipt of data, the program will start to receive data. If the interruption is due to the completion of sending, then, the operation after sending is processed, such as restarting the sending queue.
Receiving process:
1. Allocate skb = dev_alloc_skb (pkt-> datalen + 2)
2. read data from hardware to skb
3. Call netif_rx to send data to the protocol stack.
 

Interrupt handling

Network Interfaces usually support three types of interruptions: Arrival interruption of New packets, completion interruption of message sending, and error interruption. The interrupt handler can identify the interrupt type by checking the interrupt Status Register of the NIC.

Related Article

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.