第九章 Linux网络设备驱动程序
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.2.1 网络设备的注册、注销 注册与注销函数
int register_netdev(struct net_device *dev); void unregister_netdev(struct net_device *dev);
创建net_device
struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device*)); struct net_device *alloc_etherdev(int sizeof_priv);
9.3 网络设备的打开和释放
网络设备的打开函数完成如下工作:
使能设备使用的硬件资源,申请I/O区域、中断和DMA通道等。 调用Linux内核提供的netif_start_queue()函数,激活设备发送队列。
网络设备的关闭函数需要完成如下工作:
调用Linux内核提供的netif_stop_queue()函数,停止设备传输包。 释放设备所使用的I/O区域、中断和DMA资源。
全局成员 硬件相关成员 接口相关成员 设备方法成员 公用成员
9.1.2 网络设备接口层
net_device 结构的主要成员
全局信息
char name[IFNAMESIZ] int (*init)(struct net_device *dev)
如果被设置了,在register_netdev奖 调用他初始化net_device结构,现代 驱动一般在注册接口中完成初始化。
unsigned char *head; unsigned char *data; unsigned char *tail; unsigned char *end; unsigned long len; unsigned char ip_summed; unsigned char pkt_type
指向数据包中各个层的数据包头。h指向传 输层包头,nh指向网络层包头,mac指向 链路层包头 用来寻址数据包中的数据指针。head指向 已分配空间开头,data指向有效的octet开 头,tail指向有效的octet结尾,而end指向 tail可以到达的最大地址 PACKET_HOST PACKET_BROADCAST PACKET_MULTICAST PACKET_OTHERHOST
根据先前检索到的源和目的硬件地址建立硬件头
int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
9.1.2 网络设备接口层
释放net_device
void free_netdev(struct net_device *dev);
9.2.1 网络设备的注册、注销
1 int xxx_init_module(void) 2{ 3 … 4 /*分配net_device结构体并对其成员赋值*/ 5 xxx_dev = alloc_netdev(sizeof(struct xxx_priv),“sn%d”, xxx_init); 6 if(xxx_dev == NULL) 7 …/*分配net_device失败*/ 8 9 /*注册net_device结构体*/ 10 if((result = register_netdev(xxx_dev))) 11 … 12 } 13 14 void xxx_cleanup(void) 15 { 16 … 17 /*注销net_device结构体*/ 18 unregister_netdev(xxx_dev); 19 /*释放net_device结构体*/ 20 free_netdev(xxx_dev); 21 }
设置地址 修改传输参数 维护流量和流量控制 错误统计和报告
网络设备的特点
网络子系统是完全与协议无关的,
网络驱动程序与内核其余部分之间的每次交互处理的 都是一个网络数据包
9.1 Linux网络设备驱动的结构
9.1.1 网络协议接口层
最主要的功能是给上层协议提供了透明的数据包发送 和接收接口。 上层ARP或IP协议需要发送数据包时,调用网络协议 接口层的dev_queue_xmit()函数
9.1.2 网络设备接口层
如果接口支持MAC地址改 变,则可以实现该函数 int (*set_mac_address)(struct net_device *dev, void *addr); 当接口的MTU改变时, 该方法将被调用,负责 做出相应的特定处理 int (*change_mtu)(struct net_device *dev, int new_mtu); 根据ARP查询的结果填充hh_cache结构 int (*header_cache) (struct neighbour *neigh, struct hh_cache *hh); 在发生变化时,该方法更新 hh_cache结构中的目的地址 int (*header_cache_update) (struct hh_cache *hh, struct net_device *dev, unsigned char *haddr); 从skb中包含的数据包中获得源地址,并 将其复制到位于haddr的缓冲区中 int (*hard_header_parse) (struct sk_buff *skb, unsigned char *haddr);
用来在传输数据包之前重建硬件头 int (*rebuild_header)(struct sk_buff *skb); 数据包发送在超时时间内失败,这时 该方法被调用。这个方法应该解决失 败的问题并重新开始发送数据包 void (*tx_timeout)(struct net_device *dev); 当应用程序需要获得接口的统计信息时,这个方法被调用 struct net_device_stats *(*get_stats)(struct net_device *dev); 改变接口的配置。比如改变I/O端口和中断号 等,现在的驱动程序通常无需该方法 int (*set_config)(struct net_device *dev, struct ifmap *map); 实现设备自定义的ioctl命令 int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); 当设备的组播列表改变或设备 标志改变时,该方法被调用 void (*set_multicast_list)(struct net_device *dev);
硬件信息
unsigned long rmem_end; unsigned long rmem_start; unsigned long mem_end;
这些字段描述了设备共享内存的 起止地址
unsigned long mem_start;
unsigned long base_addr; unsigned char irq; unsigned char if_port; unsigned char dma;
int skb_tailroom(struct sk_buff *skb);
返回缓冲区后部可用空间总量
int skb_headroom(struct sk_buff *skb);
返回缓冲区前面部分可用空间总量
void skb_reserve(struct sk_buff *skb, int len);
int (*stop)(struct net_device *dev);
停止接口。在这个方法里面,我们完 成与open方法相反的,注销操作
该方法初始化数据包的传输。是网络设备驱动中非常重要的一个方法。我们将 完整的数据包放入一个套接字缓冲区sk_buff结构里 int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev);
unsigned char *skb_put(struct sk_buff *skb, int len); unsigned char *_ _skb_put(struct sk_buff *skb, int len);
在缓冲区末尾添加数据,前 一个函数会进行检查
9.1.1 网络协议接口层
unsigned char *skb_push(struct sk_buff *skb, int len); unsigned char *_ _skb_push(struct sk_buff *skb, int len); 缓冲区头部添加数据
第9章
Linux网络设备驱动程序
本章目标
了解Linux网络驱动程序的数据交换过程 掌握移植和编写具体网卡驱动程序的方法
本章结构
Linux网络设备驱动的结构 网络设备的注册、注销和初始化 网络设备的打开和释放 Linux网络设备驱动程序 数据包发送 数据包接收 网络连接状态
参数设置和统计数据
Linux网络设备简介
网络设备,又叫网络接口是Linux第三类标准设备 网络设备和块设备类似,在内核的特定数据结构中注册自 己 当发生网络数据交换时,网络设备驱动程序注册的方法将 被内核调用 网络设备不会在/dev下存在一个设备入口,它使用保留的 内部设备名
网络设备的特点
网络设备异步的接收外来的数据包,有别于其他设备
网络设备主动的“请求”将硬件获得的数据包压入内 核,而其他设备例如块设备被“请求”向内核发送缓 冲区 网络设备同时要执行大量的管理任务
在可填充缓冲区之前保留包头空间
unsigned char *skb_pull(struct sk_buff *skb, int len); 从数据包头拿出数据,通常用来剥离数据包头
9.1.2 网络设备接口层
net_device 结构
该结构是网络设备驱动的核心,它包含了许多成员。 可以参考<include/linux/netdevice.h>文件,阅读它的完整定义。 net_device结构可分为
9.1.1 网络协议接口层
struct sk_buff *alloc_skb(unsigned int len, int priority); struct sk_buff *dev_alloc_skb(unsigned int len); 分配套接字缓冲区
void kfree_skb(struct sk_buff *skb); void dev_kfree_skb(struct sk_buff *skb); 释放套接字缓冲区
netif_start_queue()和netif_stop_queue()两个函数的原型
描述设备的I/O基地址 描述设备中断号 描述多端口设备的活动端口 描述设备的DMA通道
9.1.2 网络设备接口层
接口信息
int (*open)(structຫໍສະໝຸດ Baidunet_device *dev);
打开接口。当ifconfig激活网络设备 时,接口被打开。通常我们在open方 法里面完成资源的分配,包括I/O映射、 中断注册、DMA注册等。同时激活硬 件,并增加使用计数
dev_queue_xmit(struct sk_buff *skb);
上层对数据包的接收也通过向netif_rx()函数:
int netif_rx(struct sk_buff *skb);
9.1.1 网络协议接口层
套接字缓冲区(sk_buff)结构
套接字缓冲区(sk_buff)结构是Linux内核网络子系统的核心内 容,在<linux/skbuff.h>中被定义 sk_buff结构中的重要字段: struct net_device *rx_dev; 分别为接收和发送缓冲区的设备 struct net_device *dev; union { /* ... */ } h; union { /* . . . */ } nh; union { /*... */} mac;