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 "htmlcode">// 自己构造包实现三次重复的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 10003. 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>
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]