跳到主要内容

6. 测试建立请求与响应 (Test Setup Request and Response)

客户端源 IP 地址和服务器目标 IP 地址不得 (MUST NOT) 是广播地址或组播地址. 任何包含组播或广播源 IP 地址或目标 IP 地址的 Test Setup Request 或 Test Setup Response 数据包都必须 (MUST) 被静默丢弃并忽略.

本文档规定的测量方法和协议预期可使用单播和任播 IP 地址运行.

6.1. 客户端生成 Test Setup Request

客户端应 (SHALL) 通过向服务器的标准控制端口发送 Test Setup Request 消息来开始 Control phase 交换. 对于多连接测试的每个连接, 都使用这个标准 UDPSTP 端口号.

客户端应 (SHALL) 同时启动测试发起定时器, 以便在 Control phase 未能在分配时间内完成 Test Setup 和 Test Activation 交换时, 客户端软件应 (SHALL) 退出, 即 UDP 套接字将被关闭, 并向用户显示错误消息. 消息丢失会导致 Test Setup 和 Test Activation 失败. 测试发起定时器可以 (MAY) 复用测试终止超时值.

看门狗超时 (watchdog timeout) 配置为 1 秒间隔, 用于触发一条警告消息, 表示接收流量已经停止. 测试终止超时基于看门狗间隔, 并在触发非优雅终止之前再等待 2 秒.

注: 在任何 PDU 中, 标记为 "reserved for alignment" 的任何字段都必须 (MUST) 设置为 0, 并且接收时必须 (MUST) 忽略.

UDP PDU 格式布局应 (SHALL) 如下所示 (大端 AB, 从最高有效字节开始, 到最低有效字节结束):

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| pduId | protocolVer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| mcIndex | mcCount | mcIdent |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| cmdRequest | cmdResponse | maxBandwidth |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| testPort |modifierBitmap | authMode |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| authUnixTime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. authDigest (32 octets) .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| keyId | reservedAuth1 | checkSum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

图 2: Test Setup PDU 布局

Setup Request 和 Response 字段的更多细节如下:

pduId: 两个八位字节字段. IANA 已分配十六进制值 0xACE1 (第 12.3.1 节).

protocolVer: 两个八位字节字段, 用于标识实际协议版本. IANA 已将值 20 分配给该字段 (第 12.3.2 节).

mcIndex: 一个八位字节字段, 表示某个连接相对于组成单个测试的所有连接的索引 (从 0 开始, 每个连接递增 1). 它用于区分多连接测试中的独立连接. 实现可以将单个测试支持的连接数限制为小于或等于 255 的值.

mcCount: 一个八位字节字段, 表示客户端正在尝试建立的连接总数.

mcIdent: 两个八位字节字段, 包含一个伪随机非零标识符 (通过随机数生成器, 源端口号等获得), 该标识符对单个测试的所有连接都是共同的. 客户端和服务器使用它将独立连接关联到一个多连接测试.

cmdRequest: 一个八位字节字段, 设置为 CHSR_CREQ_SETUPREQ, 用于表示 Setup Request 消息. 注意, CHSR_CREQ_NONE 仍未使用.

cmdResponse: 一个八位字节字段. 所有 Request PDU 的 Command Response 始终为 XXXX_CRSP_NONE (即 CHSR_CRSP_NONE, CHNR_CRSP_NONECHTA_CRSP_NONE).

maxBandwidth: 两个八位字节字段. 该字段的非零值指定客户端期望在所请求测试期间发送或接收的最大比特率, 单位为 Mbps. 服务器将该值与其当前可用的已配置测试准入控制限制进行比较. 该字段可以 (MAY) 用于限制服务器应尝试达到的最大速率. maxBandwidth 字段的最高有效位 CHSR_USDIR_BIT 默认设置为 0, 表示 "downstream", 并且必须设置为 1 才表示 "upstream".

testPort: 两个八位字节字段, 在 Test Setup Request 中设置为 0, 并由服务器在 Test Setup Response 中填充. 它包含服务器上的 UDP 临时端口号, 客户端必须使用该端口号发送 Test Activation Request 以及后续 Load 或 Status PDU.

modifierBitmap: 一个八位字节字段. 本文档只在该位图中分配两个比特, 见第 12.3.3 节:

CHSR_JUMBO_STATUS (0x01): 默认应 (SHALL) 设置该比特. 默认情况下, 最高 1 Gbps 的发送速率不得 (SHALL NOT) 产生大于 1250 bytes 的 IP 数据包大小 (除非设置了 CHSR_TRADITIONAL_MTU), 而高于 1 Gbps 的速率可以 (MAY) 产生最高 9000 bytes 的 IP 数据包大小. 当未设置 CHSR_JUMBO_STATUS 时, 所有发送速率都不得 (SHALL NOT) 产生大于 1250 bytes 的 IP 数据包大小 (除非设置了 CHSR_TRADITIONAL_MTU).

