- 应用层 (TELNET、FTP、DNS)
- 传输层(TCP、UDP)
- Internet(IP)
- 网络接口物理层(PPP/SLIP、LAN)
- 发送数据
当缓冲区被传送到硬件以后,硬件应答信号标识传输已经完毕,驱动程序必须调用dev_kfree_skb(skb, FREE_WRITE)函数释放缓冲区,一旦该调用结束,缓冲区就会很自然地消失,这样,驱动程序就不能再涉及缓冲区了。sk_buff是被锁住的(locked),确保其他程序不会存取它。
数据帧在传送之前先要排成对列,在加入队列之前,还要在每个数据帧的开始添加硬件帧头,这项工作对于数据传送非常必要。网络设备驱动程序提供了一个dev->hard_header()例程,来完成添加硬件帧头的工作。协议层在发送数据之前会在缓冲区的开始留下至少 dev->hard_header_len 长度字节的空闲空间。这样dev->hard_header()程序只要调用 skb_push(),然后正确填入硬件帧头就可以了。
- 接收数据
PACKET_BROADCAST 链接层广播地址
PACKET_MULTICAST 链接层多路地址
PACKET_SELF 发给自己的数据帧
PACKET_OTHERHOST 发向另一个主机的数据帧 (监听模式时会有到)
最后,设备驱动程序调用netif_rx()把缓冲区向上传递给协议层。netif_rx()将数据放入处理队列后返回,真正的处理是在中断返回后,可以减少中断时间。一旦netif_rx( )被调用,缓冲区就不在属设备驱动程序所有,它不能被修改,而且设备驱动程序也不能再涉及它了。
在协议层,接收数据包的流程控制分两个层次: 首先,netif_rx()函数限制了从物理层到协议层的数据帧的数量。第二,每一个套接字都有一个队列,限制从协议层到套接字层的数据帧的数量。在传输方面,驱动程序的dev->tx_queue_len 参数用来限制队列的长度。队列的长度通常是100帧,在进行大量数据传输的高速连接中,它足以容纳下所有等待传输的缓冲区,不会出现大量缓冲区阻塞的情况。在低速连接中,例如Slip 连接,队列的长度长设为10帧左右,因为传输10帧的数据就要花费数秒的时间排列数据。
int (*init)(struct net_device *dev);
int (*open)(struct net_device *dev);
int (*stop)(struct net_device *dev);
struct sk_buff *alloc_skb(unsigned int len, int priority);
struct sk_buff *dev_alloc_skb(unsigned int len);
分配一个缓冲区。alloc_skb函数分配一个缓冲区并初始化skb->data和skb->tail为skb->head。参数len为数据缓冲区的空间大小,通常以L1_CACHE_BYTES字节(对ARM为32)对齐,参数priority为内存分配的优先级。dev_alloc_skb()函数以GFP_ATOMIC优先级进行skb的分配。
释放缓冲区
void kfree_skb(struct sk_buff *skb);void dev_kfree_skb(struct sk_buff *skb);
操作函数unsigned char *skb_put(struct sk_buff *skb, int len);unsigned char *skb_push(struct sk_buff *skb, int len);unsigned char *skb_pull(struct sk_buff *skb, int len);void skb_reserve(struct sk_buff ×skb, int len);
int (*hard_header)(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
int (*rebuild_header)(struct sk_buff *skb);
void (*tx_timeout)(struct net_device *dev);
struct net_device_stats *(*get_stats)(struct net_device *dev);
int (*do_ioctl)(struct net_device *dev, struct ifmap *map);