Chinaunix首页 | 论坛 | 博客
  • 博客访问: 505341
  • 博文数量: 157
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 1608
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-16 09:30
文章存档

2010年(155)

2008年(2)

我的朋友

分类:

2010-03-11 20:39:54


sk_buff结构分析
sk_buff是我们遇到的第二个重要的结构,在内核中经常被缩写成skb.在linux 2.6.21它被定义成:
struct sk_buff {
         //指向下一个skb
struct sk_buff               *next;
//上一个skb
         struct sk_buff               *prev;
 
         struct sk_buf0f_head   *list;
         //对应的sock。这也是个重要的结构,在传输层的时候我们再来分析
         struct sock          *sk;
         //接收或者发送时间戳
         struct timeval               stamp;
         //接收或者发送时对应的net_device
         struct net_device *dev;
         //接收的net_device
         struct net_device *input_dev;
         //数据包对应的真实net_device.关于虚拟设备可以在之后的网桥模式分析中讨论
         struct net_device *real_dev;
         //ip层的相关信息
         union {
                   struct tcphdr       *th;
                   struct udphdr      *uh;
                   struct icmphdr    *icmph;
                   struct igmphdr    *igmph;
                   struct iphdr         *ipiph;
                   struct ipv6hdr     *ipv6h;
                   unsigned char      *raw;
         } h;
         //协议层的相关信息
         union {
                   struct iphdr         *iph;
                   struct ipv6hdr     *ipv6h;
                   struct arphdr       *arph;
                   unsigned char      *raw;
         } nh;
         //链路层的相关信息
         union {
                unsigned char     *raw;
         } mac;
         //在路由子系统中再来分析这一结构
         struct  dst_entry        *dst;
         struct         sec_path    *sp;
 
         /*
          * This is the control buffer. It is free to use for every
          * layer. Please put your private variables there. If you
          * want to keep them across layers you have to do a skb_clone()
          * first. This is owned by whoever has the skb queued ATM.
          */
         char                     cb[40];
         //各层的数据长度
         unsigned int                  len,
                                     data_len,
                                     mac_len,
                                     csum;
         unsigned char                local_df,
                                     cloned,
                                     pkt_type,
                                     ip_summed;
         __u32                           priority;
         unsigned short              protocol,
                                     security;
 
         void                     (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
        unsigned long                  nfmark;
         __u32                           nfcache;
         __u32                           nfctinfo;
         struct nf_conntrack      *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
        unsigned int           nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
         struct nf_bridge_info    *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
         union {
                   __u32                  ifield;
         } private;
#endif
#ifdef CONFIG_NET_SCHED
       __u32                       tc_index;        /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
         __u32           tc_verd;               /* traffic control verdict */
         __u32           tc_classid;            /* traffic control classid */
#endif
 
#endif
 
 
         /* These elements must be at the end, see alloc_skb() for details.  */
         unsigned int                  truesize;
         //引用计数
         atomic_t              users;
         //存储空间的起始地址
         unsigned char      *head,
         //网络数据的起始起址
                                     *data,
         //存放网络数据的结束地址
                                     *tail,
         //存储空间的结束地址
                                     *end;
}
对应我们上面的网卡驱动分析。接收到的数据是存放在data至tail之间的区域。
Skb通常还有常用的几个函数,一一列举分析如下:
struct sk_buff *alloc_skb(unsigned int size,int gfp_mask)
分配存储空间为sixe的skb,内存分配级别为gfp_mask.注意这里的存储空间的含义,即为skb->data至skb->tail的区域
struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
克隆出的skb指向同一个结构,同时会增加skb的引用计数
struct sk_buff *skb_copy(const struct sk_buff *skb, int priority)
复制一个全新的skb
void kfree_skb(struct sk_buff *skb)
当skb的引用计数为1的时候,释放此skb
unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
使skb的存储空间扩大len.即使tail指针下移
unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
push,即推出一段数据,使data指针下层。
void skb_reserve(struct sk_buff *skb, unsigned int len)
该操作使data指针跟tail指针同时下移,即扩大存储区域之前的空间
int skb_headroom(const struct sk_buff *skb)
返回data之前可用的空间数量
int skb_tailroom(const struct sk_buff *skb)
返回缓存区中可用的空间大小
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/luoye144200720102030/archive/2009/06/04/4243358.aspx
阅读(834) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~