CHSR_TRADITIONAL_MTU (0x02): 默认不得 (SHALL NOT) 设置该比特. 如果设置, 最高 1 Gbps 的发送速率可以 (MAY) 产生最高为传统大小 1500 bytes 的 IP 数据包. 如果同时未设置 CHSR_JUMBO_STATUS, 所有发送速率都不得 (SHALL NOT) 产生大于传统大小 1500 bytes 的 IP 数据包.

其他比特位置在本文档中保留为未分配.

authMode: 一个八位字节字段. authMode 字段目前分配了两个值 (见第 12.3.4 节). 必须设置以下值之一 (操作要求和细节见第 5.3 节):

AUTHMODE_1: Control phase 所需的认证.

AUTHMODE_2: Control phase 和 Data phase 所需的认证 (仅 Status Feedback PDU).

范围 60 到 63 保留用于实验. IANA 已为这些已分配值创建 "Test Setup PDU Authentication Mode" 注册表, 见第 12.3.4 节.

authUnixTime: 自 1970 年 1 月 1 日 00:00:00 UTC 的 Unix Epoch 起, 当前系统 (挂钟) 时间的 32-bit 时间戳.

authDigest: 该字段包含覆盖整个 PDU 的 32 个八位字节 HMAC-SHA-256 哈希. 通常, 计算在构建 PDU 的最后一步完成. 但是, 如果正在使用可选的 checkSum 字段, 该计算会成为倒数第二步, 并在校验和计算之前完成 (checkSum 字段设置为 0).

keyId: 一个八位字节字段, 携带 localKeyName, 即共享密钥表中某个密钥的数字密钥标识符.

reservedAuth1: 一个八位字节字段. 该字段必须 (MUST) 设置为 0, 并且接收时必须 (MUST) 忽略. 在所有 PDU 中一致命名并放置 reservedAuth1 字段, 是为了最大限度减少未来 UDPSTP 版本中与认证相关的变更.

checkSum: 两个八位字节字段, 包含整个 PDU 的可选校验和 (指导见第 5.6 节). 计算在构建 PDU 的最后一步完成, 此时 checkSum 字段设置为 0.

6.2. 服务器 Test Setup Request 处理和 Response 生成

本节描述服务器用于评估 Test Setup Request 并确定后续步骤的过程. 当服务器收到 Setup Request 时, 它应 (SHALL) 首先执行以下操作:

消息验证过程:

  1. 验证消息大小是否正确.

  2. 如果正在使用可选的 checkSum 字段, 按第 5.6 节所述验证校验和, 并且如果校验和有效, 在认证验证之前将 checkSum 字段清零.

  3. 验证 authMode 值对该消息类型是否有效且适当 (依据第 5.3 节).

  4. 如果 authMode 有效且适当, 按第 5.3 节规定检查 authDigest, 对消息进行认证.

  5. 如果消息真实可信, 检查 authUnixTime 字段是否具有可接受的即时性.

注: 如果上述任一检查失败, 该消息应 (SHALL) 被视为无效.

6.2.1. Test Setup Request 处理 - 拒绝

随后, 服务器应 (SHALL) 评估协议头部中的其他字段, 例如协议版本, PDU ID (用于验证消息类型), 测试请求的最大带宽, 以及用于 Jumbo 数据报状态和 Traditional MTU (1500 bytes) 等选项的 modifierBitmap.

如果客户端选择的以下选项与服务器配置不匹配, 服务器必须 (MUST) 拒绝 Setup Request:

  • Jumbo 数据报支持 (modifierBitmap)

  • Traditional MTU (modifierBitmap)

  • 认证模式 (authMode)

如果必须拒绝 Setup Request, 以下条件决定服务器是否发送响应:

  • 如果 authDigest 有效, 应 (SHALL) 向客户端发回 Test Setup Response, 并带有相应的 Command Response 值来表示拒绝原因.

  • 如果 authDigest 无效, 则 Test Setup Request 应当 (SHOULD) 静默失败. 例外是出于运维支持目的: 允许服务器管理员发送 Setup Response 以支持运维和故障排查.

在以下额外情况下, 服务器不得 (SHALL NOT) 为错误条件传达适当的 Command Response 代码, 即静默失败:

  • Setup Request PDU 大小不等于图 3 中所示的 struct controlHdrSR 大小,

  • PDU ID 不是 0xACE1 (Test Setup PDU), 或

  • 已检测到定向攻击.

在这种情况下, 服务器将允许建立尝试静默终止. 攻击检测超出本规范范围.

