免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1722 | 回复: 9
打印 上一主题 下一主题

[网络子系统] 关于ip_append_data函数和scatter-gather IO的问题 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-09-11 23:40 |只看该作者 |倒序浏览
本帖最后由 jiufei19 于 2016-09-11 23:52 编辑

在阅读《Understanding Linux Network Internals》一书时,对其中第21章的关于SG方式的描述有点疑问,希望能得到解答,谢谢!

根据该书的讲解,大体可以理解SG就是利用skb_shinfo(skb),也就是skb->end指针处开始的位置中的字段来记录那些在page中的碎片数据,然后网络硬件支持SG,则就不用软件来将这些page中的数据拷贝到skb的主buffer中了,那么如果支持SG模式,则所分配的一个skb的skb->len就将是主buffer中数据的长度加上在page中的所有碎片数据的长度之和,这个概念我能基本理解,但是我不太清楚的地方是,既然L4层发来的数据都已经在page中了,那么在申请主buffer时,主buffer中的数据长度到底多长?换句话讲,哪些数据一定在主buffer中,哪些在page中,这个问题把我搞晕了,因为该书没有对这一点进行阐述。


捕获.PNG (84.13 KB, 下载次数: 66)

捕获.PNG

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
2 [报告]
发表于 2016-09-11 23:55 |只看该作者
补充下,我将原书中第21章的一张图附上,其中用红色圆圈包围的部分就是我的疑问,这部分数据来自哪里?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
3 [报告]
发表于 2016-09-11 23:55 |只看该作者
本帖最后由 jiufei19 于 2016-09-11 23:57 编辑

补充下,我将原书中第21章的一张图附上,其中用红色圆圈包围的部分就是我的疑问,既然udp_sendmsg发来的数据都在page里面,那么图中这部分数据来自哪里?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
4 [报告]
发表于 2016-09-12 11:28 |只看该作者
自己顶下!
原书中第21章有如下两句:

1、When Scatter/Gather I/O is in use, the memory area to which skb->data points is used only the first time. The following chunks of data are copied into pages of memory allocated specifically for this purpose.

2、Figure 21-5(a) shows memory use after the first call and Figure 21-5(b) shows it after the second call, when Scatter/Gather I/O is enabled

第1句是说在SG启用的情况下,还是会有第1次分配skb的过程,之后不再分配新的skb了,数据就呆在pages中即可,这里语焉不详,我搞不懂具体咋个做到的,我是希望知道从sendto-->udp_sendmsg-->ip_append_data这个调用序列中,SG是咋个介入的,并表现为该书所说的方式?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
5 [报告]
发表于 2016-09-13 18:56 |只看该作者
参考一下ip_append_data的实现?http://lxr.free-electrons.com/source/net/ipv4/ip_output.c#L861

1066行就是填充frag/page的部分,这个过程中skb->len不断的调整(变大)。
红色部分,可能是1034行copy进去的。

其中的getfrag是ip_generic_getfrag,它来完成从msg->iovec到page的拷贝。
http://lxr.free-electrons.com/source/net/ipv4/ip_output.c#L781
http://lxr.free-electrons.com/source/net/ipv4/udp.c#L907

除非是开启zerocpoy,否则用户态的buffer拷贝到skb的data或page里,需要经过copy的过程。
skb的page是按需分配的,它的分配在http://lxr.free-electrons.com/source/net/ipv4/ip_output.c#L1070

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
6 [报告]
发表于 2016-09-16 20:24 |只看该作者
本帖最后由 jiufei19 于 2016-09-16 20:27 编辑

回复 5# nswcfd

感谢nswcfd,虽然你给我的答案不是我想要的,对于如何filling page,这个我能看懂。我的问题是说在SG模式下,那个skb->data中如何做到被填充部分数据后,其余数据全在page中存放。我的理解是似乎仅首次分配skb时,udphdr这个长度的空间可以由skb->data来指向,其他余下的所有应用层发来的数据都应在page中存在了

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
7 [报告]
发表于 2016-09-18 11:33 |只看该作者
FIG 25-a是什么样子? 手头暂时没有这本书,方便的话贴一下图。

SG应该是达成楼主所说的那个效果。
不过具体到包含哪些内容在data里,哪些在page里,只能check代码了。

其实如果可以通过调试手段(kgdb或者uml)run一下的话,问题就很容易说清楚了。
或者在driver之前加个hook,查看一下skb内容的构成。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
8 [报告]
发表于 2016-09-18 14:05 |只看该作者
本帖最后由 nswcfd 于 2016-09-18 14:10 编辑

根据 http://lxr.free-electrons.com/source/net/ipv4/ip_output.c#L968
968                         if ((flags & MSG_MORE) &&
969                             !(rt->dst.dev->features&NETIF_F_SG))
970                                 alloclen = mtu;
971                         else
972                                 alloclen = fraglen;

在SG模式下,第一次(并且是唯一的)skb只分配了传进来的length+IP头的长度,然后调用getfrag把传进来的buffer拷贝到skb->data的区域。

后续的ip_append_data调用,不再分配skb(假设不涉及IP分片),直接调用getfrag(必要的时候先分配page),把buffer拷贝到page里。

==========================

用户态传进来的数据都是通过getfrag得到的。
不同的是,在各种情况下,to参数是不一样的,有的是skb->data,有的是page。
对于SG的情况,第一次是skb->data,后续的是shinfo里的page。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
9 [报告]
发表于 2016-09-18 14:14 |只看该作者
PS, append_data貌似只填充7层内容,不填充4层头?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
10 [报告]
发表于 2016-09-23 12:08 |只看该作者
本帖最后由 jiufei19 于 2016-09-23 12:12 编辑

回复 8# nswcfd

   897             if ((flags & MSG_MORE) &&
   898                 !(rt->u.dst.dev->features&NETIF_F_SG))
   899                 alloclen = mtu;
   900             else
   901                 alloclen = datalen + fragheaderlen; ======》对应nswcfd所看的内核版本,该行为alloclen = fraglen,意思都一样哈

从上面代码上看,假定传入的数据length,并且当前是首次分配skb,那么如果支持SG模式,则alloclen的长度就按之前确定好的datalen+fragheaderlen来分配,而不再按mtu这个最大值来分配了,这说明首个skb是不关联内存page数据的。之后就直接通过getfrag对应的数据拷贝函数从length数据源开始拷贝数据到此skb的主buffer区域
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP