Packetdrill的简明使用手册
作者:五山小新新 发布时间:2021-11-05 13:18:52
1. Packetdrill 编译与安装
源码链接 https://github.com/google/packetdrill.git
源码编译 注释netdev.c
/* Set the offload flags to be like a typical ethernet device */
static void set_device_offload_flags(struct local_netdev *netdev)
{
#ifdef linux
// const u32 offload =
// TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_TSO_ECN | TUN_F_UFO;
// if (ioctl(netdev->tun_fd, TUNSETOFFLOAD, offload) != 0)
// die_perror("TUNSETOFFLOAD");
#endif
}
./configure && make
使用方法
./packetdrill test.pkt
test.pkt为按Packetdrill语法编写的测试脚本。
成功:无输出,表示脚本正确,一切都符合预期。
失败:指出脚本的错误地方,以及原因。
2. Packetdrill 执行自带测试用例
开启tcpdump -i any tcp port 8080抓包便于分析
这里测试快速重传,测试环境centos7.2。
简单说明< 表示输入,packetdrill会构造一个真实的数据包。>表示预期协议栈会响应的数据包。(这个包不是由packetdrill构造的,而是由协议栈发出的。)
// Test fast retransmit with 4 packets outstanding, receiver sending SACKs.
// In this variant the receiver supports SACK.
// Establish a connection.
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
//三次握手
+0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+0 > S. 0:0(0) ack 1 <...>
+.1 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
//系统调用,让协议栈发出100个字节
// Send 1 data segment and get an ACK, so cwnd is now 4.
+0 write(4, ..., 1000) = 1000
//预期协议栈会发出psh,ack,实际上发出了ack1
//+0 > P. 1:1001(1000) ack 2
//向协议栈注入 ack
+.1 < . 1:1(0) ack 1001 win 257
// Write 4 data segments.
//系统调用,让协议栈发出4000个字节
+0 write(4, ..., 4000) = 4000
//预期协议栈会发出psh,ack,实际上发出了seq 1001:2001, ack 1;seq 2001:3001, ack 1;seq 3001:4001, ack 1;[P.], seq 4001:5001, ack 1
//+0 > P. 1001:5001(4000) ack 1
// Get 3 SACKs.
//向协议栈连续发出三个ack
+.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.
//预期协议栈会发出一次快速重传 Seq 1001:2001,ack 1
//+0 > . 1001:2001(1000) ack 1
// Receiver ACKs all data.
//向协议栈ack,响应所有报文的ack。
+.1 < . 1:1(0) ack 6001 win 257
4. 将fr-4pkt-sack-linux.pkt 中的修改如下。
+0 > P. 1:1001(1000) ack 2 +0 > P. 1:1001(1000) ack 1
//+0 > P. 1001:5001(4000) ack 1
+0 > . 1001:2001(1000) ack 1
+0 > . 2001:3001(1000) ack 1
+0 > . 3001:4001(1000) ack 1
+0 > P. 4001:5001(1000) ack 1
[注解:如果执行packetdrill自带的用例出错,一般是协议栈发出的包没有达到预期的包,先将预期>那部分干掉,然后再执行测试用例,然后通过抓包分析预期结果。通常是因为三次握手mss 的限制]
执行: ../../../packetdrill fr-4pkt-sack-linux.pkt,无出错。
抓包可以看到一下结果:三次重复ack,则实施快速重传。达到预期效果。
// 自己构造包实现三次重复的ack 1001.
07:57:36.469280 IP 192.0.2.1.36840 > TENCENT64.site.webcache: Flags [.], ack 1001, win 257, options [sack 1 {2001:3001},nop,nop], length 0
07:57:36.469836 IP 192.0.2.1.36840 > TENCENT64.site.webcache: Flags [.], ack 1001, win 257, options [sack 1 {2001:4001},nop,nop], length 0
07:57:36.470349 IP 192.0.2.1.36840 > TENCENT64.site.webcache: Flags [.], ack 1001, win 257, options [sack 1 {2001:5001},nop,nop], length 0
// 协议栈发起快速重传。Seq 1001:2001,ack 1,1000
07:57:36.470376 IP TENCENT64.site.webcache > 192.0.2.1.36840: Flags [.], seq 1001:2001, ack 1, win 229, length 1000
3. Packetdrill 解读自带测试用例说明
这里主要说明packetdrill的基本语法。
脚本中可以包含四种语句:数据包、系统调用、shell命令、python语句。
每条语句都必须以时间戳开头,指明它的执行时间。
Packets
数据包分为:输入的数据包、输出的数据包,格式类似于tcpdump的,
支持TCP、UDP、ICMP,以及TCP的大部分选项。
输入数据包(<表示输入):packetdrill会构造一个真实的数据包,然后注入协议栈。
例子:
0.100 < S 0:0(0) win 32792 <mss 1000, nop, nop, sackOK, nop, wscale 7>
0.250 < [1:1461(1460)] icmp unreachable frag_needed mtu 1200
输出数据包(>表示输出):packetdrill会检查协议栈是不是真的发出了这样一个包。
+0 > udp (1472)
System Calls
系统调用的格式类似于strace。
对于每个系统调用,packetdrill会在指定的时间给予执行,并检查返回值是否和预期的一样。系统调用的主要是应用于场景构造,已经非测试端的数据发送和接收。
常见的系统调用例子:
系统调用
connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) //客户端连接服务器
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 //获取scoketopt
fcntl(3, F_SETFL, O_RDWR) = 0 //Fcntl设置
ioctl(4, SIOCINQ, [1000]) = 0 //Ioctl设置
read(3, ..., 1024) = 785 //读取数据
write(3, ..., 57) = 57 //写入数据
close(3) = 0 //关闭连接
socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 //Tcp socket
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 //设置地址复用
bind(3, ..., ...) = 0 //绑定端口
listen(3, 1) = 0 //监听端口
accept(3, ..., ...) = 4 //接受连接
shell脚本用法
常见用法是用shell脚本设置内核参数或者调用shell命令统计tcp信息。设置
例子:
+0 `sysctl -q net.ipv4.tcp_timestamps=0`
+0 `ss -4 -n state SYN-RECV | grep 192.168.0.1:8080 > /dev/null`
python脚本的用法
常见用法是使用python的assert断言tcp_info的里面的信息,是否符合预期。
例子:
0.310 %{
assert tcpi_reordering == 3
assert tcpi_unacked == 10
assert tcpi_sacked == 6
assert tcpi_ca_state == TCP_CA_Recovery
}%
时间戳
每条语句都必须以时间戳开头,指明它的执行时间,或者预期事件的发生时间。测试case有可能是timing的问题导致测试case无法通过。
时间戳可以使用多种格式:
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的时间误差。
4. Packetdrill 实现基本场景构造测试
场景的场景构造是客户端场景或者是服务器场景。具体包怎么构造,具体看packetdrill的自带的测试用例。
1.服务端场景
构造服务器端场景:数据包输入端是客户端。数据包输出端是系统调用,充当服务端。
// Establish a connection.
0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
0.000 bind(3, ..., ...) = 0
0.000 listen(3, 1) = 0
0.000...0.200 accept(3, ..., ...) = 4
0.100 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
0.100 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 6>
0.200 < . 1:1(0) ack 1 win 257
//服务器端调用系统调用,预期发出2段数据包。
0.300 write(4, ..., 2000) = 2000
//0.300 > P. 1:2001(2000) ack 1
0.300 > . 1:1001(1000) ack 1
0.300 > P. 1001:2001(1000) ack 1
1.客户端场景构造
构造服务器端场景:数据包输入端是服务端。数据包输出端是系统调用,充当客户端。
// Create a socket and set it to non-blocking.
0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
0.000 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
0.000 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
// Establish connection and verify that there was no error.
0.100 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
0.100 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 6>
0.200 < S. 0:0(0) ack 1 win 5792 <mss 1460,sackOK,TS val 700 ecr 100,nop,wscale 7>
0.200 > . 1:1(0) ack 1 <nop,nop,TS val 200 ecr 700>
//客户端调用系统调用,预期发出http请求。
// Send the HTTP request.
0.200 write(3, ..., 57) = 57
0.200 > P. 1:58(57) ack 1 <nop,nop,TS val 200 ecr 700>
0.300 < . 1:1(0) ack 58 win 92 <nop,nop,TS val 800 ecr 200>
来源:https://blog.csdn.net/al_xin/article/details/52216887


