[百度分享]以太网卡TSO技术浅析

baiduforum 2010-05-20 10:03:09
加精
TSO(TCP Segment Offload)技术是一种利用网卡的少量处理能力,降低CPU发送数据包负载的技术,需要网卡硬件及驱动的支持。

在不支持TSO的网卡上,TCP层向IP层发送数据会考虑mss,使得TCP向下发送的数据可以包含在一个IP分组中而不会造成分片, mss是在TCP初始建立连接时由网卡MTU确定并和对端协商的,所以在一个MTU=1500的网卡上,TCP向下发送的数据不会大于min(mss_local, mss_remote)-ip头-tcp头。

而当网卡支持TSO时,TCP层会逐渐增大mss(总是整数倍数增加),当TCP层向下发送大块数据时,仅仅计算TCP头,网卡接到到了IP层传下的大数 据包后自己重新分成若干个IP数据包,添加IP头,复制TCP头并且重新计算校验和等相关数据,这样就把一部分CPU相关的处理工作转移到由网卡来处理。 内核TCP/IP协议栈也必须考虑下发包数和实际包数不一致的情况,例如处理拥塞控制算法时必须做一些特殊的处理等等。

注:参考内核版本为2.6.9;
1 TCP/IP协议栈对TSO的支持
1.1 逐渐增大mss(offload)

在不支持TSO的网卡 上,TCP层向IP层发送数据会考虑mss,使得TCP向下发送的数据可以包含在一个IP分组中而不会造成分片, mss是在TCP初始建立连接时根据网卡MTU确定并和对端协商的,所以在一个MTU=1500的网卡上,TCP向下发送的数据不会大于min (mss_local, mss_remote)-ip头-tcp头。

在应用层向传输层传输数据时,对于TCP协议,最终会调用如下函数:

文件 net/ipv4/tcp.c

int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size)

该函数会调用如下函数

文件 net/ipv4/tcp.c

unsigned int tcp_current_mss(struct sock *sk, int large)

获得当前的mss值,如果网卡不支持TSO,则该函数返回的mss值将和原来相同,否则如果当前不是一个MSG_OOB类型的消息,内核将尝试增大 mss值,注意: 最大的mss值不会大于65535-ip头-tcp。 内核根据/proc变量tcp_tso_win_divisor决定增大后的mss占当前拥塞控制窗口的比率(snd_cwnd)。最终的效果是:增大的mss总是原有mss值的整数倍,但是不会超过snd_cwnd/tcp_tso_win_divisor。
1.2 对skb计数的修正

在启用TSO时,由于TCP层向下发送一个skb, 有可能最终会发出n个IP数据包,即一个skb和一个IP packet可能不是一一对应的关系,而我们都知道,TCP拥塞控制算法需要精确跟踪当前发送、接收以及拥塞控制窗口来决定最终发送多少数据包,TSO的 存在给计算带来了一定的复杂性,所以内核在每一个skb的末尾维护了额外的数据(struct skb_shared_info,通过skb_shinfo取出),表示该skb包含多少个packet。内核提供下列函数操作这块数据:

tcp_skb_pcount

tcp_skb_mss

tcp_inc_pcount

tcp_inc_pcount_explicit

tcp_dec_pcount_explicit

tcp_dec_pcount

tcp_dec_pcount_approx

tcp_get_pcount

tcp_set_pcount

tcp_packets_out_inc

tcp_packets_out_dec

tcp_packets_in_flight

最终,当TCP协议栈在调用tcp_snd_test决定是否可以发送当前skb时,会调用上述函数修正计算结果。
2 网卡驱动层对TSO的支持

如果skb_shinfo(skb)->tso_size不为0,则表明网卡需要对这样的skb作特殊的处理(而只有当网卡驱动初始化时声明自己支持TSO,才可能出现这样的skb),以e1000网卡驱动为例:

函数e1000_tso,在文件drivers/net/e1000/e1000_main.c,被e1000_xmit_frame (即hard_start_xmit服务函数)调用

if(skb_shinfo(skb)->tso_size) {



// 计算头部偏移

ipcss = skb->nh.raw - skb->data;

ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;

tucss = skb->h.raw - skb->data;

tucso = (void *)&(skb->h.th->check) - (void *)skb->data;

tucse = 0;

……

//把头部偏移放入context,最终写入寄存器

context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);

context_desc->lower_setup.ip_fields.ipcss = ipcss;

context_desc->lower_setup.ip_fields.ipcso = ipcso;

