struct sk_buff 学习

本文深入介绍了Linux内核中sk_buff数据结构,它是网络数据包处理的核心。文章详细解释了sk_buff的主要成员变量及其作用,并提供了关键函数的说明,如sk_put、sk_push等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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_putL2层接收数据时,将除了数据帧头部(已经拷贝)的内容包考到sk_buff数据缓冲区
sk_push发送数据时,高层->低层添加头部(data指针改变)
sk_pull接收数据时,低层->高层去掉头部(data指针改变)
sk_reserveL2层开始接收数据前,保持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的作用在单处理器上,关中断.多处理器上, 通过一个原子变量,保证函数的执行安全.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值