对内核网络协议栈的学习,验证和深度研究

  • packetdrill 将大事化小
  • 深入packetdrill
    • packetdrill 模拟包和验证包
    • packetdrill 设计
    • 独特的packetdrill脚本语言
      • 注入包和验证包的脚本
      • 系统调用
      • shell命令
      • python命令
      • 时间戳格式
    • 协议栈协议支持
      • IPv4和IPv6
      • Path MTU
      • ECN
    • 安装和执行
    • 参考文献:

packetdrill 将大事化小

本文是学习和研究内核网络协议栈的一个文笔记录,主要围绕的是一款能帮助大家深入理解内核网络协议栈的工具——packetdrill。packetdrill工具并不能真实的将复杂的内核系统变得更简单,它所做的是让使用者将对象聚焦于一点。换句话说,它构建了一个定量研究某个特定事物的方法。在其他特性保持一致的状态下,不一致的因素成为全局影响因素的导火索。可以说,packetdrill通过另一种形式将大事化小。

深入packetdrill

packetdrill 现支持TCP、UDP、ICMP协议的网络协议栈测试,虽然不多,但已经足够!

QUIC 也可以用packetdrill来测试了。QUIC-mapped-packetdrill

packetdrill 模拟包和验证包

packetdrill是一个测试工具

简洁明了的说,packetdrill工具是通过自定义脚本的形式,探测网络中包传输的实际过程。这里的网络中包传输实际过程指的是真实网络场景下,端在内核协议有变化的前提收到的真实包的信息。而用户自定义脚本的意义在于,使用者管控不同的内核网络协议栈状态的变化,任意注入不同格式的数据包和对应预期接收的数据包信息。

这些是深入理解内核网络协议栈的利器。

使用者可以学习和验证内核网络协议栈的某个模块对网络传输的意义。并且深入研究和优化内核网络协议栈的爱好者可以利用packetdrill测试自己的成果是否accept,和对已有的内核网络协议栈bugfix。

packetdrill不算简单,但掌握绝对有意义。

packetdrill 设计

这里并不是必要内容,跳过也不影响本文的阅读和对packetdrill的使用。 但如果你有时间,我希望你能学习一下这个章节,在这里你能得到packetdrill的一些内幕,这对你使用packetdrill绝对是一笔划算的买卖。

网上对packetdrill引擎描述的图很多,我就不贴了!

  1. 执行模块
    这个模块是对自定义脚本的执行,关联的分析器和解释器会将packetdrill格式的脚本变成计算机可读的机器码。
  2. 本地和远端测试
    本地模块是测试在本机网卡和本机构建的一个虚拟网卡之间的交互。本地不是涉及到网络中链路等因素的影响。
    远端模块是测试在两台物理存在的计算机间的交互。packetdrill能测试真实网络中,内核网络协议栈变化的结果。
  3. 时间模块
    脚本是按照时间顺序进行的,每一行脚本语句都会打上时间戳,以被执行模块的解释器翻译成真实时间下的执行动作。

独特的packetdrill脚本语言

packetdrill脚本语言是使用者自定义内核网络协议栈配置和模拟包测试配置在真实网络场景下结果的工具。

注入包和验证包的脚本

packetdrill单独将注入内核网络协议栈的数据包和内核网络协议栈上传预期接收的验证包用一种唯一的脚本语言格式定义。

注入包:

0.100 < S 0:0(0) win 32792 <mss 1000,nop,nop,sack OK,nop,wscale 6>

< 语句是一条注入数据包

0.100 时间戳,后面详细介绍时间模块定义在脚本语句上的不同时间语义。
S SYN包
0:0(0) 起始序号:结束序号(包长度)
win 32792 通告窗口大小
<mss 1000,nop,nop,sack OK,nop,wscale 6> 选项值

0.100 > S. 0:0(0) ack=1 <mss 1460,nop,nop,sack OK,nop,wscale 8>

> 语句是一条预期收到的验证包

S. SYN+ACK包
0:0(0) 起始序号:结束序号(包长度)
ack=1 ack序号
<mss 1000,nop,nop,sack OK,nop,wscale 8> 选项值

实际收到的包会和预期包比较,当发生不吻合的情况,会打印出两条语句的结果。

packetdrill正是通过结果的不同找到内核网络协议栈配置的影响。

系统调用

Linux/Unix的系统调用是用户态到内核态的接口。packetdrill要设计不同的场景,比如测试发送一张图片时,协议栈配置的影响。这个时候模拟太多的包是费力不讨好的,用系统调用的内核函数可以轻松完成这些复杂且麻烦的脚本设计。

