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`; doecho "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/

转载于:https://www.cnblogs.com/jhcelue/p/6754030.html

不错的网络协议栈測试工具 — Packetdrill相关推荐

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

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

  2. packetdrill 深入理解内核网络协议栈的工具集

    对内核网络协议栈的学习,验证和深度研究 packetdrill 将大事化小 深入packetdrill packetdrill 模拟包和验证包 packetdrill 设计 独特的packetdril ...

  3. linux内核网络协议栈--监控和调优:接收数据(十五)

    译者序 本文翻译自 2016 年的一篇英文博客 Monitoring and Tuning the Linux Networking Stack: Receiving Data.如果能看懂英文,建议阅 ...

  4. TCP/IP网络协议栈面试经典题目

    目录 面试官:看你简历说精通TCP和IP,那我们来讨论下网络模型和TCP.IP协议,讲下你的理解先 面试官:看你画的图,TCP有自己的首部结构,这都有哪些字段,最好说说它们的作用 面试官:那TCP和U ...

  5. 监视和调整Linux网络协议栈:发送数据

    目录 有关监视和调整Linux网络堆栈的一般建议 总览 详细外观 协议族注册 通过套接字发送网络数据 sock_sendmsg,__sock_sendmsg和__sock_sendmsg_nosec ...

  6. 什么叫linux网络协议栈,我们为什么使用Linux内核的TCP协议栈

    最近的一篇文章提出了"我们为什么使用Linux内核的TCP协议栈"的问题,并在Hacker News引发了非常有意思的讨论. 在CloudFlare的时候我也曾思考这个问题.我的经 ...

  7. Linux 虚拟化网络技术 — 虚拟网络协议栈

    目录 文章目录 目录 前言 Neutron L3 agent 概述 L3 agent的配置 虚拟路由器实现原理 总结 前言 本文通过 OpenStack Neutron L3 Agent 实现的 Li ...

  8. linux 内核网络协议栈

    Linux网络协议栈之数据包处理过程  1前言 本来是想翻译<The journey of a packet through the linux 2.4 network stack>这篇文 ...

  9. linux内核网络协议栈--linux bridge(十九)

    1 . 前言 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码. 2. 网桥的原理 2.1 桥接的概念 简单来说,桥接就是把一台机器上的若干个网络接口" ...

最新文章

  1. 仿WINDWS无限级Ajax菜单树升级1.2版(菜单名支持非法字符)
  2. Java程序员新手老手都离不开八大开发工具
  3. Win10显示此应用无法在你的电脑上运行 此应用无法在你的电脑上运行处理办法
  4. YIi2 對接 支付寶Alipay支付接口
  5. pyinstaller库的使用——将Python语言脚本打包成可执行文件的第三方库
  6. 单片机如何产生PWM信号
  7. c/c++成长之捷径
  8. jsp MySQL购物车价格总和_计算购物车金额总和( jquery )
  9. ENVI5.3.1高分2号影像预处理流程
  10. matlab 求信号频率响应,频率响应 - MATLAB Simulink - MathWorks 中国
  11. 年轻人先实现社会价值,再去实现人生价值
  12. ysdk应用宝渠道接入问题记录
  13. 过河问题(贪心算法)(python)
  14. FusionCharts参数中文说明
  15. 推荐一部美国电影---‘’决胜21点‘’O(∩_∩)O
  16. 微控制器MCU片上资源分类总结
  17. SwiftUI之深入解析如何绘制徽章视图的路径和形状
  18. 基于牛顿方法在直流微电网潮流研究(Matlab代码实现)
  19. 99美元的Mira Prism,将iPhone变成一个迷你“HoloLens”
  20. 计算机32位怎么转换为64位,CAD2014 32位怎么转换成64位

热门文章

  1. ActiveMQ从入门到精通(二)
  2. Python OpenCV学习笔记之:灰度图像的直方图计算
  3. Haproxy相关概念解析
  4. DNS配置,主从,子域,转发
  5. 《XNA游戏开发》简介
  6. linux中date命令设置系统时间的方法-转
  7. 蓝桥杯 ALGO-28 算法训练 星际交流
  8. [Java] 蓝桥杯BASIC-21 基础练习 Sine之舞
  9. [Java] 蓝桥杯 BASIC-10 基础练习 十进制转十六进制
  10. pythonwindow程序窗体操作_python操作Windows窗口程序