Linux内核-网络代码-关键的数据结构(struct sk_buff、struct net_device)

本文详细解析了Linux内核中的structsk_buff结构,介绍了其组成部分、用途,以及与网络设备、套接字相关的管理函数如skb_put、skb_push、skb_pull和内存分配函数如alloc_skb和dev_alloc_skb的用法。
摘要由CSDN通过智能技术生成

1、struct sk_buff结构体解析

struct sk_buff:一个封包就存储在这里。所有网络分层都会使用这个结构来储存其报头、有关用户数据的信息(有效载荷),以及用来协调其工作的其他内部信息。

struct net_device:在Linux内核中每种网络设备都用这个数据结构表示,包括软硬件的配置信息。

struct sk_buff定义在#include <linux/skbuff.h>

struct sk_buff {
        union {
                struct {
                        /* These two members must be first. */
                        struct sk_buff          *next;        /* 下一个struct sk_buff结构 */
                        struct sk_buff          *prev;        /* 前一个struct sk_buff结构 */

                        union { 

/*报文到达或者离开的时间戳; Time we arrived 表示这个skb的接收到的时间, 一般是在包从驱动中往二层发送的接口函数中设置 */

                                ktime_t         tstamp;        /* 通常只对一个已接收的封包才有意义。时间戳标记,用于表示封包何时被接收,或者有时用于表示封包预定传输的时间。此字段由netif_rx函数用net_timestamp设置,该函数在接收每个封包之后由设备驱动程序调用 */
                                struct skb_mstamp skb_mstamp;
                        };
                };
                struct rb_node  rbnode; /* used in netem & tcp stack */
        };
        struct sock             *sk;                /* 用户存储套接字的网络信息,该包属于哪个socket */
        struct net_device       *dev;          /* 收到这个包的网络设备的信息 */

