千家信息网

linux中Packetdrill如何使用

发表于:2025-02-03 作者:千家信息网编辑
千家信息网最后更新 2025年02月03日,这篇文章主要介绍linux中Packetdrill如何使用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. Packetdrill 编译与安装源码链接 https://git
千家信息网最后更新 2025年02月03日linux中Packetdrill如何使用

这篇文章主要介绍linux中Packetdrill如何使用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

1. Packetdrill 编译与安装

  1. 源码链接 https://github.com/google/packetdrill.git

  2. 源码编译 注释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 执行自带测试用例

  1. 开启tcpdump -i any tcp port 8080抓包便于分析

  2. 这里测试快速重传,测试环境centos7.2。

  3. 简单说明< 表示输入,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 +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 +0 < . 1:1(0) ack 1001 win 257 +0 < . 1:1(0) ack 1001 win 257 // 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 2574. 将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 的限制]

  1. 执行: ../../../packetdrill fr-4pkt-sack-linux.pkt,无出错。

  2. 抓包可以看到一下结果:三次重复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 007: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 007: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,100007: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 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  //获取scoketoptfcntl(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 socketsetsockopt(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 == 3assert tcpi_unacked == 10assert tcpi_sacked == 6assert tcpi_ca_state == TCP_CA_Recovery}%
  • 时间戳

每条语句都必须以时间戳开头,指明它的执行时间,或者预期事件的发生时间。测试case有可能是timing的问题导致测试case无法通过。

时间戳可以使用多种格式:

Absolute(绝对时间):0.75Relative(相对时间):+0.2Wildcard(任意时间):*Range(绝对时间区间):0.750~0.900Relative Range(相对时间区间):+0.1~+0.2Loose(允许误差值):--tolerance_usecs=800Blocking(阻塞时间区间):0.750...0.900

如果在规定的时间戳,对应的事件并没有发生就会报错,并告知该事件的实际发生时间。

+1.0 > S. 0:0(0) ack 1 

预期在1s以后TCP应该发送一个SYNACK包。

在实际的使用中,一般指定-tolerance_usecs=405000,也就是允许4ms的时间误差。

4. Packetdrill 实现基本场景构造测试

场景的场景构造是客户端场景或者是服务器场景。具体包怎么构造,具体看packetdrill的自带的测试用例。

1.服务端场景

构造服务器端场景:数据包输入端是客户端。数据包输出端是系统调用,充当服务端。

// Establish a connection.0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 30.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 00.000 bind(3, ..., ...) = 00.000 listen(3, 1) = 00.000...0.200 accept(3, ..., ...) = 40.100 < S 0:0(0) win 32792 0.100 > S. 0:0(0) ack 1 0.200 < . 1:1(0) ack 1 win 257//服务器端调用系统调用,预期发出2段数据包。0.300 write(4, ..., 2000) = 2000//0.300 > P. 1:2001(2000) ack 10.300 > . 1:1001(1000) ack 10.300 > P. 1001:2001(1000) ack 1

1.客户端场景构造

构造服务器端场景:数据包输入端是服务端。数据包输出端是系统调用,充当客户端。

// Create a socket and set it to non-blocking.0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 30.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) 0.200 < S. 0:0(0) ack 1 win 5792 0.200 > . 1:1(0) ack 1 //客户端调用系统调用,预期发出http请求。// Send the HTTP request.0.200 write(3, ..., 57) = 570.200 > P. 1:58(57) ack 1 0.300 < . 1:1(0) ack 58 win 92 

以上是"linux中Packetdrill如何使用"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

0