- 论坛徽章:
- 0
|
网络设备驱动的层次结构
1网络协议接口层 向网络层提供统一的数据包收发接口,dev_queue_xmit() netify_rx()
2网络设备接口层 向协议接口层提供用于描述具体网络设备属性和操作的结构体netdevice,该结构体
是设备驱动功能层中各函数的容器。从宏观上规划了具体操作硬件的设备功能层的结构
3设备驱动功能层 是驱使网络设备硬件完成相应动作的程序,通过hard_start_xmit()函数启动发送
动作,并通过设备上的中断触发接收操作。
4 网络设备和媒介层是王城数据包发送和接收的物理实体。
网络协议接口层
dev_queue_xmit(struct sk_buff *skb); int netif_rx(struct sk_buff *skb);
sk_buff成员
union {
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct ipv6hdr *ipv6h;
unsigned char *raw ;//数据链路层头部
}h;
union {
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
unsigned char *raw;
}nh;
union {
unsigned char *raw;
}mac;
head 指向已分配的用于承载网络数据的缓冲区起始地址。不变
data 指针指向对应当前协议层有效数据的起始地址,每个协议层的有效数据不一样。变
end 与data相对
end 则指向内存中分配的数据缓冲区结尾。不变
end 指向的缓冲区末尾还包括skb_shared_info结构体,存放分割存储的数据片,存放在不同的
内存空间中。长度1页
len 数据包有效数据的长度,包括协议头和负载
data_len 记录分片的数据存放
truesize sizeof(struct sk_buf)加上传入alloc_skb()函数或dev_alloc_skb()函数长度包括
skb_shared_info长度
==========================================================================
struct sk_buf * alloc_skb(unsigned int len, int priority);len数据缓冲区的空间。套接字
缓冲区和数据缓冲区
struct sk_buf * dev_allco_skb(unsigned int len);以GFP_ATOMIC(分配过程不能中断)调用上面
的函数,并保存skb->head 和skb->data之间的16字节
释放:void kfree_skb(struct sk_buff *skb);内核内部使用
void dev_kfree_skb(struct sk_buff *skb);网络设备驱动
void dev_kfree_skb_irq(struct sk_buff *skb);
void dev_kfree_skb_any(struct sk_buff *skb);
指针移动:
unsigned char * skb_put(struct sk_buff *skb, unsigned int len);
unsigned char * __skb_put(struct sk_buff *skb, unsigned int len);
将tail 指针下移,增加sk_buff的len值,返回skb_tail当前值。
unsigned char * skb_push(struct skb_buff *skb,unsigned int len);
unsigned char * __skb_push(struct skb_buff *skb,unsigned int len);
data指上移增加sk_buff的len,在存储空间增加网络数据包的空间,添加头部
unsigned char * skb_pull(struct skb_buff *skb,unsigned int len);
unsigned char * __skb_pull(struct skb_buff *skb,unsigned int len);
void skb_reserve(struct sk_buff *skb, unsigned int len)
tail data同时下移,主要用于在存储空间的头部预留len空间
============================================================================
net_device结构体在内核中指代一个网络设备,网络设备驱动只需填充net_device具体成员并
注册net_device即可实现硬件操作函数与内核的挂接。我们只需要考虑以下部分
1char name[IFNAMESIZE];//设备名称
int (*init)(struct net_device *dev);//如果设置了,被注册时调用
2unsigned long mem_end;
unsigned long mem_start;//定义设备所使用的共享内存的起始和结束地址。
unsigned long base_addr;IO 基地址
unsigned char irq;
unsigned char if_port;针对多端口
unsigned char dma;分配给设备的DMA通道
3 unsigned short hard_header_len; 硬件头长度,ETH_HLEN 14
unsigned short type;硬件类型
unsigned mtu; 最大传输单元
unsigned char dev_addr[MAX_ADDR_LEN];硬件地址6B
unsigned char broadcast[MAX_ADDR_LEN];广播地址6B
unsigned short flags; 网络接口标志
IFF_UP(设备被激活并可以开始发送数据)IFF_AUTOMEDIA(设备可以在多种媒介间转换)
IFF_BROADCAST(允许广播) IFF_DEBUG(调试模式,可以控制printk调用的详细程度)
IFF_LOOPBACK(回环) IFF_MUILTICAST(组播) IFF_NOARP(接口不能执行ARP) IFF_PIONTTOPOINT
4int (*open)(struct net_device *dev);
打开网络接口设备,获得IO地址,IRQ,DMA通道
int (*stop)(struct net_device *dev);
int (*hard_start_xmit(struct sk_buff *skb, struct net_device *dev);//启动数据包发送
int (*tx_timeout)(struct net_device *dev); //重启发送,重启硬件
int (*hard_header)(struct sk_buf *skb, struct net_device *dev, unsigned short type,
void *daddr,void *saddr, unsignedlen);
完成硬件帧头填充,返回填充的字节数
struct net_device_stats * (*get_stats)(struct net_device *dev);
用于获得网络设备的状态信息:如详细的流量统计信息,如发送数据包数,字节数
int (*do_ioctl)(struct net_device *dev,struct ifreq *if, int cmd);
int (*set_config_(struct net_device *dev, struct ifmap *map);改变IO地址和中断号
int (*set_mac_address)(struct net_device *dev, void *addr);MAC
int (*poll)(struct net_device *dev, int quota);
NAPI不采取中断的方式读取数据包,而采用借助中断唤醒数据包接收服务进程,以轮询方式读取
5 unsigned long trans_start;最后数据包开始发送时间戳
unsigned long last_rx; 接受
void *priv; 设备私有信息指针 netdev_priv()获取该指针
spinlock_t xmit_lock;
int xmit_lock_owner;当前xmit_lock自旋锁的CPU编号
===================================================================================
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/69624/showart_1071231.html |
|