本文主要注解skb_gro_receive函数,并画出示意图,便于理解。该函数是把前面已经判断过属于同一条流的skb合并到之前已经聚合过的skb上,把要合并的数据payload整理到已经合并的skb上去,下面根据代码逻辑画出4组示意图。

int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
{struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);unsigned int offset = skb_gro_offset(skb);unsigned int headlen = skb_headlen(skb);//线性区域长度unsigned int len = skb_gro_len(skb);//data部分的长度struct sk_buff *lp, *p = *head;//已经合并的报文的首地址unsigned int delta_truesize;if (unlikely(p->len + len >= 65536))return -E2BIG;lp = NAPI_GRO_CB(p)->last;pinfo = skb_shinfo(lp);
//headlen是skb的线性区域长度,offset是payload的偏移,如果headlen<offset说明还有一部分头部在非线性区域,也说明数据部分都在非线性区域if (headlen <= offset) {skb_frag_t *frag;skb_frag_t *frag2;int i = skbinfo->nr_frags;//skb的frags的个数int nr_frags = pinfo->nr_frags + i;//合并之后的总的frags的个数if (nr_frags > MAX_SKB_FRAGS) //如果nr_frags大于最大的限制,那么直接mergegoto merge;offset -= headlen;//此时的offset表示,在非线性区域,头部的长度pinfo->nr_frags = nr_frags;//更新nr_fragsskbinfo->nr_frags = 0;//skb的nr_frags置0frag = pinfo->frags + nr_frags;//指向已经合并的skb的最后一个frags[]frag2 = skbinfo->frags + i;//指向待合并的skb的最后一个frags[]do {*--frag = *--frag2;//已经合并的skb的frags[]指针指向待合并的skb的frags[]指针(先--,再赋值)} while (--i);frag->page_offset += offset;//frag[0]需要操作一下offset的问题,把头部的部分剔除skb_frag_size_sub(frag, offset);/* all fragments truesize : remove (head size + sk_buff) */delta_truesize = skb->truesize -SKB_TRUESIZE(skb_end_offset(skb));skb->truesize -= skb->data_len;skb->len -= skb->data_len;skb->data_len = 0;NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE;goto done;
} else if (skb->head_frag) {int nr_frags = pinfo->nr_frags;skb_frag_t *frag = pinfo->frags + nr_frags;//此flow合并后的最后一个分片包的skb_frag_t结构体执针struct page *page = virt_to_head_page(skb->head);//获取skb->head所在的pageunsigned int first_size = headlen - offset; //data部分的长度unsigned int first_offset;if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS) //合并后的frag数目大于最大的frag(17)数目直接mergegoto merge;first_offset = skb->data -(unsigned char *)page_address(page) +offset; //获取到payload到本page的offsetpinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags;//合并后分片的数量frag->page.p          = page;//页数据的首地址frag->page_offset = first_offset;//payload部分在该页的偏移skb_frag_size_set(frag, first_size);//frag->size是page中数据的长度memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags);// skb如果有 分片数组直接拷贝到后面/* We dont need to clear skbinfo->nr_frags here */delta_truesize = skb->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));//对齐NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;//置位,当前报文已经做过gro,待释放。goto done;}merge:delta_truesize = skb->truesize;if (offset > headlen) {unsigned int eat = offset - headlen;skbinfo->frags[0].page_offset += eat;skb_frag_size_sub(&skbinfo->frags[0], eat);skb->data_len -= eat;skb->len -= eat;offset = headlen;}__skb_pull(skb, offset);if (NAPI_GRO_CB(p)->last == p)skb_shinfo(p)->frag_list = skb;elseNAPI_GRO_CB(p)->last->next = skb;NAPI_GRO_CB(p)->last = skb;__skb_header_release(skb);lp = p;done:NAPI_GRO_CB(p)->count++;p->data_len += len; //非线性区域长度p->truesize += delta_truesize;p->len += len;if (lp != p) {lp->data_len += len;lp->truesize += delta_truesize;lp->len += len;}NAPI_GRO_CB(skb)->same_flow = 1;return 0;
}
EXPORT_SYMBOL_GPL(skb_gro_receive);

(1)headlen>offset

把待合并的skb的page首地址和offset保存到已经合并的skb的frags[]中保存。如果待合并的skb在非线性区域中还有数据,那么直接调用函数:memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags) 把待合并的skb的非线性区域的数据拷贝到已经合并的skb的非线性区域中。

a.待合并的skb的payload部分全部存在非线性区域

b.payload一部分在线性区域,一部分在非线性区域,存在frags[]中,示意图如下:

(2)headlen <= offset

a.headlen < offset 说明待拷贝的skb还有一部分头部在非线性区frags[0].

b.headlen = offset,头部全部存在线性区域

若有问题欢迎各位大神指正,互相学习进步