猜你喜欢
- 齐毛鸭在使用dedecms时发现,每一个栏目的列表页的title是不能直接优化的。举个例子,某栏目的名字是“文学天地”,但在title中我们
- 十月开始新建了一个英文的网站,网站系统基于MovableType,模板自制。在做好基于页面的优化工作之后,逐步的开始内容建设和推广。主要观察
- Google AdSense 是一种获取收入的快速简便的方法,适合于各种规模的网站发布商。它可以在网站的内容网页上展示相关性较高的 Goog
- 本篇随笔将详细讲解Linux系统的网卡高级命令、IP别名以及Linux下多网卡绑定的知识一、网卡高级命令在之前的一篇随笔里Linux学习之C
- 衣服宽松一些看着更舒服了,广告也是,大一点的广告往往效果更好请记住 AdSense的三种“王牌”广告
- 帝国的叫大气,系统安全稳定,二次开发能力强,但好像不是太适合那种喜欢“大而全”的新手站长使用!PHPCMS,这个吗,现在炒作的也是很热的,有
- 11月4日消息,针对旗下游戏新作《绿色征途》自封国内首款绿色网游惹争议一事,巨人网络今日发表回应称,绿色网游应重视玩家利益。据悉,巨人网络为
- 业界加密 TCP/IP 网络产品的标准是 SSL ,对于 Internet 上普遍使用的超文本传输协议(HTTP)而言,其加密后的协议称为
- 现在我们来看看域名与主机如何影响网站的SEO:每一个网站的域名对应一个IP地址,IP 地址是在网络上分配给每台计算机或网络设备的数字标识。域
- 很多时候我们会发现自己的系统问题越来越多,如果将就使用,那系统运行效率肯定不会很高,甚至还无法正常运行,如果选择重新安装系统,那不但麻烦不说
- 做SEO的一个基本工作就是每天都要关注自己的网站以及竞争对手网站的数据更新,今天我也是毫不例外的打开查询工具,赫然发现PR上升、百度大更新、
- 问题描述安装Qt5.15.0后,在运行测试用例时弹出错误:qt.qpa.plugin: Could not load the Qt plat
- 10月23日消息,国内领先的社交网站51.com宣布,截止2009年10月中旬,该网站用户上传的图片数量已经超过110亿张,相比去年10月份
- 经过这些天的观察,发现大家对SEO技术类文章比较感兴趣,其实可以想象的到来此的大多数是想学到一些技术性的东西。而ZeYa前面没有分析到这一点
- 软件下载下载软件链接链接: https://pan.baidu.com/s/1sfR8qGNEzuzMLq8nr9O-HQ 提取码: 5mk
- 网站空间是我们做站必不可少的一部分,在这次网络整改的风暴中,倒下了一批IDC服务商,很多站长因为受不了国内的政策,更受不了运营商“一刀切”的
- 近日笔者接触到很多企业都声称要招募手机网游开发人员,笔者想或许是这些企业打算在手机网游领域奋力一搏,势必要取得在网游以及网页游戏等领域中失去
- 最新消息,康盛创想(Comsenz)旗下核心产品UCenter Home(简称UCHome)当前应用站点已经超过15万家。UCenter H
- 首先是管理方面的特点,主要有:是否图形方式配置、是否图形方式安装、有没有远程管理能力、可否利用简单网管协议配置和监视。第二是从扩展能力来说,
- 最近正在学习Linux系统的常用操作命令,于是心血来潮,想自己安装一个Linux系统实践一下,在网上找了半天资料,终于在自己的电脑上成功安装