套接口缓存-Linux网络内核数据结构sk_buff

套接口缓存-Linux网络内核数据结构sk_buff

网络协议中的操作对系统的存储及设计要求都非常高:

  • 能够很方便地处理可变长缓存,因为接收和发送的数据报长度不是固定的。
  • 能够很容易地实现在头尾部添加和移除数据,因为这些缓存区需要在不同网络层次间进行传递。
  • 在添加和移除数据时能够尽量避免数据的复制。

以上这些操作将会直接影响网络处理的性能。在Linux网络子系统中称为套接口缓存(socket buffer),相应的数据结构为sk_buffer,在下文中将简称为sk_buff。

sk_buff是Linux网络代码中最重要的结构体之一。它是Linux在其协议栈里传输的结构体,也就是”包“。用来描述已接收或者待发送的数据报文信息,skb在不同网络协议层之间传递,可被用于不同网络协议。所有网络分层(MAC或L2分层上的另一种链路层协议,L3的IP,L4的TCP或UDP)都会使用这个结构来存储其报头,有关用户数据的信息,以及用来协调其工作的其他内部信息。当该结构从一个分层传到另一个分层时,其不同的字段会随之发生改变。四层向三层传递前会添加一个四层首部,同样,三层向二层传递前也会添加一个三层首部。在不同层数据传递时,通过附加报头的形式,减少了拷贝带来的开销。添加首部比在不同层之间复制数据效率更高。由于在数据缓存区的头部添加数据意味着要修改指向数据缓存区的指针,这是个复杂的操作,所以内核提供了skb_reserve()来完成这个功能。协议栈中的每一层在往下一层传递sk_buff前,首先调用该函数在数据缓存区头部预留出的空间。如果是向上层协议传递sk_buff,则下层协议层的首部信息就没有用了。例如,二层首部只有在网络驱动处理二层协议时有用,三层是不会关心的。但是内核并没有把二层首部从数据缓存区中删除,而只是把有效载荷指向三层首部,这样做能很大程度上提高效率。

sk_buff结构体

sk_buff有两个部分,一部分为sk_buff结构本身,另一部分为数据缓存区(参见sk_buff结构的head成员),以下是对sk_buff结构的详细描述,包括各个成员:

struct sk_buff {
         /* These two members must be first. */
         struct sk_buff          *next;
         struct sk_buff          *prev;
 
         struct sock             *sk;
         struct skb_timeval      tstamp;
         struct net_device       *dev;
         struct net_device       *input_dev;
 
         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[48];
 
         unsigned int            len,
                                 data_len,
                                 mac_len,
                                 csum;
         __u32                   priority;
         __u8                    local_df:1,
                                 cloned:1,
                                 ip_summed:2,
                                 nohdr:1,
                                 nfctinfo:3;
         __u8                    pkt_type:3,
                                 fclone:2,
                                 ipvs_property:1;
         __be16                  protocol;
 
         void                    (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
         __u32                   nfmark;
         struct nf_conntrack     *nfct;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
         struct sk_buff          *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
         struct nf_bridge_info   *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#ifdef CONFIG_NET_SCHED
         __u16                   tc_index;       /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
         __u16                   tc_verd;        /* traffic control verdict */
#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;
};
  • struct sk_buff *next;

    struct sk_buff *prev;

    分别表示前驱和后继节点。这两个域用来连接相关的sk_buff,如果有分片,将这些分片连接在一起

  • struct sock *sk;

    指向拥有此套接字缓冲区的sock数据结构

  • struct skb_timeval tstamp;

    记录报文到达或离开的时间戳

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值