dpsk和bpsk的区别(简单讲解skbuff结构分析)
dpsk和bpsk的区别(简单讲解skbuff结构分析)
2024-06-28 08:08:08  作者:喜欢你空气  网址:https://m.xinb2b.cn/know/cxv319567.html

前言:

以下是根据《深入理解Linux网络技术内幕》对sk_buff的相关总结,由于是刚刚看这本书(太厚了),不免在前期出现错误,随着对此书的深入我会在修改前面的错误,也希望各位牛人给予指点。帮助我成长。

sk_buff分析:

sk_buff是Linux网络代码中最重要的结构体之一。它是Linux在其协议栈里传送的结构体,也就是所谓的“包”,在他里面包含了各层协议的头部,比如ethernet, IP ,tcp ,udp等等。也有相关的操作等。熟悉他是进一步了解Linux网络协议栈的基础。

此结构定义在<include/linux/skbuff.h>头文件中,结构体布局大致可分为以下四部分:l 布局(layout)

l 通用(general)

l 功能专用(feature-specific)

l 管理函数(management functions)

网络选项以及内核结构

我们可以看到在此结构体里有很多预处理,他是在需要指定相应功能时才起作用,我们在这里先对通用的作出分析。布局字段:

sk_buff是一个复杂的双向链表,在他结构中有next和prev指针,分别指向链表的下一个节点和前一个节点。并且为了某些需求(不知道是哪些目前)需要很快定位到链表头部,所以还有一个指向链表头部的指针list(我在2.6.25内核没有发现这个指针)。sk_buff_head结构是:

struct sk_buff_head { struct sk_buff *next; struct sk_buff *prev; __u32 qlen; //代表元素节点数目 spinlock_t lock; //加锁,防止对表的并发访问};

dpsk和bpsk的区别(简单讲解skbuff结构分析)(1)

struct sock *sk

这个指针指向一个套接字sock数据结构。当数据在本地产生或者本地进程接受时,需要这个指针;里面的数据会有TCP/udp和用户态程序使用。如果是转发此指针为NULL

更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.

dpsk和bpsk的区别(简单讲解skbuff结构分析)(2)

dpsk和bpsk的区别(简单讲解skbuff结构分析)(3)

Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂

unsigned int len

缓冲区中数据块大小。长度包括:主要缓冲区(head所指)的数据以及一些片断(fragment)的数据。当包在协议栈向上或向下走时,其大小会变,因为有头部的丢弃和添加。

unsigned int data_len

片段中数据大小

unsigned int mac_len

mac包头大小

atomic_t users

引用计数,使用这个sk_buff的使用者的数目,可能有多个函数要使用同一个sk_buff所以防止提前释放掉,设置此计数unsigned int truesize

此缓冲区总大小,包括sk_buff。sk_buff只不过是个指针的集合,他所指的才是真正的数据区,所以是两部分。(见下图)sk_buff_data_t tail;

sk_buff_data_t end;

unsigned char *head, *data;

这些指针很重要,他们指向的是真正的数据区,他们的边界。head和end指向的是数据区的开端和尾端(注意和data,tail区别)如下图,data和tail指向的是实际数据的开头和结尾。

因为数据区在协议栈走的时候要一层层添加或去掉一些数据(比如报头)所以申请一块大的足够的内存,然后在往里放东西。真实的实际数据可能用不了这么多,所以用data,tail指向真实的,head,tail指向边界。刚开始没填充数据时前三个指针指向的是一个地方。

dpsk和bpsk的区别(简单讲解skbuff结构分析)(4)

void (*destructor) (…….)

此函数指针被初始化一个函数,当此缓冲区删除时,完成某些工作。通用字段

struct timeval stamp(2.6.25没有,估计是ktime_t tstamp)

时间戳,表示何时被接受或有时表示包预定的传输时间struct net_device *dev

描述一个网络设备,我会以后分析他。sk_buff_data_t transport_header; //L4

sk_buff_data_t network_header; //L3

sk_buff_data_t mac_header; //L2

这些指针分别指向报文头部,和2.4版本比较有了变化,不再是联合体,使用更加方便了,Linux给出了很方便的函数直接定位到各层的头部。下图是2.4版本的,只是说明一下。

dpsk和bpsk的区别(简单讲解skbuff结构分析)(5)

struct dst_entry dst

路由子系统使用。目前不知道怎么回事呢。据说比较复杂。char cb[40]

缓冲控制区,用来存储私有信息的空间。比如tcp用这个空间存储一个结构体tcp_skb_cb ,可以用宏TCP_SKB_CB(__skb)定位到他,然后使用里面的变量。ip_summed:2

__wsum csum;

校验和unsigned char pkt_type

根据L2层帧的目的地址进行类型划分。unsigned char cloned

表示该结构是另一个sk_buff克隆的。__u32 priority;

QoS等级__be16 protocol;

从L2层设备驱动看使用在下一个较高层的协议。功能专用字段

Linux是模块化的,你编译时可以带上特定功能,比如netfilter等,相应的字段才会生效。应该是那些预定义控制的。

管理函数

下面这个图是:(a*)skb_put; (b*) skb_push; (c*) skb_pull (d*) skb_reserve的使用,主要是对skb_buf所指向的数据区的指针移动。(数据预留以及对齐)

dpsk和bpsk的区别(简单讲解skbuff结构分析)(6)

下图是用skb_reserve函数,把一个14字节的ethernet帧拷贝到缓冲区。skb_reserve(skb, 2), 2表示16字节对齐。14 2=16

dpsk和bpsk的区别(简单讲解skbuff结构分析)(7)

分配内存:

alloc_skb 分配缓冲区和一个sk_buff结构

dev_alloc_skb 设备驱动程序使用的缓冲区分配函数

释放内存:

kfree_skb 只有skb->users计数器为1时才释放

dev_kfree_skb

缓冲区克隆函数 skb_clone

列表管理函数:

skb_queue_head_init

队列初始化skb_queue_head , skb_queue_tail

把一个缓冲区添加到队列头或尾skb_dequeue, skb_dequeue_tail

从头或尾去掉skb_queue_purge

把队列变空skb_queue_walk

循环队列每个元素

内核也新增了几个函数,来提供获取这些偏移的接口:#ifdef NET_SKBUFF_DATA_USES_OFFSET如果使用了offset来表示偏移的话,就是说是一个相对偏移的情况:static inline unsigned char *skb_transport_header(const struct sk_buff *skb){ return skb->head skb->transport_header;}static inline void skb_reset_transport_header(struct sk_buff *skb){ skb->transport_header = skb->data - skb->head;}static inline void skb_set_transport_header(struct sk_buff *skb, const int offset){ skb_reset_transport_header(skb); skb->transport_header = offset;}static inline unsigned char *skb_network_header(const struct sk_buff *skb){ return skb->head skb->network_header;}static inline void skb_reset_network_header(struct sk_buff *skb){ skb->network_header = skb->data - skb->head;}static inline void skb_set_network_header(struct sk_buff *skb, const int offset){ skb_reset_network_header(skb); skb->network_header = offset;}static inline unsigned char *skb_mac_header(const struct sk_buff *skb){ return skb->head skb->mac_header;}static inline int skb_mac_header_was_set(const struct sk_buff *skb){ return skb->mac_header != ~0U;}static inline void skb_reset_mac_header(struct sk_buff *skb){ skb->mac_header = skb->data - skb->head;}static inline void skb_set_mac_header(struct sk_buff *skb, const int offset){ skb_reset_mac_header(skb); skb->mac_header = offset;}#else 不使用相对偏移的情况static inline unsigned char *skb_transport_header(const struct sk_buff *skb){ return skb->transport_header;}static inline void skb_reset_transport_header(struct sk_buff *skb){ skb->transport_header = skb->data;}static inline void skb_set_transport_header(struct sk_buff *skb, const int offset){ skb->transport_header = skb->data offset;}static inline unsigned char *skb_network_header(const struct sk_buff *skb){ return skb->network_header;}static inline void skb_reset_network_header(struct sk_buff *skb){ skb->network_header = skb->data;}static inline void skb_set_network_header(struct sk_buff *skb, const int offset){ skb->network_header = skb->data offset;}static inline unsigned char *skb_mac_header(const struct sk_buff *skb){ return skb->mac_header;}static inline int skb_mac_header_was_set(const struct sk_buff *skb){ return skb->mac_header != NULL;}static inline void skb_reset_mac_header(struct sk_buff *skb){ skb->mac_header = skb->data;}static inline void skb_set_mac_header(struct sk_buff *skb, const int offset){ skb->mac_header = skb->data offset;}#endif 1、TCP层获取相关偏移的函数static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb){ return (struct tcphdr *)skb_transport_header(skb);}这个函数用来获得sk_buff结构中TCP头的指针static inline unsigned int tcp_hdrlen(const struct sk_buff *skb){ return tcp_hdr(skb)->doff * 4;}这个函数用来获得TCP头的长度static inline unsigned int tcp_optlen(const struct sk_buff *skb){ return (tcp_hdr(skb)->doff - 5) * 4;}获取tcp option的长度2、IP相关的函数static inline struct iphdr *ip_hdr(const struct sk_buff *skb){ return (struct iphdr *)skb_network_header(skb);}该函数获得ip头static inline struct iphdr *ipip_hdr(const struct sk_buff *skb){ return (struct iphdr *)skb_transport_header(skb);}该函数获得ipip头,实际上偏移已经跑到了传输层的开始3、MAC相关函数static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb){ return (struct ebt_802_3_hdr *)skb_mac_header(skb);}获取802.3MAC头指针。static inline struct ethhdr *eth_hdr(const struct sk_buff *skb){ return (struct ethhdr *)skb_mac_header(skb);}获取以太网MAC头指针。以太网头指针结构体: struct ethhdr { unsigned char h_dest[ETH_ALEN]; unsigned char h_source[ETH_ALEN]; __be16 h_proto; } __attribute__((packed));内核中网络地址转化为字符串形式的IP地址的宏定义:#define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] #define NIPQUAD_FMT "%u.%u.%u.%u"

- - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

转载地址:简单讲解sk_buff结构分析 - 圈点 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

dpsk和bpsk的区别(简单讲解skbuff结构分析)(8)

