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的作用在单处理器上,关中断.多处理器上, 通过一个原子变量,保证函数的执行安全.
阅读(1513) | 评论(0) | 转发(1) |