struct sk_buff 学习 1.sk_buff是linux 网络内核里面最终要的数据结构了.存放要发送和接收的数据.头文件 linux/skbuff.h 2.主要成员以及相关结构函数分为以下几类 a.layout struct sk_buff *next; struct sk_buff *prev; struct sk_buff_head* list; 方便找到表头 __u32 qlen; 双链表里sk_buff结构的数量 spinlock_t lock; 保证操作链表安全 struct sock *sock; 指向tcp udp socket结构,如果数据被转发的话,该指针为NULL unsigned int len; 整个sk_buff链data_len的总和 unsigned int data_len; 当前sk_buff的数据长度.包含协议头部内容.各层传输时大小会变化 unsigned int mac_len; mac头部大小 atomic_t users; 引用计数.(skb_get kfree_skb改变) unsigned int truesize; data大小 + sizeof(sk_buff) unsigned char *head; unsigned char *data; unsigned char *tail; unsigned char *end; 以上都是数据段的指针 void (*destructor)(...) 当sk_buff某个socket的时候被初始化,通常执行sock_rfree或者sock_wfree b.general struct timeval stamp; 接收到数据时时间 struct net_device *dev; 网络设备,也很重要 struct net_device *input_dev; 输入设备 struct net_device *real_dev; 可用于虚拟设备 /* application 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; struct dst_entry dst; 路由子系统使用,复杂 char cb[40]; 控制缓冲区或者存放隐私信息,例如tcp用它来存放一个struct_skb_cb的结构体 struct tcp_skb_cb { ... ... ... _ _u32 seq; /* Starting sequence number */ _ _u32 end_seq; /* SEQ + FIN + SYN + datalen*/ _ _u32 when; /* used to compute rtt's */ _ _u8 flags; /* TCP header flags. */ ... ... ... }; unsigned int csum; unsigned char ip_summed; unsigned char cloned; 该sk_buff是否克隆的 unsigned char pkt_type; 根据L2层的目的地址判断,该数据包的类型,本机的,多播,广播,其他主机 __u32 priority; 发送和转发的QoS unsigned short protocol; L2层的协议类型.通常是ip ip6 arp rarp unsigned short security; IPSec,未使用 c.feature-specific unsigned long nfmark; __u32 nfcache; __u32 nfctinfo; struct nf_conntrack *nfct; unsigned int nfdebug; struct nf_bridge_info *nf_bridge; 以上字段netfilter模块使用. union {...} private HIPPI使用 __u32 tc_index; __u32 tc_verd; __u32 tc_classid; 以上字段用于traffic control struct sec_path *sp; 用于IPSec跟踪传输 d.manegement functions sk_put L2层接收数据时,将除了数据帧头部(已经拷贝)的内容包考到sk_buff数据缓冲区 sk_push 发送数据时,高层->低层添加头部(data指针改变) sk_pull 接收数据时,低层->高层去掉头部(data指针改变) sk_reserve L2层开始接收数据前,保持4字节对齐,data += 2
alloc_skb dev_alloc_skb 分配空间函数,默认用dev_alloc_skb.分配的空间包括两次,第一个是struct sk_buff,第二个是data_size + sizeof(struct skb_shared_info) kfree_skb dev_kfree_skb 释放sk_buff内存 struct skb_shared_info { 紧跟着data缓冲区后面,保存data缓冲区的相关信息的结构体 atomic_t dataref; unsigned int nr_frags; unsigned short tso_size; unsigned short tso_seqs; unsigned sk_buff *frag_list; skb_frag_t frags[MAX_SKB_FRAGS]; }; clone和copy clone:数据需要给其他的使用者时候(不会改变数据内容),会采用clone.分配一个新的sk_buff,并且 cloned属性为1,users属性为1,保证不要的时候释放内存.head data等仍然指向以前的data缓冲区.但是 保存data缓冲区的 struct skb_shared_info的dataref需要加一. copy:其他使用者需要改变data缓冲区的数据的时候使用.分配两块新的内存.不会设置clone位 相关函数:skb_clone pskb_copy(拷贝当前data缓冲区) skb_copy(拷贝所有data缓冲区)
skb_queue_head_init 初始化一个空链表 skb_queue_head skb_queue_tail 添加sk_buff到链表 skb_dequeue skb_dequeue_tail 删除sk_buff从链表 skb_queue_purge 清空sk_buff链表 skb_queue_walk 循环链表 进行这些函数的时候需要使用 : unsigned long flags; spin_lock_irqsave(...); function(); spin_unlock_irqrestore(...); spin的作用在单处理器上,关中断.多处理器上, 通过一个原子变量,保证函数的执行安全.
|