一个在线看Linux源码的网站http://lxr.free-electrons.com,需要翻墙
第二章 关键数据结构
本章讲述以下两个重要数据结构:
struct sk_buff:存储所有网络分层的包头、有效载荷,其他内部信息
struct net_device:网络设备的通用数据结构
sk_buff
布局:
书上sk_buff 写到的对分层头的设计是以union形式来表示,这是Linux 2.6.24之前的方式
/* Transport layer header */ union { struct tcphdr *th; struct udphdr *uh; struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; struct spxhdr *spxh; unsigned char *raw; } h; /* Network layer header */ union { struct iphdr *iph; struct ipv6hdr *ipv6h; struct arphdr *arph; struct ipxhdr *ipxh; unsigned char *raw; } nh; /* Link layer header */ union { struct ethhdr *ethernet; unsigned char *raw; } mac;
Linux 2.6.24后,这个分层的指针精简为了
#ifdef NET_SKBUFF_DATA_USES_OFFSETtypedef unsigned int sk_buff_data_t;#elsetypedef unsigned char *sk_buff_data_t;#endif...... sk_buff_data_t transport_header; sk_buff_data_t network_header; sk_buff_data_t mac_header;
L2到L3时报头指针变化:
管理函数:有很多名称类似do_something和__do_somthing,第一个是包裹函数,增加额外检查或者上锁,内部的__do_something通常不会直接调用。
报文经过每一层缓冲区处理的关键函数:
skb_reserve, skb_put, skb_push, skb_pull
主要是更新:skb->data, skb->len
skb_clone只是克隆了skb_buff的结构,指向相同的缓存,缓存保存了引用计数。
skb_copy是完全拷贝缓存。
sk_buff的队列管理要注意上spin_lock锁以保证原子操作。
net_device
包括真实设备和虚拟设备(VLAN或聚合口)
全局变量dev_base列表存储了所有设备的net_device,
每个net_device有唯一的ID。
混杂模式promiscuous mode:设备接收所有封包。
设备的统计数据存在于设备的驱动内,net_device结构只保存一个priv指针指向该数据结构,有线和无线设备关键字段有区别。