context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse);

context_desc->upper_setup.tcp_fields.tucss = tucss;

context_desc->upper_setup.tcp_fields.tucso = tucso;

context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);

context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss);

context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;

context_desc->cmd_and_length = cpu_to_le32(cmd_length);

……

}

……

//设置TSO标志

if (likely(tso))

tx_flags |= E1000_TX_FLAGS_TSO;

……

//发送“大”的skb数据

e1000_tx_queue(adapter,

e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),

tx_flags);

即驱动需要告诉网卡硬件(设置E1000_TX_FLAGS_TSO标志),让网卡对这个skb重新分块,对每一个分块计算TCP头和IP头校验和,为此需要告诉网卡对应字段的偏移。
3 TSO对基于 RAW_SOCKET的抓包工具的影响

当发送数据包时,skb经过如下路径发向网卡驱动

net_tx_action->dev_queue_xmit()-> 驱动的hard_start_xmit服务函数

在函数dev_queue_xmit()中,如果有抓包工具开启了RAW_SOCKET,则该函数会在调用hard_start_xmit之前调用 dev_queue_xmit_nit clone一份skb交给抓包工具。如果skb是一个TSO-enable的特殊skb,抓包工具将会看到这个长度大于MTU的“特殊”skb。 而且,由于TCP、IP的校验和与长度字段将由网卡重新计算,一些版本的内核有可能为了优化而不去计算填写这些数值,所以除了会出现大数据包、校验和与长 度错误的现象。

例如:使用tcpdump在支持TSO的网卡抓取外出数据包可能会出现如下3种错误,其中第一种一般出现在使用e1000网卡驱动的2.6.9内核上,第2种出现在使用bnx2网卡驱动的2.6.9内核上,第3种出现在2.6.23+版本后的内核上:

* ip bad len = 0

000001 IP 192.168.13.1.61941 > 192.168.13.223.32879: . ack 4345 win 32768 <nop,nop,timestamp 945581949 19361257>

000145 IP bad-len 0

000229 IP 192.168.13.1.61941 > 192.168.13.223.32879: . ack 8689 win 32768 <nop,nop,timestamp 945581949 19361257>

000011 IP bad-len 0

* bad csum

16:29:32.561407 IP (tos 0x60, ttl 48, id 14116, offset 0, flags [DF], length:

80) 69.42.67.34.2612 > 81.13.94.6.1234: . [bad cksum 0 (->2610)!] ack 93407

win 9821

<nop,nop,timestamp 1046528205 5497679,nop,nop,sack sack 3

{122367:127103}{128551:129572}{122367:127103} >

* “包合并”

在MTU=1500的网卡上抓包,出现了比1500还大的IP包

21:58:36.691026 IP (tos 0x0, ttl 64, id 38181, offset 0, flags [DF], proto 6, length: 52) 10.13.100.34.45043 > 10.1

3.100.102.34476: . [tcp sum ok] 1:1(0) ack 482281 win 16664 <nop,nop,timestamp 2304130362 99107965>

21:58:36.691029 IP (tos 0x0, ttl 64, id 10688, offset 0, flags [DF], proto 6, length: 23220) 10.13.100.102.34476 >

10.13.100.34.45043: . 525769:548937(23168) ack 1 win 1448 <nop,nop,timestamp 99107965 2304130362>

21:58:36.691031 IP (tos 0x0, ttl 64, id 38183, offset 0, flags [DF], proto 6, length: 52) 10.13.100.34.45043 > 10.1

3.100.102.34476: . [tcp sum ok] 1:1(0) ack 485177 win 16664 <nop,nop,timestamp 2304130362 99107965>

21:58:36.691033 IP (tos 0x0, ttl 64, id 38185, offset 0, flags [DF], proto 6, length: 52) 10.13.100.34.45043 > 10.1

3.100.102.34476: . [tcp sum ok] 1:1(0) ack 488073 win 16664 <nop,nop,timestamp 2304130362 99107965>

根据上面的分析,可以知道这些现象本质都是TSO造成的假象,即TCPDUMP抓取的*外出*数据包并不能真实反应链路上实际的数据帧, 解决办法有两种:

1. 关闭网卡的TSO选项

[xxx]#ethtool -K eth0 tso off

2. 使用其他的旁路链路层的抓包工具
...全文
4698 116 打赏 收藏 转发到动态 举报
写回复
用AI写文章
116 条回复
切换为时间正序
请发表友善的回复…
发表回复
hanhannina 2011-12-31
  • 打赏
  • 举报
