Linux网络协议栈--ip_append_data函数分析

开场白:

要分析这个函数原因有两个:

一个是前几天要写《Linux网络协议栈--UDP》结果卡在这个函数这了。

另外一个就是这个函数又是UDP报文必经之路,而且对其理解对于套接口中发送队列的理解非常有帮助,所以认真去学习了下。


文章定位:

(1)尽可能撇开一些不需要的细节,重点介绍流程

(2)说明发送队列是如何组织起来的

(3)书本肯定都比我说的好,要真的看明白,还是需要看书,这里能做的就是将其结构重新组织,并且将不同的书的内容重新揉合,帮忙看的更快一些


参考书籍:

(1)《Understand Linux Kernel Internel》

(2)《Linux内核源码剖析-TCP/IP实现》

(3)linux内核源码--我使用的版本是3.2.4

注:虽然这写书都有电子版的,不过我还是希望大家能够支持正版。作者写这些书不容易。



一、cork

一开始先来说一个单词,以下内容为个人理解,仅供参考,如果有错恳请指正。

UDP相关的数据经常会存储在一个名为cork的变量中,第一次看的时候非常的让人感觉疑惑。

cork在英文中是软木塞的意思,那软木塞又和UDP有什么关系?

可以将UDP底部到IP的部分看成一个漏斗,如果从UDP下来的数据都是小数据(比如都只有几十个字节),那无疑会加重下层处理数据的负担,而且会让网络充斥各种小报文。所以cork给人的感觉就是将这个漏斗底部给堵住,等在一定时候再拔掉这个塞子,这样就可以把各种小数据汇集成一个大数据了。

不过需要注意的是,cork的标志是需要应用层来设置,所以这个塞塞子和拔塞子的动作都掌握在应用层手中,所以可以掐头去尾的看了。


二、ip_append_data在做什么

就是将上层下来的数据进行整形,如果是大数据包进行切割,变成多个小于或等于MTU的SKB。如果是小数据包,并且开启了聚合,就会将若干个数据包整合。

说的简单,但是在实现的时候做起来就复杂了,因为函数中考虑到了

(1)如何填充队列中上一个skb中未填充的部分?

(2)如何将队列中上一个skb中不能进行对齐的数据部分移动到新的skb中

(3)如何什么时候分配skb,而且skb的大小是多少

(4)如何在分配skb的时候为下层预留足够的空间

(5)需要将数据重用户空间拷贝到内核空间,那怎么拷贝效率才高

(6)如何才能减少内存的拷贝消耗

(7)……

因为考虑的事情太多,所以做起来就比较繁琐了。


三、参数

先介绍下参数,虽然参数多,但是关键参数却很少

注:该参数是3.2.4中的,可能与其他版本的不一样,不过不影响整体介绍

struct *sk : 

struct flowi4 *fl4 : 

struct sk_buff_head *queue : 

struct inet_cork *cork : 输出数据块的地址。

int getfrag() : 将数据复制到SKB中,其为一个函数指针,会有不同的选择,在udp_sendmsg最开始的时候会进行初始化。其可能的函数如图1-1所示(见《Linux内核源码剖析-TCP/IP实现》表11-12

图 1-1

void *from : 

int length : 数据长度

int transhdrlen : 传输层首部长度,同时也是标志是否为第一个fragment的标志

struct ipcm_cookie *ipc :

struct rtable **rpt : 

unsigned int flags : 处理标志,如图1-2所示(见《Linux内核源码剖析-TCP/IP实现》表23-1),在ip_append_data中只用到其中两个MSG_PROBE和MSG_MORE。其余暂时不关心


图1-2


三、几个标志

ip_append_data代码非常大,主要是它存在多个分支,不过令人高兴的是,它的分支的标志都比较清晰,所以看到如下标志就需要多注意了: 

1、copy

队列中最后一个skb剩余的空间,存在3种情况,如图3-1所示(《Understand Linux K

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值