Learning linux driver (4) - a network device driver

(A) architecture

Required knowledge points:

1. The stack level of Linux
2. Linux network subsystem architecture

(B) protocol stack

One of the advantages of Linux is that it is rich and stable network protocol stack. Ranging from independent layer protocol (e.g. generic socket layer interface or the device layer) to various specific network protocol.

Protocol Overview

For the introduction of network theory generally used OSI (Open Systems Interconnection) model, but introduce the Linux networking stack is generally divided into four layers of the Internet model.

 

Network Interface Layer

Network interface layer to the data link and physical layers were combined together, provide access to the physical device drivers, network protocol mainly corresponding Ethernet protocol

Internet Layer

Data transmission between the network layer protocol discrete management computer, such as the IP protocol provides a method for transmitting packets to the remote computer and the user, to ensure that the packet destination machine correctly. Important network layer protocol ARP (Address Resolution Protocol), ICMP (Internet Control Message Protocol) protocol and IP (Internet Protocol)

Transport Layer

Functional transport layer comprising: formatting information flow, providing reliable transmission. Transport layer comprises TCP (Transmission Control Protocol, Transmission Control Protocol) and UDP (User Datagram Protocol, User Datagram Protocol), which are the main transport layer protocol.

Application layer

The application layer of the protocol stack at the top, its main task is to serve the application, such as with FTP (File Transfer Protocol) file transfer. Common application layer protocols are: HTTP, FTP, Telnet and so on. The application layer is the Linux network configuration is critical layer, Linux server configuration document aimed at the application layer protocol.

(C) Linux network subsystem

Top Linux network subsystem is the system call interface layer. It provides a way to access core network subsystem for user-space applications. Beneath it is a protocol-independent layer, it provides a general way to use a transport layer protocol. Then it is to achieve concrete agreements, included in the Linux embedded protocol TCP, UDP, and of course IP. Then the device-independent layer that provides a common interface protocol to communicate with the device driver, the device driver is the lowermost

系统调用接口

为应用程序提供访问内核网络子系统的方法:Socket系统调用。

协议无关接口

实现一组通用函数来访问各种不同的协议:通过socket实现。Linux 中的 socket 使用struct sock来描述,这个结构包含了特定socket 所需要的所有状态信息,还包括socket 所使用的特定协议和在 socket 上可以执行的一些操作。

网络协议

网络协议层用于实现各种具体的网络协议,如: TCP、UDP 等。

设备无关接口

设备无关接口将协议与各种网络设备驱动连接在一起。这一层提供一组通用函数供底层网络设备驱动程序使用,让它们可以对高层协议栈进行操作。首先,设备驱动程序可能会通过调用 register_netdevice 或unregister_netdevice 在内核中进行注册或注销。调用者首先填写 net_device 结构,然后传递这个结构进行注册。内核调用它的 init 函数(如果定义了这种函数),然后执行一组健全性检查,并将新设备添加到设备列表中(内核中的活动设备链表)。

要从协议层向设备发送数据,需要使用dev_queue_xmit函数,这个函数对数据进行排队,并交由底层设备驱动程序进行最终传输报文的接收通常是使用netif_rx 执行的。当底层设备驱动程序接收到一个报文(包含在所分配的sk_buff中)时,就会通过调用 netif_rx 将 数据上传至设备无关层,然后,这个函数通过 netif_rx_schedule将 sk_buff 在上层协议队列中进行排队,供以后进行处理。

驱动程序

网络体系结构的最底部是负责管理物理网络设备的设备驱动程序层

(四)网卡驱动设计

设备描述

每个网络接口都由一个net_device结构来描述, 该结构可使用如下内核函数动态分配:
1、struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *))
sizeof_priv 私有数据区大小; mask:设备名; setup 初始化函数
2、struct net_device *alloc_etherdev(int sizeof_priv)

net_device

结构 net_device 的主要成员包括:

    • char name[IFNAMSIZ] 设备名,如:eth%d
    • unsigned long state 设备状态
    • unsigned long base_addr I/O 基地址
    • unsigned int irq 中断号

int (*init)(struct net_device *dev)
初始化函数。该函数在register_netdev时被调用来完成对 net_device 结构的初始化