// Initialize connection0 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// three-ways handshack +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>+0 < . 1:1(0) ack 1 win 514+0 accept(3, ..., ...) = 4+0 open("/tmp/testfile", O_RDONLY) = 5+0 sendfile(4, 5, [0], 5) = 5+0 > P. 1:6(5) ack 1

用户可以系统调用函数,自定义初始化TCP连接。默认情况下packetdrill把我们完成了这一步,但用户有需求,亦可以自定义。如上面脚本想改变服务端的默认TCP连接,用自定义的int socket=3文件来传输。

找一个最复杂的
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3

socket 调用socket函数
… packetdrill中不允许用户改变的参数
SOCK_STREAM, IPPROTO_TCP 用户自定义的参数
= 3 预期得到的系统函数socket调用的返回值

shell命令

`sysctl -q net.ipv4.tcp_timestamps=0`

`` 声明该语句是shell命令,packetdrill下的shell可以在测试脚本下配置测试的机器属性,以及用netstat、ss、top等shell命令查看测试下的机器状态。

sysctl -q net.ipv4.tcp_timestamps=0是关闭测试中TCP报文的时间戳选项。

python命令

packetdrill允许脚本中的python块来打印信息和声明断言,这里的断言是由内核getsockopt函数返回的数据结构TCP_INFO支持的,python可以对TCP_INFO的若干信息断言,判断当前该信息实际是否与预期的有出入。

python语句块用%{ }%声明。
+0 %{assert tcpi_snd_cwnd == 10}%

该语句是assert断言TCP连接发送方的拥塞窗口是10个包。

packetdrill还支持打印当前你想要得到的TCP_INFO的信息,用print得到。
+0 %{ print tcpi_snd_wnd }%
终端可查看打印信息。

时间戳格式

packetdrill每一条语句都有时间戳,脚本里的每一个时间戳都会被packetdrill在测试开始后的真实时间对应执行。

所以,时间戳格式的设计决定你测试脚本的顺利执行。

  • 当你使用绝对时间 0.75,表示脚本测试开始后的时间将发生的事件;
  • 当你使用相对时间 +0.2,表示距离上一个事件发生后的相对时间将发生的事件;
  • 当你使用*, 表示该事件将发生在测试后的任一时间
  • 当你使用0.750~0.900,表示在测试开始后的时间范围内将发生的事件;
  • 当你使用+0.1~+0.2,表示距离上一个事件发生后的相对时间范围内将发生的事件;
  • 当你使用–tolerance_usecs=800,表示在这个误差内允许所有事件发生且正常,特殊的是这个条理不是脚本语言内的,而是通过命令行执行的。
  • 当你使用0.750…0.900,表示阻塞将在该时间段一直进行。

协议栈协议支持

学习内核网络协议栈也需要一些特殊的协议支持,方便在该协议启动的状态下,测试配置对该状态下数据包传输的影响。

IPv4和IPv6

内核网络协议栈中有两种不同的网络协议,IPv4和IPv6。packetdrill支持IPv4、IPv6,以及IPv4协议的IPv6套接字。

当需要分别探究配置对IPv4和IPv6的影响,或者仅测试一种网络协议参与的脚本时,packetdrill可以显示化的通过命令行配置。

--ip_version=ipv4 是脚本在IPv4下执行;
--ip_version=ipv6 是脚本在IPv6下执行;
--ip_version=ipv4-mapped-ipv6 是脚本在IPv4协议和IPv6套接字下执行;

Path MTU

Path MTU协议能提高传输效率,发现网络中最大被允许的MTU值。Packetdrill支持PMTU Discovery,意味着端能够显式得到当前状态下被允许的最大MTU值。当前,你可以注入数据包,通过ICMP协议通告端设备,模拟网络协议栈的MTU限制机制。
+.100 < icmp unreachable frag_needed mtu 1000 [1:1500(1500)]

ECN

ECN协议是显示拥塞标识,通过IP报文的两个ECN位判断当前网络的拥塞状态。packetdrill支持ECN协议,代表着开启ECN,端设备能够显式地得知当前网络的拥塞状态。这对研究网络拥塞无疑是一种好的讯息。

安装和执行

packetdrill的安装很简单,可以直接按照google的官方文档来配置。

sudo apt install git gcc make bison flex python
git clone https://github.com/google/packetdrill.git
cd packetdrill/gtests/net/packetdrill
./configure
make
cd …
./packetdrill/run_all.py -S -v -L -l tcp/

详情可见测试工具: packetdrill.

安装和简单测试完成。

