本文目录
- 一、测试用命令
- 二、iperf3客户端状态机中各个状态解析
- 状态机迁移图
- 运行正向TCP单向测试时的客户端的状态列表
- 三、iperf3客户端状态机迁移分析
- A-初始化测试对象(NA--->初始化状态):
- B-建立控制连接,等待服务端PARAM_EXCHANGE的指令(初始化状态--->PARAM_EXCHANGE状态):
- C-完成服务端与客户端的配置参数交换(PARAM_EXCHANGE状态--->CREATE_STREAM状态):
- D-发起创建TCP测试链接(CREATE_STREAM状态--->TEST_START状态):
- E-创建客户端为TCP测试流使用的各种定时器及其它资源(TEST_START状态--->TEST_RUNNING状态):
- F-发送TCP测试数据流,直到本次测试结束(TEST_RUNNING状态--->TEST_END状态):
- G-不做什么,等待服务端下一条指令(TEST_END状态--->EXCHANGE_RESULT状态):
- H-把测试结果发送给服务端(EXCHANGE_RESULT状态--->DISPLAY_RESULTS状态) :
- I-打印测试报告,并向服务端发IPERF_DONE指令(DISPLAY_RESULTS状态--->IPERF_DONE状态):
- J-本次测试完成,释放所有资源,退出iperf3客户端程序(IPERF_DONE状态--->NA):
这里描述的是iperf3进行单向TCP正向流测试时的iperf3客户端的状态机转换过程,以及转换过程中的代码调用关系。通过前面的iperf3代码主要架构分析之main函数主要流程我们已经知道iperf3虽然是C语言编写的,但它是以面向对象的方式实现的,所以本文中讲述的状态机是以每个测试对象(即为每次测试实例的运行过程创建一个测试对象,从测试开始到测试进行到测试结束输入测试报告管理测试实例的整个生命周期)为单位的。每个测试对象都拥有独立的状态机。所以这里同时也引也客户端和服务端都有自己的独立的状态机,服务端和客户端的状态会通过控制链接相互同步。
一、测试用命令
在正常的测试过程中,使用如下图描述的命令启动iperf3进行单向TCP正向流测试:
- 服务端
iperf3 -s
- 客户端
总共发送8K数据,每次发送1K
iperf3 -c 127.0.0.1 -n 8K -l 1K
二、iperf3客户端状态机中各个状态解析
状态机迁移图
有限状态机编程通常是由当前状态,事件+条件,动作,状态迁移(或称为目标状态)的五元组组成的。所以下面我们也会用这五元组来描述状态。如图所示,iperf3客户端在正常情况下(客户端启动测试后,就一直跑到测试完成,中途不中断测试)有9个状态。状态迁移方向如如箭头所示,状态迁移发生的”事件+条件“由箭头上的字母标识,会在下一章中详细解析。
运行正向TCP单向测试时的客户端的状态列表
- 初始化状态
- PARAM_EXCHANGE状态
- CREATE_STREAM状态
- TEST_START状态
- TEST_RUNNING状态
- TEST_END状态
- EXCHANGE_RESULT状态
- DISPLAY_RESULT状态
- IPERF_DONE状态
三、iperf3客户端状态机迁移分析
这一章节描述各个状态下有限状态机迁移五元组源代码调用过程。
A-初始化测试对象(NA—>初始化状态):
服务端开始运行,创建测试对象后,对象状态会直接初始化成初始化状态,函数调用关系如下
-----------------------------------------------------------------------------------
debug out: func = main ,line = 62, file = main.c
debug out: func = iperf_new_test ,line = 2748, file = iperf_api.c
debug out: func = iperf_defaults ,line = 2812, file = iperf_api.c
debug out: func = iperf_parse_arguments ,line = 1136, file = iperf_api.c
debug out: test state is 0
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | 无 |
事件+条件 | perf3做为客户端被启动运行 |
动作 | A-初始化测试对象 |
下一状态 | 初始化状态 |
B-建立控制连接,等待服务端PARAM_EXCHANGE的指令(初始化状态—>PARAM_EXCHANGE状态):
根据用户的输入参数,向服务端发起连接请求,等链接建立成功后,调用iperf_handle_message_client()函数来等待服务端发送过来的“准备好做PARAM_EXCHANGE的指令”(通过test->ctrl_sck指向的控制链接) 。
......
-----------------------------------------------------------------------------------
debug out: func = main ,line = 62, file = main.c
debug out: func = iperf_new_test ,line = 2748, file = iperf_api.c
debug out: func = iperf_defaults ,line = 2812, file = iperf_api.c
debug out: func = iperf_parse_arguments ,line = 1136, file = iperf_api.c
debug out: test state is 0
-----------------------------------------------------------------------------------
debug out: func = run ,line = 145, file = main.c
debug out: func = run ,line = 196, file = main.c
debug out: func = iperf_run_client ,line = 536, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 566, file = iperf_client_api.c
debug out: func = iperf_connect ,line = 376, file = iperf_client_api.c
debug out: func = make_cookie ,line = 119, file = iperf_util.c
debug out: func = netdial ,line = 237, file = net.c
debug out: create control link
debug out: func = create_socket ,line = 129, file = net.c
debug out: func = timeout_connect ,line = 87, file = net.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 0 to 9
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | 初始化状态 |
事件+条件 | 无条件向下执行 |
动作 | B-建立控制连接,等待服务端PARAM_EXCHANGE的指令 |
下一状态 | PARAM_EXCHANGE状态 |
C-完成服务端与客户端的配置参数交换(PARAM_EXCHANGE状态—>CREATE_STREAM状态):
在收以服务端发过来的PARAM_EXCHANGE指令后,调用iperf_exchange_parameters函数,通过控制链接向服务端发送配置参数,完成服务端与客户端的参数交换后,重新调用iperf_handle_message_client()等待服务端发送CREATE_STREAM指令
......
-----------------------------------------------------------------------------------
debug out: func = run ,line = 145, file = main.c
debug out: func = run ,line = 196, file = main.c
debug out: func = iperf_run_client ,line = 536, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 566, file = iperf_client_api.c
debug out: func = iperf_connect ,line = 376, file = iperf_client_api.c
debug out: func = make_cookie ,line = 119, file = iperf_util.c
debug out: func = netdial ,line = 237, file = net.c
debug out: create control link
debug out: func = create_socket ,line = 129, file = net.c
debug out: func = timeout_connect ,line = 87, file = net.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 0 to 9
-----------------------------------------------------------------------------------
debug out: func = iperf_exchange_parameters,line = 2076, file = iperf_api.c
debug out: func = send_parameters ,line = 2160, file = iperf_api.c
debug out: func = iperf_on_connect ,line = 908, file = iperf_api.c
debug out: func = iperf_on_connect ,line = 921, file = iperf_api.c
Connecting to host 127.0.0.1, port 5201
debug out: func = iperf_on_connect ,line = 952, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 9 to 10
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | PARAM_EXCHANGE状态 |
事件+条件 | 收到服务端发过来的PARAM_EXCHANGE指令 |
动作 | C-完成服务端与客户端的配置参数交换,等待服务端的下一条指令 |
下一状态 | CREATE_STREAM状态 |
D-发起创建TCP测试链接(CREATE_STREAM状态—>TEST_START状态):
在收到服务端发过来的CREATE_STREAM指令后,调用iperf_create_streams函数,创建本次新的TCP测试流实例 ,重新调用iperf_handle_message_client()等待服务端发起的TEST_START指令。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_exchange_parameters,line = 2076, file = iperf_api.c
debug out: func = send_parameters ,line = 2160, file = iperf_api.c
debug out: func = iperf_on_connect ,line = 908, file = iperf_api.c
debug out: func = iperf_on_connect ,line = 921, file = iperf_api.c
Connecting to host 127.0.0.1, port 5201
debug out: func = iperf_on_connect ,line = 952, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 9 to 10
-----------------------------------------------------------------------------------
debug out: func = iperf_create_streams ,line = 69, file = iperf_client_api.c
debug out: func = create_socket ,line = 129, file = net.c
debug out: func = iperf_new_stream ,line = 4241, file = iperf_api.c
debug out: func = iperf_add_stream ,line = 4453, file = iperf_api.c
[ 5] local 127.0.0.1 port 59494 connected to 127.0.0.1 port 5201
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 10 to 1
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | CREATE_STREAM状态 |
事件+条件 | 收到服务端发起的CREATE_STREAM指令 |
动作 | D-发起创建TCP测试链接,等待服务端的TEST_START指令 |
下一状态 | TEST_START状态 |
E-创建客户端为TCP测试流使用的各种定时器及其它资源(TEST_START状态—>TEST_RUNNING状态):
进入TEST_START状态后,无条件的开始创建客户端为TCP测试流使用的各种定时器及其它资源,然后等待服务端发过来TEST_RUNNING指令。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 10 to 1
-----------------------------------------------------------------------------------
debug out: func = iperf_init_test ,line = 1972, file = iperf_api.c
debug out: func = create_client_timers ,line = 179, file = iperf_client_api.c
debug out: func = create_client_omit_timer ,line = 234, file = iperf_client_api.c
debug out: func = iperf_create_send_timers ,line = 2011, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 1 to 2
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | TEST_START状态 |
事件+条件 | 进入TEST_START状态后,无条件开始以下动作 |
动作 | E-创建客户端为TCP测试流使用的各种定时器及其它资源 |
下一状态 | TEST_RUNNING状态 |
F-发送TCP测试数据流,直到本次测试结束(TEST_RUNNING状态—>TEST_END状态):
调用iperf_run_client函数,直接进入TEST_RUNNING分支后,调用iperf_send函数里的sp->rcv和test->protocol->recv二个函数指针,最终调用iperf_tcp_send()函数向服务端发送测试数据开始测试,直到本次测试结束后进入到TEST_END状态,并向服务端发送TEST_END指令。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_init_test ,line = 1972, file = iperf_api.c
debug out: func = create_client_timers ,line = 179, file = iperf_client_api.c
debug out: func = create_client_omit_timer ,line = 234, file = iperf_client_api.c
debug out: func = iperf_create_send_timers ,line = 2011, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 1 to 2
-----------------------------------------------------------------------------------
debug out: func = iperf_run_client ,line = 633, file = iperf_client_api.c
debug out: func = iperf_send ,line = 1890, file = iperf_api.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_stats_callback ,line = 3237, file = iperf_api.c
debug out: func = iperf_set_send_state ,line = 1810, file = iperf_api.c
wangsheng: set the state from 2 to 4
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | TEST_RUNNING状态 |
事件+条件 | 进入TEST_RUNNING状态后,无条件开始以下动作 |
动作 | F-发送TCP测试数据流,直到本次测试结束 |
下一状态 | TEST_END状态 |
G-不做什么,等待服务端下一条指令(TEST_END状态—>EXCHANGE_RESULT状态):
调用iperf_handle_message_client()等待服务端发过来的EXCHANGE_RESULT指令。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_tcp_send ,line = 87, file = iperf_tcp.c
debug out: func = iperf_send ,line = 1907, file = iperf_api.c
debug out: func = iperf_stats_callback ,line = 3237, file = iperf_api.c
debug out: func = iperf_set_send_state ,line = 1810, file = iperf_api.c
wangsheng: set the state from 2 to 4
-----------------------------------------------------------------------------------
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 4 to 13
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | TEST_END状态 |
事件+条件 | 收到服务端发过来的EXCHANGE_RESULT指令 |
动作 | G-不做什么,等待服务端下一条指令 |
下一状态 | EXCHANGE_RESULT状态 |
H-把测试结果发送给服务端(EXCHANGE_RESULT状态—>DISPLAY_RESULTS状态) :
进入EXCHANGE_RESULT状态后,服务端无条件调用iperf_exchange_result()函数,向服务端发送的测试报告后等待服务商端发过来的DISPLAY_RESULTS指令。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 4 to 13
-----------------------------------------------------------------------------------
debug out: func = iperf_exchange_results ,line = 2134, file = iperf_api.c
debug out: func = send_results ,line = 2367, file = iperf_api.c
debug out: func = get_results ,line = 2488, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 13 to 14
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | EXCHANGE_RESULT状态 |
事件+条件 | 进入EXCHANGE_RESULT状态后,无条件开始以下动作 |
动作 | H-把测试结果发送给服务端,等待服务端发过来的下一条指令 |
下一状态 | DISPLAY_RESULTS状态 |
I-打印测试报告,并向服务端发IPERF_DONE指令(DISPLAY_RESULTS状态—>IPERF_DONE状态):
进入DISPLAY_RESULTS状态后,客户端主动发起打印测试报告,并向服务端发IPERF_DONE指令。
......
debug out: func = iperf_exchange_results ,line = 2134, file = iperf_api.c
debug out: func = send_results ,line = 2367, file = iperf_api.c
debug out: func = get_results ,line = 2488, file = iperf_api.c
debug out: func = iperf_run_client ,line = 620, file = iperf_client_api.c
debug out: func = iperf_handle_message_client,line = 267, file = iperf_client_api.c
debug out: receive and change the state from 13 to 14
-----------------------------------------------------------------------------------
debug out: func = iperf_client_end ,line = 490, file = iperf_client_api.c
debug out: func = iperf_reporter_callback ,line = 4075, file = iperf_api.c
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-0.00 sec 8.00 KBytes 105 Mbits/sec 0 320 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-0.00 sec 8.00 KBytes 105 Mbits/sec 0 sender
[ 5] 0.00-0.00 sec 4.00 KBytes 36.8 Mbits/sec receiver
debug out: func = iperf_set_send_state ,line = 1810, file = iperf_api.c
debug out: set the state from 14 to 16
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | DISPLAY_RESULTS状态 |
事件+条件 | 进入DISPLAY_RESULTS状态后,无条件开始以下动作 |
动作 | I-打印测试报告,并向服务端发IPERF_DONE指令 |
下一状态 | IPERF_DONE状态 |
J-本次测试完成,释放所有资源,退出iperf3客户端程序(IPERF_DONE状态—>NA):
进入IPERF_DONE状态后,释放所有资源,退出iperf3客户端程序,本次测试完成。
......
-----------------------------------------------------------------------------------
debug out: func = iperf_client_end ,line = 490, file = iperf_client_api.c
debug out: func = iperf_reporter_callback ,line = 4075, file = iperf_api.c
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-0.00 sec 8.00 KBytes 105 Mbits/sec 0 320 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-0.00 sec 8.00 KBytes 105 Mbits/sec 0 sender
[ 5] 0.00-0.00 sec 4.00 KBytes 36.8 Mbits/sec receiver
debug out: func = iperf_set_send_state ,line = 1810, file = iperf_api.c
wangsheng: set the state from 14 to 16
-----------------------------------------------------------------------------------
iperf Done.
-----------------------------------------------------------------------------------
状态机元组名称 | 状态机元组当前值 |
---|---|
当前状态 | IPERF_DONE状态 |
事件+条件 | 进入IPERF_DONE状态后,无条件开始以下动作 |
动作 | J-本次测试完成,释放所有资源,退出iperf3客户端程序 |
下一状态 | NA |