        /*
         * 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] __aligned(8);

        unsigned long           _skb_refdst;

/* 当此缓冲区被删除时,可以完成某些工作。当此缓冲区不属于一个套接字时,destructor通常不会被初始化。当此缓冲区属于一个套接字时,一般都是设置为sock_rfree或者sock_wfree。 */
        void                    (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_XFRM
        struct  sec_path        *sp;
#endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
        struct nf_conntrack     *nfct;
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        struct nf_bridge_info   *nf_bridge;
#endif
        unsigned int            len,        /* 分片数据区和连续数据区的总长度 */
                                data_len;      /* 分片结构体数据区的总长度 */
        __u16                   mac_len,        /* MAC报头的长度 */
                                hdr_len;            /* 用于clone的时候,它表示clone的skb的头的长度 */

        /* Following fields are _not_ copied in __copy_skb_header()
         * Note that queue_mapping is here mostly to fill a hole.
         */
        kmemcheck_bitfield_begin(flags1);
        __u16                   queue_mapping;        /* 多队列的设备应用,也就是说映射到哪个队列 */
        __u8                    cloned:1,
                                nohdr:1,
                                fclone:2,
                                peeked:1,
                                head_frag:1,
                                xmit_more:1;
        /* one bit hole */
        kmemcheck_bitfield_end(flags1);

        /* fields enclosed in headers_start/headers_end are copied
         * using a single memcpy() in __copy_skb_header()
         */
        /* private: */
        __u32                   headers_start[0];
        /* public: */

/* if you move pkt_type around you also must adapt those constants */
#ifdef __BIG_ENDIAN_BITFIELD
#define PKT_TYPE_MAX    (7 << 5)
#else
#define PKT_TYPE_MAX    7
#endif
#define PKT_TYPE_OFFSET()       offsetof(struct sk_buff, __pkt_type_offset)

        __u8                    __pkt_type_offset[0];
        __u8                    pkt_type:3;
        __u8                    pfmemalloc:1;
        __u8                    ignore_df:1;
        __u8                    nfctinfo:3;

        __u8                    nf_trace:1;
        __u8                    ip_summed:2;
        __u8                    ooo_okay:1;
        __u8                    l4_hash:1;
        __u8                    sw_hash:1;
        __u8                    wifi_acked_valid:1;
        __u8                    wifi_acked:1;

        __u8                    no_fcs:1;
        /* Indicates the inner headers are valid in the skbuff. */
        __u8                    encapsulation:1;
        __u8                    encap_hdr_csum:1;
        __u8                    csum_valid:1;
        __u8                    csum_complete_sw:1;
        __u8                    csum_level:2;
        __u8                    csum_bad:1;

#ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
#endif
        __u8                    ipvs_property:1;
        __u8                    inner_protocol_type:1;
        __u8                    remcsum_offload:1;
        /* 3 or 5 bit hole */

#ifdef CONFIG_NET_SCHED
        __u16                   tc_index;       /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
        __u16                   tc_verd;        /* traffic control verdict */
#endif
#endif

        union {
                __wsum          csum;
                struct {
                        __u16   csum_start;
                        __u16   csum_offset;
                };
        };
        __u32                   priority;       /* 优先级,主要用于QOS */ 
        int                     skb_iif;
        __u32                   hash;
        __be16                  vlan_proto;
        __u16                   vlan_tci;
#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
        union {
                unsigned int    napi_id;
                unsigned int    sender_cpu;
        };
#endif
#ifdef CONFIG_NETWORK_SECMARK
        __u32                   secmark;
#endif
        union {
                __u32           mark;
                __u32           reserved_tailroom;
        };

        union {
                __be16          inner_protocol;
                __u8            inner_ipproto;
        };

        __u16                   inner_transport_header;        /*  */
        __u16                   inner_network_header;
        __u16                   inner_mac_header;

        __be16                  protocol;        /* 协议类型 */
        __u16                   transport_header;        /* 传输层头部 */
        __u16                   network_header;        /* 网络层头部 */
        __u16                   mac_header;        /* 链路层头部 */

        /* private: */
        __u32                   headers_end[0];
        /* public: */

        /* These elements must be at the end, see alloc_skb() for details.  */
        sk_buff_data_t          tail;        /* 实际数据区的尾端 */
        sk_buff_data_t          end;        /* 数据区的尾端 */
        unsigned char           *head,        /* 数据区的起始位置 */
                                *data;                /* 实际数据区的起始位置 */

/* 这些字段代表缓冲区的边界以及其中的数据。当每一分层为其工作而准备缓冲区时,可能会为一个报头或更多的数据分配更多的空间。head和end指向已分配缓冲区空间的开端和尾端,而data和tail则指向实际数据的开端和尾端。可以在head和data之间的空隙中填上一个协议报文头 */

/*  */
        unsigned int            truesize;

/* 这个是在缓冲区中实例化的计数。其作用就是在销毁skb结构体时,先查看users是否为0,若不为0,则调用函数递减下引用计数users即可;当销毁时,users为0才真正释放内存空间。有两个操作函数:atomic_inc()计数增加1;atomic_dec()计数jian'qu */
        atomic_t                users;
};

2、struct sk_buff结构体的管理函数

        skb_put之前和之后

       

         skb_push之前和之后

        

         skb_pull

        skb_reserver

         分配内存:alloc_skb和dev_alloc_skb

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
struct sk_buffLinux内核中定义的网络数据包缓冲区的结构体。它包含了各种用于存储和操作网络数据包的信息和属性。 struct sk_buff的定义位于`include/linux/skbuff.h`头文件中,其结构如下: ```c struct sk_buff { struct sk_buff *next; struct sk_buff *prev; struct sk_buff_head *list; struct sock *sk; struct net_device *dev; struct net_device *real_dev; unsigned char *head; unsigned char *data; unsigned char *tail; unsigned char *end; unsigned int len; unsigned int data_len; unsigned int truesize; unsigned int csum; unsigned int ip_summed; // ... }; ``` 下面是一些常用的struct sk_buff成员变量的解释: - next和prev:用于将多个sk_buff连接成链表,方便管理和处理。 - list:指向所属链表的头部,用于链表操作。 - sk:指向关联的socket结构,用于与网络套接字相关的操作。 - dev:指向接收/发送该数据包的网络设备。 - head、data、tail和end:指针,用于定位数据包的不同部分,如头部、数据、尾部和缓冲区末尾。 - len:数据包的总长度(包括头部和数据)。 - data_len:数据长度,即实际有效数据的长度。 - truesize:sk_buff实际占用的内存大小。 - csum:数据包的校验和。 - ip_summed:用于指示是否进行IP层校验和计算。 除了上述成员变量外,struct sk_buff还包含其他一些用于网络协议处理的字段,如协议类型、标志位等。 通过使用struct sk_buffLinux内核可以高效地传递、处理和管理网络数据包。它提供了丰富的属性和方法,使得网络协议栈能够对数据包进行灵活的操作和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值