和字符驱动一样, 网络设备也要声明能操作它的函数。有些操作可以保留为 NULL, 有的可以通过 ether_setup 来使用默认设置。网络接口的设备方法可分为两组:基本的和可选的,基本方法包括那些使用接口所必需的;可选的方法实现更多高级的功能。

基本方法

int (*open)(struct net_device *dev)
打开接口。ifconfig 激活时,接口将被打开。
int (*stop)(struct net_device *dev)
停止接口。该什么时候调用呢?
int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev)
数据发送函数

可选操作

int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd)
处理特定于接口的 ioctl 命令
int (*set_mac_address)(struct net_device *dev, void *addr)
改变Mac地址的函数,需要硬件支持该功能

设备注册

网络接口驱动的注册方式与字符驱动不同之处在于它没有主次设备号,并使用如下函数注册。
int register_netdev(struct net_device *dev)

sk_buff

Linux内核中的每个网络数据包都由一个套接字缓冲区结构 struct sk_buff 描述,即一个sk_buff结构就是一个包,指向sk_buff的指针通常被称做skb。
该结构包含如下重要成员:

      • struct device *dev; //处理该包的设备
      • __u32 saddr; //IP源地址
      • __u32 daddr; //IP目的地址
      • __u32 raddr; //IP路由器地址
      • unsigned char *head; //分配空间的开始
      • unsigned char *data; //有效数据的开始
      • unsigned char *tail; //有效数据的结束
      • unsigned char *end; //分配空间的结束
      • unsigned long len; //有效数据的长度

Skb操作函数

操作sk_buff的内核函数如下
struct sk_buff *alloc_skb(unsigned int len, int priority)
分配一个sk_buff 结构,供协议栈代码使用

struct sk_buff *dev_alloc_skb(unsigned int len)
分配一个sk_buff 结构,供驱动代码使用

unsigned char *skb_push(struct sk_buff *skb, int len)
向后移动skb的tail指针,并返回tail移动之前的值。函数常用来:

unsigned char *skb_put(struct sk_buff *skb, int len)
向前移动skb的head指针,并返回head移动之后的值。函数常用来:

kfree_skb(struct sk_buff *skb)
释放一个sk_buff 结构,供协议栈代码使用

dev_kfree_skb(struct sk_buff *skb)
释放一个sk_buff 结构,供驱动代码使用

设备打开

int net_open(struct net_device *dev)
{
  /*申请中断*/
  request_irq(dev->irq, &net_interrupt, SA_SHIRQ,“dm9000”, dev);
  /* 设置寄存器,启动设备 */
  ...... ...... ...... ......
  /*启动发送队列*/
  netif_start_queue(dev);
}

数据发送

当核心需要发送一个数据包时,它调用hard_start_transmit函数,该函数将最终调用到net_device结构中的hard_start_xmit函数指针。

数据接收

网络接口驱动可以实现两种方式的报文接收:
中断查询,Linux中驱动多采用中断方式。

接收流程

1、分配Skb
  skb = dev_alloc_skb(pkt->datalen + 2)
2、从硬件中读取数据到Skb
3、调用netif_rx将数据交给协议栈
  netif_rx(skb)

中断处理

网络接口通常支持3种类型的中断: 新报文到达中断、报文发送完成中断和出错中断。中断处理程序可通过查看网卡中的中断状态寄存器,来分辨出中断类型。

(五)DM9000网卡驱动分析

芯片介绍

DM9000是开发板经常采用的网络芯片,是一种高度集成而且功耗很低的高速网络控制器,可以和CPU直连,支持10/100M以太网连接,芯片内部自带16K的SRAM(3KB用来发送,13KB用来接收)
Dm9000在收到由上层发来的以太网帧后,开始侦听网络线路,如果线路忙,就等到线路空闲为止,否则立即发送该数据帧。接收时,它将从以太网收到的数据包在经过解码、去掉帧头和地址检验等步骤后缓存在片内。在CRC校验通过后, 它会通知CPU收到了数据帧

Guess you like

Origin www.cnblogs.com/WenLee/p/12116369.html