linux GRO相关相关推荐

  1. Linux centos7 Linux网络相关、firewalld和netfilter、netfilter5表5链介绍、iptables语法

    一. Linux网络相关 yum install net-tools ifconfig查看网卡ip ifup ens33开启网卡 ifdown ens33关闭网卡 设定虚拟网卡ens33:0 mii- ...

  2. 七周三次课(11月29日) 10.11 Linux网络相关 10.12 firewalld和netfilter 10.13 netfilter5表5链介绍 10.14 iptables语法...

    2019独角兽企业重金招聘Python工程师标准>>> 10.11 Linux网络相关 ifconfig 查看网卡ip (yum install net-tools) 安装 -a   ...

  3. Linux网络相关、firewalld、netfilter及其5表5链、iptables语法

    2019独角兽企业重金招聘Python工程师标准>>> 1.Linux 网络相关 ifconfig 查看网卡IP,见下图, net-tools 包之前安装过了,这边还可以执行这个命令 ...

  4. Linux网络相关知识

    2019独角兽企业重金招聘Python工程师标准>>> 10月25日任务 10.11 Linux网络相关 10.12 firewalld和netfilter 10.13 netfil ...

  5. 七周三次课(1月24日) 10.11 Linux网络相关 10.12 firewalld和netfilter 10.13 netfilter5表5链介绍 10.14 iptables语法...

    七周三次课(1月24日) 10.11 Linux网络相关 10.12 firewalld和netfilter 10.13 netfilter5表5链介绍 10.14 iptables语法 ====== ...

  6. mysql切换用户命令_linux基础04:linux用户相关的命令有哪些?怎样切换用户?

    通过前面的几节课,我们在windows系统中安装好了linux虚拟机,也通过xshell远程终端连接上了linux虚拟.从今天开始,我们就可以正式开始学习linux的知识了.今天,我们主要介绍的是用户 ...

  7. linux网络相关配置

    linux网络相关配置文件 linux系统一般来说分为两大类: 第一类:Debian系列:Debian.Ubuntu等: 第一类:RedHat系列:Redhat.Centos.Fedora等: lin ...

  8. Linux日常运维管理技巧(一)监控系统状态、监控网卡流量、监控IO性能、查看系统进程、查看网络状态、Linux下抓包tcpdump、Linux网络相关、DNS配置

    目录 监控系统状态 监控网卡流量 监控IO性能 查看系统进程 查看网络状态 Linux下抓包 Linux网络相关 监控系统状态 w/uptime查看系统负载 [root@zyshanlinux-01 ...

  9. 小白初解Linux基础相关

    本人对计算机及Linux等相关知识小白一个为避免自己时间过长导致忘记所以写下此博客 下面写的是我对自己随堂笔记的一些解析 如有某方面说的不透彻或错误 我会慢慢改进望 大牛们见谅. 在解析Linux基础 ...

最新文章

  1. 鸿蒙开发者自学,【5月21日鸿蒙公开课】自学鸿蒙 当代大学生的进阶之路
  2. Android学习笔记:对Android应用进行单元测试
  3. reserve和resize - 力为的技术博客 - C++博客
  4. [转载] 启用和禁用 Reporting Services 的客户端打印和导出文件格式
  5. list选取多个元素 python_【幼儿园级】0基础学python一本通(上)——AI未来系列1...
  6. idea 父文件_万事开头难!最新MyBatis程序配置教程(IDEA版)
  7. es6生成器_ES6生成器
  8. .NET 内存管理与垃圾回收:实现IDisposable接口和析构函数
  9. jsp测试mysql_求一段jsp连接mysql的测试程序
  10. python 美化ppt_python操作PPT------PPT内容样式调整
  11. 微信公共平台开发(一):服务器配置
  12. Web前端业界氛围极好的群——鬼懿IT
  13. 那些让我印象深刻的bug--05
  14. android中使用hbuilder混合开发中提示未添加plugintest模块 请参考283
  15. html如何添加时钟效果,HTML5实现时钟效果
  16. android ftp同步程序,ftp同步 安卓,安卓手机ftp上传下载文件功能同步视频照片
  17. 华为hcie认证体系华为华为hcie认证价值NSR不间断路由思科华为网工常备知识点解析ie-lab
  18. 新手怎样自己DIY一套音质不错的音响?
  19. 信号实验:随机信号的产生和分析
  20. 未来教育计算机一本通,未来教育·全国计算机等级考试一本通:一级B(2013年考试专用)...

热门文章

  1. 【有利可图网】小白设计师该如何创作电商广告Banner图?内附精华教程
  2. MIT诺奖大牛2万字雄文:记忆的本质
  3. SLAM专题(6)-- 非线性优化
  4. 数字化助力生产制造管理:专项生产管理系统
  5. 寻路机器人单片机程序示例_单片机典型案例开发(四)
  6. 华为云数据库mysql云灾备方案_华为云MySQL云灾备解决方案,为企业数据提供全方位的异地保护...
  7. 3天25顿的潮汕美食记
  8. 服务器缓存(CDN)
  9. python全栈开发实战pdf老男孩_Python教程:2017年老男孩最新全栈python第2期视频教程全套完整版...
  10. 一场世界杯比赛的时间把热情从38.5降到36.5