  • lol狗头最强出装又能扛又能打(LOL狗头1级750层Q神装单挑大龙)
  • 2024-06-29LOL狗头1级750层Q神装单挑大龙★游戏马蹄铁原创,禁止商转违者必究LOL里狗头是一个拥有成长型技能的英雄,他的Q技能在游戏后期可谓是毁天灭地的伤害秒塔秒龙秒基地都不在话下,那么当一只只有1级的狗头他有了750层的Q之后是否能够击杀大。
  • 怎么看我的微信群(查看微信群的方法)
  • 2024-06-29查看微信群的方法微信没有保存的群在通讯录中是找不到的,先打开手机里的微信进入到微信的首页后点击底部导航栏中的【通讯录】选项然后在通讯录界面中找到【群聊】并点击打开在群聊界面中显示的微信群并不是所有的,只是保存到通讯录。
  • 盖尔加朵和神奇女侠谁厉害(神奇女侠盖尔加多)
  • 2024-06-29神奇女侠盖尔加多虽然在许多好莱坞大片中饰演各种不同角色的GailGadot,但都有同一个词可以来形容她,那就是性感而我也相信盖尔的性感绝对是独一无二的女神在《速度与激情》中的一个镜头在《了不起的女人》这部电影中,这部。
  • 鼓舞的近义词和反义词(鼓舞的意思)
  • 2024-06-29鼓舞的意思鼓舞的近义词:慰勉、驱策、鼓动、策动、推动、勉力、激发、勉励、激动、激劝、激励、鞭策、促进、鼓励鼓舞的反义词:打击、丧气、颓废、消沉、颓丧等等鼓舞,拼音是gǔwǔ,意思是使振作起来,增强信心或勇气;兴。
  • 洋葱不要直接炒多加一步(洋葱这个做法真香)
  • 2024-06-29洋葱这个做法真香洋葱是咱们平常生活中特别常见的一种食材,很多朋友比较喜欢吃,而且洋葱的营养价值也比较高今天就用洋葱来给大家分享一道特别好吃的美食,这道美食就是洋葱鸡蛋早餐饼,吃起来酥软可口,咸香有味最重要的是它的做法。
  • v型脸提拉面膜(告别U形条打造完美小V脸)
  • 2024-06-29告别U形条打造完美小V脸众所周知,“女为悦己者容!”自从有了人类文明以来,女性就有了美化自身的追求,拥有年轻的肌肤是每一个爱美女性必生追求的梦想而女性要想有肌肤水润光泽就离不开面膜的悉心呵护,蕴含美丽因子的面膜更能让女人美丽。
  • 林汉杰是啥电视剧里面的(追剧啦为了顾全事业大局)
  • 2024-06-29追剧啦为了顾全事业大局在《天涯热土》第八集片尾中红丰场一大早便不得安宁一群乐安镇百姓来到场里质问林汉杰等人为何要把米粮店的粮食全买走?这场敌特组织故意制造的粮荒行动被共产党识破了林汉杰等人将对制造粮荒的敌特组织采取什么行动。
  • 巴甫洛夫成功秘诀(你属于哪种气质)
  • 2024-06-29你属于哪种气质情绪根源到底来自哪里?是心理学界和生物学界,至今没有讨论清楚的难题首先掌握男女一般情绪的心理规律,再结合特定的对象、环境、自然容易掌握与异性打交道的技巧,在看看哪种气质类型的人最易情绪化?所谓“气质”。
  • 翡翠的鉴别(如何鉴别翡翠)
  • 2024-06-29如何鉴别翡翠看翡翠的真假可以听声音的用绳子绑住翡翠并悬空吊起来后,用木筷子轻轻敲击翡翠几次如果翡翠可以发出比较清脆、悦耳的声音,就说明翡翠是真的如果翡翠发出的声音是沉闷的,就说明翡翠是假的辨别翡翠的真假也可以测硬。
  • 歌声与微笑原唱(大家可以去听听)
  • 2024-06-29大家可以去听听《歌声与微笑》是王健作词,谷建芬作曲,上海小荧星儿童合唱团演唱的一首歌曲,发行于1986年1989年,该歌曲获得中国校园歌曲创作大奖赛优秀奖1986年8月底,王健收到上海电视台的一封约稿信,请她为第一。
  • dnf领主之塔可以换的换装武器(领主之塔里的70SS套值得做吗)
  • 2024-06-29领主之塔里的70SS套值得做吗领主之塔更新后也没怎么刷,大体的更新内容也是知道的只是没有好好的看过相关的装备属性更新后的亮点除了魂链,那就是60跟70的SS套了60SS套就不说了,一般情况也没人会去做了等级有点低,套装属性也没啥好。
  • 饥荒齿轮怪会刷新吗(饥荒游戏讲述了什么)
  • 2024-06-29饥荒游戏讲述了什么饥荒齿轮怪不会刷新,获得齿轮的方法:一个是杀掉齿轮怪,一个是捡风滚草有几率获得饥荒游戏讲述的是关于一名科学家被恶魔传送到了一个神秘的世界,玩家将在这个异世界生存并逃出这个异世界的故事是由KleiEnt。