当服务器回复 Test Setup Request 消息时, Test Setup Response PDU 与 Test Setup Request PDU 结构相同, 并且应 (SHALL) 保留其中接收到的原始值, 但有以下例外:

  • cmdRequest 字段设置为 CHSR_CREQ_SETUPRSP, 表示响应.

  • cmdResponse 字段设置为错误代码 (从 cmdResponse 2, Bad Protocol Version 开始, 见第 12.3.5 节), 表示拒绝原因. 如果 cmdResponse 表示错误协议版本 (CHSR_CRSP_BADVER), protocolVer 字段也会更新, 用于指示当前预期版本.

  • authUnixTime 字段更新为当前系统 (挂钟) 时间, 并且在 authDigestcheckSum 字段清零后, 重新计算并插入 authDigest. 如果正在使用可选的 checkSum 字段, 随后也计算并插入该字段.

Setup Request/Response 消息 PDU 应 (SHALL) 按如下方式组织 (这里以及后续所有代码图都以 C 编程语言 [C-Prog] 编码):

<CODE BEGINS>
//
// Control header for UDP payload of Setup Request/Response PDUs
//
struct controlHdrSR {
#define CHSR_ID 0xACE1
uint16_t pduId; // PDU ID
#define PROTOCOL_VER 20
uint16_t protocolVer; // Protocol version
uint8_t mcIndex; // Multi-connection index
uint8_t mcCount; // Multi-connection count
uint16_t mcIdent; // Multi-connection identifier
#define CHSR_CREQ_NONE 0
#define CHSR_CREQ_SETUPREQ 1 // Setup Request
#define CHSR_CREQ_SETUPRSP 2 // Setup Response
uint8_t cmdRequest; // Command Request
#define CHSR_CRSP_NONE 0 // (used with request)
#define CHSR_CRSP_ACKOK 1 // Acknowledgment
#define CHSR_CRSP_BADVER 2 // Bad version
#define CHSR_CRSP_BADJS 3 // Jumbo setting mismatch
#define CHSR_CRSP_AUTHNC 4 // Auth. not configured
#define CHSR_CRSP_AUTHREQ 5 // Auth. required
#define CHSR_CRSP_AUTHINV 6 // Auth. (mode) invalid
#define CHSR_CRSP_AUTHFAIL 7 // Auth. failure
#define CHSR_CRSP_AUTHTIME 8 // Auth. time invalid
#define CHSR_CRSP_NOMAXBW 9 // Max bandwidth required
#define CHSR_CRSP_CAPEXC 10 // Capacity exceeded
#define CHSR_CRSP_BADTMTU 11 // Trad. MTU mismatch
#define CHSR_CRSP_MCINVPAR 12 // Multi-conn. invalid params
#define CHSR_CRSP_CONNFAIL 13 // Conn. allocation failure
uint8_t cmdResponse; // Command Response
#define CHSR_USDIR_BIT 0x8000 // Upstream direction bit
uint16_t maxBandwidth; // Required bandwidth in Mbps
uint16_t testPort; // Test port on server
#define CHSR_JUMBO_STATUS 0x01
#define CHSR_TRADITIONAL_MTU 0x02
uint8_t modifierBitmap; // Modifier bitmap
// ========== Integrity Verification ==========
#define AUTHMODE_1 1 // Mode 1: Authenticated Control
#define AUTHMODE_2 2 // Mode 2: Authenticated Control+Status
uint8_t authMode; // Authentication mode
uint32_t authUnixTime; // Authentication timestamp
#define AUTH_DIGEST_LENGTH 32 // SHA-256 digest length
uint8_t authDigest[AUTH_DIGEST_LENGTH];
uint8_t keyId; // Key ID in shared table
uint8_t reservedAuth1; // (reserved for alignment)
uint16_t checkSum; // Header checksum
};
#define SHA256_KEY_LEN 32 // Authentication key length
<CODE ENDS>

图 3: Test Setup PDU

6.2.2. Test Setup Request 处理 - 接受

如果服务器发现 Setup Request 与其配置匹配, 并且在其他方面也可接受, 则服务器应 (SHALL) 使用从 UDP 临时端口范围分配的新 UDP 套接字, 发起一个新连接以接收来自客户端的 Test Activation Request. 这个新套接字还将用于测试中的后续 Load 和 Status PDU (端口号通过 Test Setup Response 的 testPort 字段传回客户端). 然后, 服务器应 (SHALL) 启动看门狗定时器 (如果客户端静默, 则终止新连接), 并应 (SHALL) 将 Test Setup Response 发回客户端. 看门狗定时器设置为与客户端侧相同的值 (见第 6 节).

