不错的网络协议栈測试工具 — Packetdrill
Packetdrill - A network stack testing tool developed by Google.
项目:https://code.google.com/p/packetdrill/
本文:zhangskd @ csdn blog
简单介绍
The packetdrill scripting tool enables quick, precise tests for entire TCP/UDP/IPv4/IPv6 network stacks,
from the system call layer down to the NIC hardware.
截至2013年开源时。Packetdrill已经在Google内部使用了18个月,主要用于下面几个用途:
(1) Regression testing of network stack
"we have a suite of hundreds of packetdrill scripts that are run by all developers on our team before
submitting a patch for review."
对网络协议栈进行回归測试。确保新的功能不会影响网络协议栈的可用性。
总共包括657个test cases。
(2) Test-driven development of network protocols
"we have developed several new features for Linux TCP using packetdrill."
在下面几个TCP新特性的开发中发挥重要作用:
Early Retransmit
Fast Open
Loss Probes
Rewrite of F-RTO
(3) Reproduction of bugs seen in production network traces
"we have used packetdrill to isolate hard-to-reproduce bugs seen in complex real traces."
使用它发现了Linux内核的10个bug。
安装和使用
(1) 安装
首先安装flex和bison。用于构建词法和语法分析器。
然后编译就可以:
cd packetdrill
./configure
make
(2) 使用
./packetdrill test.pkt
test.pkt为按Packetdrill语法编写的測试脚本。
成功:无输出,表示脚本正确。一切都符合预期。
失败:指出脚本的错误地方,以及原因。
语法
The tool supports four types of statements: packets, system calls, shell commands, and Python scripts.
Each statement is timestamped and is executed by the interpreter in real time, verifying that events
proceed as the script expects.
脚本中能够包括四种语句:数据包、系统调用、shell命令、python语句。
每条语句都必须以时间戳开头。指明它的运行时间。
(1) Packets
数据包分为:输入的数据包、输出的数据包。格式类似于tcpdump的,
支持TCP、UDP、ICMP,以及TCP的大部分选项。
输入的数据包(input packets)
对于输入的数据包(<表示输入),packetdrill会构造一个真实的数据包,然后注入协议栈。
< denotes an input packet to construct and inject into the system under test.
Here's an example of a TCP SYN packet, which packetdrill creates and injects into the
network stack under test 100ms after the start of the test:
0.100 < S 0:0(0) win 32792 <mss 1000, nop, nop, sackOK, nop, wscale 6>
输出的数据包(outbound packets)
对于输出的数据包(>表示输出),packetdrill会检查协议栈是不是真的发出了这样一个包。
> denotes an output packet to sniff and verify, to expect the system to send.
Here's an example of an outbound UDP packet expected to be sent immediately after
a prior event(denoted by +0), which packetdrill sniffs and then verifies for matching
specification:
+0 > udp (1472)
(2) System Calls
系统调用的格式类似于strace。
对于每一个系统调用,packetdrill会在指定的时间给予运行,并检查返回值是否和预期的一样。
Here's an example of a bind() system call invocation in packetdrill notation:
+0 bind(3, ..., ...) = 0
In this example, 3 denotes the file descriptor number to pass in, and the = 0 denotes the expected
return value (i.e.., the user expects the system call to succeed).
The ellipsis (...) allows scripts to omit irrelevant details.
(3) Shell Commands
同意在脚本中使用shell命令,用反引號括起来。
+0 `sysctl -q net.ipv4.tcp_timestamps=0`
(4) Python Commands
同意在脚本中使用Python命令,用%{和}%括起来。
Packetdrill allows inline Python code snippets to print information and to make assertions about the
internal state of a TCP socket using the TCP_INFO getsockopt() option.
The following Linux-based example asserts that the sender's congestion window is 10 packets:
+0 %{ assert tcpi_snd_cwnd == 10 }%
(5) 时间戳
每条语句都必须以时间戳开头,指明它的运行时间。或者预期事件的发生时间。
时间戳能够使用多种格式:
Absolute(绝对时间):0.75
Relative(相对时间):+0.2
Wildcard(随意时间):*
Range(绝对时间区间):0.750~0.900
Relative Range(相对时间区间):+0.1~+0.2
Loose(同意误差值):--tolerance_usecs=800
Blocking(堵塞时间区间):0.750...0.900
假设在规定的时间戳。相应的事件并没有发生就会报错,并告知该事件的实际发生时间。
+1.0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 6>
预期在1s以后TCP应该发送一个SYNACK包。
在实际的使用中。一般指定--tolerance_usecs=405000。也就是同意4ms的时间误差。
(6) 完整样例
验证TCP的高速重传功能,fast retransmit说白了就是收到3个反复的ACK或SACK后立即重传一个数据包
(对于FACK来说仅仅要孔>=3个包就可以)。
脚本中server端的协议栈是要观測的对象,相应的是输出的数据包(outbound packet)。
脚本中client相应的是输入的数据包(inbound packet),用于注入协议栈。
完整样例例如以下:
// Establish a connection. 服务端socket函数调用
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0 // client的socket函数调用不用显式指出
// client构造SYN包,注入协议栈
+0 < S 0:0(0) win 32792 <mss 1000, sackOK, nop, nop, nop, wscale 7> // 预期协议栈发送SYNACK包
+0 > S. 0:0(0) ack 1 <...> // client构造ACK包。注入协议栈,完毕三次握手
+.1 < . 1:1(0) ack 1 win 257 // 服务端接受连接
+0 accept(3, ..., ...) = 4 // Send 1 data segment and get an ACK,构造收发包场景
+0 write(4, ..., 1000) = 1000
+0 > P. 1:1001(1000) ack 1
+.1 < . 1:1(0) ack 1001 win 257
+0 %{ print tcpi_snd_cwnd }% // Write 4 data segments
+0 write(4, ..., 4000) = 4000
+0 > P. 1001:5001(4000) ack 1 // Get 3 SACKs。构造高速重传场景
+.1 < . 1:1(0) ack 1001 win 257 <sack 2001:3001, nop, nop>
+0 < . 1:1(0) ack 1001 win 257 <sack 2001:4001, nop, nop>
+0 < . 1:1(0) ack 1001 win 257 <sack 2001:5001, nop, nop> // We've received 3 duplicate ACKs, so we do a fast retransmit.
// 收到3个SACK后。预期协议栈会高速重传
+0 > . 10001:2001(1000) ack 1 // Receiver ACKs all data.
+.1 < . 1:1(0) ack 6001 win 257
实现
Packetdrill是一个用户态应用程序,主要用C语言编写。
使用flex构造词法分析器,使用bison构造语法分析器。
脚本解释器包含一个主线程和一个用于运行堵塞的系统调用的线程。
使用packet socket来验证输出的数据包,使用TUN device来注入输入的数据包。
详细代码可见项目。
測试案例
一些用于測试详细场景的測试案例:
fast_retransmit // 高速重传
early_retransmit // ER补丁測试
blocking // 堵塞的系统调用
fast_recovery // PRR补丁測试
initial_window // 初始cwnd
init_rto // SYNACK包的RTO
close
connect
icmp
inet_diag
ioctl
listen
mss
pmtu_discovery
receiver_rtt
sack
shutdown
undo
run_tests.h为一个測试脚本:
#!/bin/bash
for f in `find . -name "*.pkt" | sort`; do
echo "Running $f ..."
ip tcp_metrics flush all &> /dev/null
../../packetdrill $f
done
注意:Due to TCP metrics caching in recent kernels, a second run of all tests can result in failures.
The script run_tests.sh in this directory uses the iproute tool to flush the TCP metrics cache
before each test.
这些測试脚本在3.11.0-12-generic中都能通过。
偶尔有timing error,是正常现象,可用--tolerance_usecs=405000指定同意的时间误差。
我的体验
測试一个简单的场景:连接建立后,服务端发送10个包。
这时候处于慢启动阶段,cwnd是指数增长的。
按理来说每收到1个ACK,cwnd++;每收到1个delayed ACK,cwnd+=2。终于cwnd应该为20。
但測试结果表明,终于cwnd为12。
进一步分析发现这是受到拥塞窗体有效性验证机制的影响,当发送是受到应用程序的限制(没有新数据可供发送),
而不是受到cwnd的限制时,不同意添加cwnd。
当然。这仅仅是一个小样例,说明Packetdrill有助于网络协议栈的分析。
优缺点
不论什么一个工具都有长处和限制,Packetdrill也不例外。
(1) 长处
属于脚本測试工具,可以高速和方便的測试网络协议栈,自由的构造測试场景。
由于是用脚本測试。所以高速方便,不用大动干戈。
能够在产品机上直接測试,因此測结果是真实的。
场景可重现,測试可自己主动运行。
比較通用,支持IPv4和IPv6,支持多种操作系统。
(2) 缺点
属于黑盒測试工具,尽管它能通过TCP_INFO选项从内核中获取一些信息。可是这些信息毕竟有限。
当预期结果不符时。缺少信息来做进一步推断。
编写測试脚本时。须要对要构造的场景十分了解,知道协议栈是怎样详细处理的(对每一步了如指掌)。
所以,当场景比較复杂时(比方涉及到较多的数据包、往返时延)。编写脚本的难度大大添加了。
另外眼下仅仅支持測试单条连接,不同意同一时候測试多条连接。
Reference
[1] packetdrill: Scriptable Network Stack Testing, from Sockets to Packets
[2] Drilling Network Stacks with packetdrill
不错的网络协议栈測试工具 — Packetdrill的更多相关文章
- 高性能WEB开发(6) - web性能測试工具推荐
WEB性能測试工具主要分为三种.一种是測试页面资源载入速度的,一种是測试页面载入完成后页面呈现.JS操作速度的,另一种是整体上对页面进行评价分析,以下分别对这些工具进行介绍,假设谁有更好的工具也请一起 ...
- 8个超有用的Java測试工具和框架
Java入门 假设你才刚開始接触Java世界,那么要做的第一件事情是,安装JDK--Java Development Kit(Java开发工具包),它自带有Java Runtime Environme ...
- Apache轻量级性能測试工具--ab
Apache轻量级性能測试工具--ab ab早已不是什么新奇玩意,平时工作中会须要一些性能測试.简单的性能測试全然能够由AB来替代,而不须要动用LR这样重量级的工具. 此文简介一下ab的工具使用与结果 ...
- 不错的网络协议栈测试工具 — Packetdrill
Packetdrill - A network stack testing tool developed by Google. 项目:https://code.google.com/p/packetd ...
- 免费APP在线測试工具以及其用法
免费APP漏洞安全检測工具:http://safe.ijiami.cn/ 漏洞分析是爱加密推出免费 APP 漏洞分析平台,服务包含一键对APK 进行签名数据信息採集.内部配置信息採集.市场渠道相关信息 ...
- SQLIO 磁盘測试工具參考
SQLIO 下载地址:id=20163">SQLIO Disk Subsystem Benchmark Tool 默认文件夹:C:\Program Files\SQLIO 以命令行执行 ...
- 【測试工具】一个将Unix时间转换为通用时间的工具
一个将Unix时间转换为通用时间的工具 演示效果: 点击转换之后变为: 源码: function calctime2(){ var time = window.document.getElementB ...
- 开源网络协议栈onps诞生记
小孩没娘,说来话长,一切都要从LwIP说起.大约是06年9月,本人在二姨的坛口发布了一篇小文--<uC/OS-II 平台下的 LwIP 移植笔记>.自此一发不可收拾,开启了一段我与LwIP ...
- 理解 Linux 网络栈(1):Linux 网络协议栈简单总结
本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...
随机推荐
- Tui-x 基础使用
本章以Tui-x3.x仓库里的HelloTuiCpp项目来做具体解说.[ 由于HelloTuiCpp里面演示的全部控件,本文篇幅有限,不能一一说明,所以仅仅能列举两个控件,后面的文章会有针对性地解说其 ...
- error: <class 'xml.parsers.expat.ExpatError'>, syntax error: line 1, column 0: file: /usr/local/lib/python2.7/xmlrpclib.py line: 557
当linux设备上开启sonar6.2时, supervisorctl status报如下错误: error: <class 'xml.parsers.expat.ExpatError'> ...
- Java多线程学习(吐血超具体总结)
林炳文Evankaka原创作品. 转载请注明出处http://blog.csdn.net/evankaka 写在前面的话:此文仅仅能说是java多线程的一个入门.事实上Java里头线程全然能够写一本书 ...
- Android studio如何导出.so库(NDK开发入门)
转自:http://blog.csdn.net/ssy_neo/article/details/51758687 项目中用到了硬件调试,google一下拿到了硬件调试的源码,可惜握草so库根本加载不进 ...
- CC+语言 struct 深层探索——CC + language struct deep exploration
1 struct 的巨大作用 面对一个人的大型C/C++程序时,只看其对struct 的使用情况我们就可以对其编写者的编程经验进行评估.因为一个大型的C/C++程序,势必要涉及一些(甚至 ...
- 创建带Mipmap的osg::Image
我们常用osgDB::readImage或者osg::Image::allocateImage()方式创建Image对象, 跟深一步的带Mipmap的Image怎样创建呢? 偶然在分析osgParti ...
- 数据库:mongodb与关系型数据库相比的优缺点zz (转)
与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问速度:举例来说,在传统的关系型数据库中,一个COUNT类型的操作会锁定数据集,这样可以保证得到“当前”情况下的精确值 ...
- 非阻塞I/O
http://blog.163.com/tyw_andy/blog/static/1167902120099163252164/ 套接口缺省是阻塞的.这一点意味着当发出一个不能立即完成的套接口调用时, ...
- java实现双向循环链表
java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...
- 树形dp hdu-4616-Game
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4616 题目大意: 给一棵树,每个节点有一个礼物值及是否有trick,每来到一个节点必须拿礼物,如果该 ...