Chinaunix首页 | 论坛 | 博客
  • 博客访问: 592000
  • 博文数量: 92
  • 博客积分: 5026
  • 博客等级: 大校
  • 技术积分: 1321
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-28 11:04
文章分类

全部博文(92)

文章存档

2011年(9)

2010年(17)

2009年(12)

2008年(54)

我的朋友

分类: LINUX

2008-08-07 16:15:03

 

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的作用在单处理器上,关中断.多处理器上, 通过一个原子变量,保证函数的执行安全.

阅读(1655) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~