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

[3] https://code.google.com/p/packetdrill/

不错的网络协议栈測试工具 — Packetdrill的更多相关文章

  1. 高性能WEB开发(6) - web性能測试工具推荐

    WEB性能測试工具主要分为三种.一种是測试页面资源载入速度的,一种是測试页面载入完成后页面呈现.JS操作速度的,另一种是整体上对页面进行评价分析,以下分别对这些工具进行介绍,假设谁有更好的工具也请一起 ...

  2. 8个超有用的Java測试工具和框架

    Java入门 假设你才刚開始接触Java世界,那么要做的第一件事情是,安装JDK--Java Development Kit(Java开发工具包),它自带有Java Runtime Environme ...

  3. Apache轻量级性能測试工具--ab

    Apache轻量级性能測试工具--ab ab早已不是什么新奇玩意,平时工作中会须要一些性能測试.简单的性能測试全然能够由AB来替代,而不须要动用LR这样重量级的工具. 此文简介一下ab的工具使用与结果 ...

  4. 不错的网络协议栈测试工具 — Packetdrill

    Packetdrill - A network stack testing tool developed by Google. 项目:https://code.google.com/p/packetd ...

  5. 免费APP在线測试工具以及其用法

    免费APP漏洞安全检測工具:http://safe.ijiami.cn/ 漏洞分析是爱加密推出免费 APP 漏洞分析平台,服务包含一键对APK 进行签名数据信息採集.内部配置信息採集.市场渠道相关信息 ...

  6. SQLIO 磁盘測试工具參考

    SQLIO 下载地址:id=20163">SQLIO Disk Subsystem Benchmark Tool 默认文件夹:C:\Program Files\SQLIO 以命令行执行 ...

  7. 【測试工具】一个将Unix时间转换为通用时间的工具

    一个将Unix时间转换为通用时间的工具 演示效果: 点击转换之后变为: 源码: function calctime2(){ var time = window.document.getElementB ...

  8. 开源网络协议栈onps诞生记

    小孩没娘,说来话长,一切都要从LwIP说起.大约是06年9月,本人在二姨的坛口发布了一篇小文--<uC/OS-II 平台下的 LwIP 移植笔记>.自此一发不可收拾,开启了一段我与LwIP ...

  9. 理解 Linux 网络栈(1):Linux 网络协议栈简单总结

    本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...

随机推荐

  1. Go:Hello World!

    备注 结束了一周紧张的工作,周末像品茶一样玩味一下Go,本文主要记录学习Go的经历. Go是什么? 官方网站:http://golang.org/. 在Windows下安装Go 官方教程:http:/ ...

  2. .NET:负载平衡的主意事项

    允许局域网发现和共享. 设置固定IP. 网站的IP设置为“全部未分配”. 注意:如果停止IIS的话,不会对负载平衡有影响,负载还是会分配停止了的IIS所在在的电脑,只有停止服务器了,负载不会再分配给停 ...

  3. Linux命令执行的屏幕输出内容重定向到日志文件

    摘要: 作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 快速mark一下这个命令细节,免得以后使用又忘记了 大家都知道可以用echo来输出内容到 ...

  4. Eclipse经常使用的快捷键

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1aHVhbmNoYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  5. Tensorflow 之 name/variable_scope 变量管理

    name/variable_scope 的作用 充分理解 name / variable_scope TensorFlow 入门笔记 当一个神经网络比较复杂.参数比较多时,就比较需要一个比较好的方式来 ...

  6. ubuntu14.04如何卸载mysql

    1. 删除mysql的数据文件 sudo rm /var/lib/mysql/ -R 2. 删除mqsql的配置文件 sudo rm /etc/mysql/ -R 3. 自动卸载mysql的程序 su ...

  7. easyui messager alert 三秒后自动关闭提示

    $.messager.alert(' ','<font size=\"2\" color=\"#666666\"><strong>数据库 ...

  8. (剑指Offer)面试题4:替换空格

    题目: 请实现一个函数,把字符串中的每个空格替换成“%20”,例如输入“We are happy”,则输出“We%20are%20happy”. 思路: 背景: 在网络编程中,如果URL参数中含有特殊 ...

  9. es5 - array - reverse

    /** * 描述:也就是数组元素反转 * 使用:arr.reverse() */ var a = [1,2,3]; console.log(a.reverse()); /** * 一个经典的问题:如何 ...

  10. pring MVC过滤器-HttpPutFormContentFilter

    在Spring MVC过滤器-HiddenHttpMethodFilter中我们提到,jsp或者说html中的form的method值只能为post或get,我们可以通过HiddenHttpMetho ...