Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2034421
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: LINUX

2008-01-31 23:23:02

前不久Linus了Linux-2.6.24,这个版本中加入了支持TCP协议的通用功能,它通过将多个TCP数据整合在一个skb结构中,并在稍后的某个时刻作为一个大的数据包交付给上层的网络协议栈,以减少上层协议栈处理skb的开销,提高Linux系统接收TCP数据包的能力。

当然,这一切都是需要网卡驱动程序支持的。不过,对于Linux社区来说,并不是什么问题,相信很快就会有大量的网卡驱动程序支持LRO。

要想理解LRO的工作原理,理解sk_buff结构体是必须的,这方面可以参考写的,它详细介绍了sk_buff结构体中每个成员的作用。有一点需要注意,sk_buff最多可以有三种方式保存数据:
  1. 数据被保存在skb->data指向的由kmalloc申请的内存缓冲区中,这个数据区通常被称为线性数据区,数据区的长度可由函数skb_headlen给出。
  2. 数据被保存在紧随于skb线性数据区尾部的共享结构体skb_shared_info中的成员frags所表示的内存页面中,skb_frag_t的数目由nr_frags给出,skb_frags_t中有数据在内存页面中的偏移量和数据区的大小。注意,因为这里直接引用的是内存页面,所以可以在它的基础上实现零拷贝的高效网络。
  3. 数据被保存于skb_shared_info中的成员frag_list所表示的skb分片队列中。
以上数据区在读取的时候是从上往下依此进行的(可以参考函数skb_copy_datagram_iovec的实现),这也就要求保存数据的时候也要按序。

如果理解了以上部分,那么如何将多个skb数据包合并于一个数据包中就比较容易了。lro_receive_skb就是将一个skb表示的数据放在第3种缓冲区中,lro_receive_frags是为那些本身就把数据直接放在内存页面的网卡驱动设计的,它将数据放在第2种缓冲区中。

合并了N个skb的skb,能够一次性通过网络协议栈,而不是N次,对CPU负担的减轻也是很显然的。
阅读(8146) | 评论(8) | 转发(2) |
0

上一篇:

下一篇:回家过年

给主人留下些什么吧!~~

chinaunix网友2008-08-14 14:21:51

博主你好,很高兴你能在百忙之中回答我的问题,而且说的这么详细 假如我现在有这样一个需求,我在 IP_FORWARD 中注册一个钩子,利用 conntrack 的特性这里得到的数据包应该已经是 defrag 过的,我要把数据包 IP 层后的 payload 部分扩展到 65535bytes,然后再放走(后面填充自己的内容,校验和自己重新计算),再利用 conntrack 的功能自动分片。 在 2.6.23 内核中,我可以利用 skb_copy_expand 做出一个符合我大小的数据包,之后填充正确的结构,kfree_skb 掉之前的,返回系统正确的 skb 指针。 在 2.6.24 以后的内容中该如何作呢?虽然可以用 skb_put 来增加尾部数据空间,但 tailroom 不够的话怎么办啊?

xiaosuo2008-08-14 08:59:07

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3db05fea51cdb162cfa8f69e9cfb9e228919d2a9 从上面的记录来看,是Herbert Xu做出的更改,原因是没人用了。 至于你的问题,给你看一段注释(include/linux/netfilter/x_tables.h): /* Returns verdict. Argument order changed since 2.6.9, as this must now handle non-linear skbs, using skb_copy_bits and skb_ip_make_writable. */ unsigned int (*target)(struct sk_buff *skb,

chinaunix网友2008-08-14 05:34:19

借这个改变也问个问题,请博主解答一下 2.6.24 改变了 netfilter 的 target 部分,调用时由 **pskb 变成了 *skb,这样的话如果想在 netfilter module 中 clone 一个包作处理,然后返回给系统自己制作的包,是不是就无法实现了? 2.6.24 为什么要作这样的改变决定呢?我查了很多资料都没找到答案