当服务器回复 Test Setup Request 消息时, Test Setup Response PDU 与 Test Setup Request PDU 结构相同, 并且应 (SHALL) 保留其中接收到的原始值, 但有以下例外:

  • cmdRequest 字段设置为 CHSR_CREQ_SETUPRSP, 表示响应.

  • cmdResponse 字段设置为 CHSR_CRSP_ACKOK, 表示确认.

  • testPort 字段设置为临时端口号, 客户端的 Test Activation Request 和所有后续通信都将使用该端口号.

  • authUnixTime 字段更新为当前系统 (挂钟) 时间, 并且在 authDigestcheckSum 字段清零后, 重新计算并插入 authDigest. 如果正在使用可选的 checkSum 字段, 随后也计算并插入该字段.

最后, 与新套接字和端口号关联的新 UDP 连接准备就绪, 服务器在该处等待后续通信.

为确保服务器本地防火墙能成功允许发往新临时端口号的数据包, 服务器应 (SHALL) 立即发送一个 Null Request, 其中包含对应值, 包括源和目标 IP 地址以及端口号. 源端口应 (SHALL) 是新的临时端口. 即使服务器本地防火墙禁止开放临时端口范围, 该操作也允许通信到达服务器. 如果客户端侧防火墙阻止非预期流量, 该数据包预期不会成功到达客户端. 如果 Null Request 到达客户端, 它确认新端口对上的进一步交换是可能的 (但这并非严格必要). 如果收到该消息, 客户端应 (SHALL) 遵循第 6.2 节第 2 段列出的消息验证过程. 注意, Null Request 没有响应.

UDP PDU 格式布局应 (SHALL) 如下所示 (大端 AB):

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| pduId | protocolVer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| cmdRequest | cmdResponse | reserved1 | authMode |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| authUnixTime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. authDigest (32 octets) .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| keyId | reservedAuth1 | checkSum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

图 4: Null Request PDU 布局

认证字段和 checkSum 字段遵循与 Setup Request 和 Response 相同的方法.

Null Request 字段的更多细节如下:

pduId: IANA 已分配十六进制值 0xDEAD (第 12.3.1 节).

cmdRequest: 设置为 CHNR_CREQ_NULLREQ, 用于表示 Null Request 消息.

cmdResponse: 设置为 CHNR_CRSP_NONE.

authMode: 同第 6.1 节.

authUnixTime: 同第 6.1 节.

authDigest: 同第 6.1 节.

keyId: 同第 6.1 节.

reservedAuth1: 同第 6.1 节.

checkSum: 同第 6.1 节.

如果随后在看门狗定时器到期之前, 服务器未在新的临时端口号上收到来自客户端的 Test Activation Request, 服务器应 (SHALL) 关闭套接字并释放相关资源.

Null Request 消息 PDU 应 (SHALL) 按如下方式组织:

<CODE BEGINS>
//
// Control header for UDP payload of Null Request PDU
//
struct controlHdrNR {
#define CHNR_ID 0xDEAD
uint16_t pduId; // PDU ID
uint16_t protocolVer; // Protocol version
#define CHNR_CREQ_NONE 0
#define CHNR_CREQ_NULLREQ 1 // Null Request
uint8_t cmdRequest; // Command Request
#define CHNR_CRSP_NONE 0 // (used with request)
uint8_t cmdResponse; // Command Response
uint8_t reserved1; // (reserved for alignment)
// ========== Integrity Verification ==========
uint8_t authMode; // Authentication mode
uint32_t authUnixTime; // Authentication timestamp
uint8_t authDigest[AUTH_DIGEST_LENGTH];
uint8_t keyId; // Key ID in shared table
uint8_t reservedAuth1; // (reserved for alignment)
uint16_t checkSum; // Header checksum
};
<CODE ENDS>

图 5: Null Request PDU

6.3. 客户端处理 Setup Response

当客户端收到 Test Setup Response 消息时, 它应 (SHALL) 首先遵循第 6.2 节第 2 段列出的消息验证过程.

随后, 客户端应 (SHALL) 继续评估协议中的其他字段, 从协议版本, PDU ID (用于验证消息类型) 以及表示消息角色的 cmdRequest 开始. 该消息必须 (MUST) 是 Test Setup Response, 即图 3 所示的 CHSR_CREQ_SETUPRSP.

如果 cmdResponse 值表示错误 (大于 CHSR_CRSP_ACKOK 的值), 客户端应 (SHALL) 向用户或管理进程显示或报告相关消息并退出. 如果客户端收到的 Command Response 代码不等于任何已定义代码, 客户端必须 (MUST) 终止连接, 并终止当前 Setup Request 的操作. 如果 Command Response 代码值表示成功 (CHSR_CRSP_ACKOK), 客户端应 (SHALL) 组合一个 Test Activation Request, 其中包含它需要的所有测试参数, 例如测试方向, 测试持续时间等, 如下文所述.