Linux 网络子系统
网络接口层:网络接口层把数据链路层和物理层合并在了一起,提供访问物理设备的驱动程序,对应的网络协议主要是以太网协议。
网络层:协议管理离散的计算机间的数据传输,如IP协议为用户和远程计算机提供了信息包的传输方法,确保信息包能正确地到达目的机器。重要的网络层协议包括ARP(地址解析协议)、ICMP(Internet控制消息协议)和IP协议(网际协议)等。
传输层:传输层的功能包括:格式化信息流、提供可靠传输。传输层包括TCP(TransmissionControl Protocol,传输控制协议)和UDP(User Datagram Protocol,用户数据报协议),它们是传输层中最主要的协议。
应用层:应用层位于协议栈的顶端,它的主要任务是服务于应用,如利用FTP(文件传输协议)传输一个文件。常见的应用层协议有:HTTP,FTP,Telnet等。应用层是Linux网络设定很关键的一层,Linux服务器的配置文档主要针对应用层中的协议。
Linux 网络子系统的顶部是系统调用接口层。它为用户空间的应用程序提供了一种访问内核网络子系统的方法。位于其下面的是一个协议无关层,它提供了一种通用方法来使用传输层协议。然后是具体协议的实现,在 Linux 中包括内嵌的协议 TCP、UDP,当然还有 IP。然后是设备无关层,它提供了协议与设备驱动通信的通用接口,最下面是设备驱动程序。
协议无关接口实现一组通用函数来访问各种不同的协议
设备无关接口将协议与各种网络设备驱动连接在一起。这一层提供一组通用函数供底层网络设备驱动程序使用
设备无关接口:要从协议层向设备发送数据,需要使用dev_queue_xmit 函数,这个函数对数据进行排队,并交由底层设备驱动程序进行最终传输报文的接收通常是使用 netif_rx 执行的。当底层设备驱程序接收到一个报文(包含在所分配的sk_buff中)时,就会通过调用 netif_rx 将 数据上传至设备无关层,然后,这个函数通过 netif_rx_schedule将 sk_buff 在上层协议队列中进行排队,供以后进行处理。
设备描述
每个网络接口都由一个net_device结构来描述,该结构可使用如下内核函数动态分配:
1、 struct net_device *alloc_netdev(intsizeof_priv, const char*mask,
void (*setup)(struct net_device *))
sizeof_priv 私有数据区大小; mask:设备名; setup 初始化函数,设置net_device
2、struct net_device *alloc_etherdev(intsizeof_priv)
网卡驱动的重要的数据结构:
1、sk_buff
2、net_device
net_device 的主要成员包括:
char name[IFNAMSIZ]
设备名,如:eth%d %d在这里表示系统自动获取一个整型数字
unsigned long state
设备状态
unsigned longbase_addr
I/O 基地址
unsigned int irq
中断号
int (*init)(structnet_device *dev)
初始化函数。该函数在register_netdev时被调用来完成对 net_device 结构的初始化。
网络接口的设备方法可分为两组:基本的和可选的,基本方法包括那些使用接口所必需的;可选的方法实现更多高级的功能。
基本方法
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)
设备是通过socket来访问的
sk_buff
Linux内核中的每个网络数据包都由一个套接字
缓冲区结构 struct sk_buff 描述,即一个
sk_buff结构就是一个包,指向sk_buff的指针通
常被称做skb。struct 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; //有效数据的长度
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(structsk_buff *skb, int len)
向后移动skb的tail指针,并返回tail移动之前的值。
unsigned char*skb_put(struct sk_buff *skb, int len)
向前移动skb的head指针,并返回head移动之后的值。
kfree_skb(structsk_buff *skb)
释放一个sk_buff 结构,供协议栈代码使用
dev_kfree_skb(struct sk_buff *skb)
释放一个sk_buff 结构,供驱动代码使用
设备打开
Open 请求任何它需要的系统资源并且启动接口 :
1、注册中断,DMA等
2、设置寄存器,启动设备
3、启动发送队列
intnet_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种类型的中断: 新报文到达中断、报文发送完成中断和出错中断。中断处理程序可通过查看网卡中的中断状态寄存器,来分辨出中断类型。
收发过程
网卡数据接收过程:网络上的数据到达网卡 -> 网卡产生中断 -> 设备驱动层收到中断接收数据 -> 调用netif_rx()将数据传给上层直到用户空间
网卡数据发送过程:用空空间发送数据 ->dev_queue_xmit ->驱动层->调用hard_xmit()发送,硬件开始发送数据包。
DM9000_probe()
1、申请内存空间,建立与net_device的联系。
2、初始化一个工作队列 dm9000_poll_work()
3、获取一些资源
4、申请mem_region()
5、配置dm9000_set_io
6、重置dm9000硬件device
7、eth_setup()注册net_device
8、eeprom读取mac地址
9、platform_set_drvdata;
10、注册设备register_netdev
首先看一下DM9000的引脚和MINI2440的引脚连接
DM9000 MINI2440 功能描述
SD0 DATA0 数据信号
| |
SD15 DATA15 数据信号
CMD ADDR2 识别为地址还是数据
INT EINT7 中断
IOR# nOE 读命令使能
IOW# nWE 写命令使能
AEN nGCS4 片选使能
可以看出连接了16条数据线,1条地址线,而这唯一的一条地址线用于判断数据线传输的是地址还是数据,所以这16条数据线为数据和地址复用
而片选信号使用的BANK4,则访问0x2000 0000 –0x27FF FFFF这个范围的地址时会激活片选使能信号nGCS4
S3C2410 / S3C2440对外引出的27根地址线ADDR0~ADDR26的访问范围有128M,此外,CPU对外还引出了8根片选信号nGCS0~nGCS7,对应于BANK0~BANK7,当访问BANKx的地址空间是,nGCSx引脚输出低电平用来选中外接的设备。这样,每个 nGCSx对应128MB地址空间,8个nGCSx信号总共就对应了1GB的地址空间。