如果你想packetdrill本地运行测试脚本,你至少需要./packetdrill foo.pkt。

如果你想远端运行,请在客户端和服务端分别安装packetdrill,然后:
申请根目录权限
客户端需要 ./packetdrill --wire_client --wire_server_ip=XXX --local_ip=XXX --wire_client_dev=XXX foo.pkt
–wire_client 标识客户端,我们做测试的机器,–wire_server_ip是连接的远端服务器,–local_ip是我们的本机IP地址 –wire_client_dev是本机数据包发送出去的网络设备
服务端需要启动packetdrill ./packetdrill --wire_server
–wire_server 服务端标识
记得服务端要先开启,这样客户端本机才能和服务端建立连接,开始测试。
最后,
如果你要添加什么配置,./packetdrill --help将展示出你可以添加配置的选项。

参考文献:

https://github.com/google/packetdrill
https://www.usenix.org/system/files/login/articles/10_cardwell-online.pdf
https://github.com/google/packetdrill/blob/master/syntax.md

先告一段落吧,如果你有兴趣使用packetdrill,联系我,我们一起进步!问题不大!!!

packetdrill 深入理解内核网络协议栈的工具集相关推荐

  1. Linux内核网络协议栈:udp数据包发送(源码解读)

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  2. Linux 内核网络协议栈运行原理

    封装:当应用程序用 TCP 协议传送数据时,数据首先进入内核网络协议栈中,然后逐一通过 TCP/IP 协议族的每层直到被当作一串比特流送入网络.对于每一层而言,对收到的数据都会封装相应的协议首部信息( ...

  3. 深入浅出Linux内核网络协议栈|结构sk_buff|Iptables|Netfilter丨内核源码丨驱动开发丨内核开发丨C/C++Linux服务器开发

    深入浅出Linux内核网络协议栈 视频讲解如下,点击观看: 深入浅出Linux内核网络协议栈|结构sk C/C++Linux服务器开发高级架构师知识点精彩内容包括:C/C++,Linux,Nginx, ...

  4. Linux内核网络协议栈流程及架构

    文章目录 Linux内核网络报文处理流程 Linux内核网络协议栈架构 Linux内核网络报文处理流程 linux网络协议栈是由若干个层组成的,网络数据的处理流程主要是指在协议栈的各个层之间的传递. ...

  5. linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用read, ...

  6. linux 内核网络协议栈

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

  7. linux内核网络协议栈--监控和调优:发送数据(三十)

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

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

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

  9. 浅析linux内核网络协议栈--linux bridge

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

最新文章

  1. OpenCV-Java版学习(3.对视频的基本操作)
  2. 局部反弹行情或一触即发|现货开户|现货投资
  3. Linux内存管理 (4)分配物理页面
  4. Mysql数据库(四)——mysql索引相关知识
  5. Flask 从入门到熟悉(不敢称为精通)
  6. First Steps with TensorFlow代码解析
  7. win java_Win搭建JAVA环境
  8. 使用RawImage播放视频不清晰(改变视频比例后不清晰)的问题解决
  9. 前端代码动态生成 审批流程图、流程图
  10. android go怎么安装,Android studio3.0安装教程-Go语言中文社区
  11. 首都师范大学 计算机学院,首都师范大学信息工程学院
  12. 三星EMMC选型常识
  13. 西行漫记(20):一路向北
  14. android svg路径动画,Svg 路径动画实现旋转进度条
  15. 【历史上的今天】3 月 24 日:苹果推出 Mac OS X;微软前任 CEO 出生;Spring 1.0 正式发布
  16. 【Python+数学】笛卡儿积
  17. python爬虫 打击无良网站弹窗广告
  18. VS2013配置VTK7.1.1
  19. 计算机仿真技术(2)
  20. Android 防止白屏与华为手机欢迎页面全屏时设置背景拉伸图片

热门文章

  1. 浅谈Java8之lambda表达式
  2. STM32/GD32 Bootloader升级APP研究以及编程实现
  3. 腾讯地图标注_怎样在导航地图上标注公司名和位置
  4. 『递推』[AGC043D] Merge Triplets
  5. CAD二次开发:用C#在AutoCAD中插入栅格图像
  6. USB-详解/sys/kernel/debug/usb/devices
  7. Y Combinator Is Boot Camp for Startups
  8. java 月份缩写_关于java:如何将日期字符串解析为Date?
  9. 一分钟带你了解新版系统集成资质——信息系统建设和服务能力评估(CS)
  10. php 制作骰子游戏,C/C++实现投骰子游戏