回复
学习了,谢谢。可不可以这样理解,如果开了TSO后,TCP层下发数据包不考虑MSS值,而且IP层协议也不会主动对超长IP报文进行分片,而是在最终发送到网卡后在硬件中进行IP分片。

请问支持TSO的网卡会不会在收包的时候主动对分片报文重组呢?其实分片并不复杂,重组才是最耗时的
ppsas513 2010-12-23
  • 打赏
  • 举报
回复
这个支持TSO技术的网卡到底有多少处理能力?
如果达到了处理上限,是否应该反馈给tcp协议栈知晓,重新按照mss的大小来发送数据包

zgycctv 2010-12-01
  • 打赏
  • 举报
回复
好。不错。顶
qs463503059 2010-11-29
  • 打赏
  • 举报
回复
说实话,看不懂,太深奥了
mr_lu2010 2010-06-20
  • 打赏
  • 举报
回复
不错,非常好。
勇往直前! 2010-06-17
  • 打赏
  • 举报
回复
感觉比较专业,拷贝放桌面慢慢看
navy_you 2010-06-04
  • 打赏
  • 举报
回复
【10年GIS之实用推荐篇】

从最开始不懂什么是GIS到摸索着用Mapinfo和ArcGis,再到用一些杂七杂八的国产GIS产品。感觉各种产品各有利弊,问题是看应用是否合适。做过的项目无数(夸张了点,呵呵),总结下来其实90%的GIS项目其实根本不需要去用那些价格昂贵、开发繁琐的产品;绝大部分项目都是浪费了资金和人力资源。最近在网上偶遇一简易版WEBGIS产品,看它介绍还不错,配置开发简单,关键是绝大多数通用的GIS功能接口都给我做好现成的了,这个我喜欢,省了最繁琐的重复劳动。而且看它案例不少,更不乏中兴这样的重量级客户,于是就拿来用了一下。感觉用的相当不错。适合有快速搭建webgis系统需求的项目,接口较为完善。很多模块可以单独装载。在此推荐一下。

为了方便了解,按照论坛发帖的规矩,介绍如下:

产品名称】:SitemapIms
【GIS底层实现技术】:DotNet
【结构】:WEB-GIS(有单机数据编辑工具)
【特点】:封装得比较好,现成应用接口(url);XML传输;现成的Ajax客户端模板
【价格】:相当低廉(一般应该都是个位数)
【产品可信赖度】:案例不少,包括中兴通讯等大客户(我就是看着这个才放心)。
【网址】:http://www.fobst.com
有兴趣的朋友可以去网站上下载试用版看看。
szp1120 2010-06-04
  • 打赏
  • 举报
回复
过路的。帮顶。。。。。。。。。。。。
yu103 2010-05-28
  • 打赏
  • 举报
回复
good
lurenjia321 2010-05-27
  • 打赏
  • 举报
回复
see see
qewei87 2010-05-26
  • 打赏
  • 举报
回复
我顶!!!!!
shihunjiangjie 2010-05-26
  • 打赏
  • 举报
回复
学习下,多多交流
liren2 2010-05-26
  • 打赏
  • 举报
回复
精华...
qihuanfengyun 2010-05-26
  • 打赏
  • 举报
回复
[Quote=引用 45 楼 pottichu 的回复:]

引用 44 楼 steptodream 的回复:

引用 43 楼 pottichu 的回复:
我是进来拜 败毒勋章的。。

那个baidu勋章是什么东西啊

估计是 csdn 和 baidu 搞什么合作。。
而且这文章也不知道是哪个神仙推荐的。。。
[/Quote]
我也膜拜一下 百毒勋章...
ltsd1 2010-05-26
  • 打赏
  • 举报
回复
看不懂
red-fly 2010-05-26
  • 打赏
  • 举报
回复
感谢楼主的贡献啊,学习
Wenxy1 2010-05-26
  • 打赏
  • 举报
回复
呵呵,支持下。
chistopher 2010-05-26
  • 打赏
  • 举报
回复
学习了
嘻嘻嘻_ 2010-05-25
  • 打赏
  • 举报
回复
这个应该是移动通讯协议里面的吧,这个真的不是很好理解的,感觉挺烦的
wwt870826 2010-05-25
  • 打赏
  • 举报
回复
what is the entire name of abreviation TSO
加载更多回复(89)

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