DCCP 协议

简介

数据报拥塞控制协议 (DCCP) 是一种不可靠的、面向连接的协议,旨在解决 UDP 和 TCP 中存在的问题,特别是对于实时和多媒体(流媒体)流量。它分为基本协议 (RFC 4340) 和可插拔的拥塞控制模块(称为 CCID)。与可插拔的 TCP 拥塞控制类似,必须启用至少一个 CCID,该协议才能正常运行。在 Linux 实现中,这是类似 TCP 的 CCID2 (RFC 4341)。其他 CCID(例如 TCP 友好的 CCID3 (RFC 4342))是可选的。有关 CCID 的简要介绍以及选择与给定应用程序匹配的 CCID 的建议,请参阅 RFC 4340 的第 10 节。

它具有基本协议和可插拔的拥塞控制 ID (CCID)。

DCCP 是一项建议标准 (RFC 2026),DCCP 作为协议的主页位于 http://www.ietf.org/html.charters/dccp-charter.html

缺失的功能

Linux DCCP 实现目前不支持 RFC 4340...42 中指定的所有功能。

已知的错误位于

有关 DCCP 实现的最新版本,请考虑使用实验性的 DCCP 测试树;有关检出的说明位于:http://www.linuxfoundation.org/collaborate/workgroups/networking/dccp_testing#Experimental_DCCP_source_tree

套接字选项

DCCP_SOCKOPT_QPOLICY_ID 设置传出数据包的取消排队策略。它以策略 ID 作为参数,并且只能在连接之前设置(即,不支持在已建立的连接期间进行更改)。目前,定义了两种策略:“simple”策略 (DCCPQ_POLICY_SIMPLE),它不做任何特殊的事情,以及基于优先级的变体 (DCCPQ_POLICY_PRIO)。后者允许将 u32 优先级值作为辅助数据传递给 sendmsg(),其中较高的数字表示较高的数据包优先级(类似于 SO_PRIORITY)。此辅助数据需要使用 cmsg(3) 消息头进行格式化,如下所示

cmsg->cmsg_level = SOL_DCCP;
cmsg->cmsg_type  = DCCP_SCM_PRIORITY;
cmsg->cmsg_len   = CMSG_LEN(sizeof(uint32_t));  /* or CMSG_LEN(4) */

DCCP_SOCKOPT_QPOLICY_TXQLEN 设置输出队列的最大长度。零值始终被解释为无界队列长度。如果不同于零,则此参数的解释取决于当前的取消排队策略(见上文):“simple”策略将通过返回 EAGAIN 来强制执行固定队列大小,而“prio”策略将通过首先丢弃最低优先级的数据包来强制执行固定队列长度。此参数的默认值是从 /proc/sys/net/dccp/default/tx_qlen 初始化。

DCCP_SOCKOPT_SERVICE 设置服务。规范要求使用服务代码(RFC 4340,第 8.1.2 节);如果未设置此套接字选项,则套接字将回退到 0(这意味着不存在有意义的服务代码)。在活动套接字上,在 connect() 之前设置此值;指定多个代码无效(所有后续服务代码将被忽略)。被动套接字的情况不同,在调用 bind() 之前可以设置多个服务代码(最多 32 个)。

DCCP_SOCKOPT_GET_CUR_MPS 是只读的,并检索当前的最大数据包大小(应用程序有效负载大小),以字节为单位,请参阅 RFC 4340,第 14 节。

DCCP_SOCKOPT_AVAILABLE_CCIDS 也是只读的,并返回端点支持的 CCID 列表。选项值是一个 uint8_t 类型的数组,其大小作为选项长度传递。最小数组大小为 4 个元素,optlen 参数中返回的值始终反映内置 CCID 的真实数量。

DCCP_SOCKOPT_CCID 是只写的,并同时设置 TX 和 RX CCID,组合了下两个套接字选项的操作。此选项优先于后两个选项,因为应用程序通常会使用相同类型的 CCID 用于两个方向;并且目前对 CCID 的混合使用了解不充分。此套接字选项至少接受一个 uint8_t 值或一个 uint8_t 值数组作为参数,该值或数组必须与可用的 CCID(见上文)匹配。必须在调用 connect() 或 listen() 之前在套接字上注册 CCID。

DCCP_SOCKOPT_TX_CCID 是读/写的。它返回当前 CCID(如果已设置)或使用与 DCCP_SOCKOPT_CCID 相同的格式设置 TX CCID 的首选项列表。请注意,这里的 getsockopt 参数类型是 int,而不是 uint8_t。

DCCP_SOCKOPT_RX_CCID 与 DCCP_SOCKOPT_TX_CCID 类似,但用于 RX CCID。

DCCP_SOCKOPT_SERVER_TIMEWAIT 使服务器(侦听套接字)在关闭连接时保持 timewait 状态 (RFC 4340, 8.3)。通常情况是,关闭服务器会发送一个 CloseReq,然后客户端保持 timewait 状态。当此布尔套接字选项打开时,服务器将改为发送 Close 并将进入 TIMEWAIT。必须在 accept() 返回后设置此选项。

DCCP_SOCKOPT_SEND_CSCOV 和 DCCP_SOCKOPT_RECV_CSCOV 用于设置部分校验和覆盖率 (RFC 4340, sec. 9.2)。默认情况下,校验和始终覆盖整个数据包,并且接收器仅接受完全覆盖的应用程序数据。因此,在发送器上使用此功能时,也必须在接收器上启用该功能,并适当选择 CsCov。

DCCP_SOCKOPT_SEND_CSCOV 设置发送器校验和覆盖率。范围为

0..15 的值是可接受的。默认设置为 0(完全覆盖),1..15 之间的值表示部分覆盖。

DCCP_SOCKOPT_RECV_CSCOV 用于接收器,并且具有不同的含义:它

设置一个阈值,其中 0..15 的值也是可接受的。默认值 0 表示所有具有部分覆盖率的数据包都将被丢弃。范围 1..15 中的值表示最小具有此覆盖率值的数据包也是可接受的。数字越高,此设置的限制性就越高(请参阅 [RFC 4340, sec. 9.2.1])。部分覆盖率设置将继承到 accept() 之后的子套接字。

以下两个选项专门应用于 CCID 3,并且仅限 getsockopt() 使用。在任何一种情况下,都会返回一个 TFRC 信息结构(在 <linux/tfrc.h> 中定义)。

DCCP_SOCKOPT_CCID_RX_INFO

在 optval 中返回 struct tfrc_rx_info;optval 和 optlen 的缓冲区必须至少设置为 sizeof(struct tfrc_rx_info)。

DCCP_SOCKOPT_CCID_TX_INFO

在 optval 中返回 struct tfrc_tx_info;optval 和 optlen 的缓冲区必须至少设置为 sizeof(struct tfrc_tx_info)。

在单向连接上,通过 shutdown (SHUT_WR 或 SHUT_RD) 关闭未使用的半连接非常有用:这将减少每个数据包的处理成本。

Sysctl 变量

可以通过以下 sysctl(sysctl net.dccp.default 或 /proc/sys/net/dccp/default)管理多个 DCCP 默认参数

request_retries

在超时之前,主动连接启动重试的次数(请求次数减 1)。此外,它还控制另一个被动侧的行为:此变量还设置当初始握手没有从 RESPOND 进展到 OPEN 时(即,在初始请求之后未收到 Ack 时),DCCP 重复发送响应的次数。此值应大于 0,建议小于 10。与 tcp_syn_retries 类似。

retries1

DCCP 响应重新传输的频率,直到侦听 DCCP 端认为其连接对等端已死。与 tcp_retries1 类似。

retries2

重新传输通用 DCCP 数据包的次数。这对于重新传输的确认和功能协商很重要,数据数据包永远不会重新传输。与 tcp_retries2 类似。

tx_ccid = 2

发送器-接收器半连接的默认 CCID。根据 CCID 的选择,自动启用发送 Ack 向量功能。

rx_ccid = 2

接收器-发送器半连接的默认 CCID;请参阅 tx_ccid。

seq_window = 100

发送器的初始序列窗口 (sec. 7.5.2)。这会影响本地 ackno 有效性窗口和远程 seqno 有效性窗口 (7.5.1)。可以设置范围 Wmin = 32 (RFC 4340, 7.5.2) 到 2^32-1 的值。

tx_qlen = 5

传输缓冲区的大小(以数据包为单位)。值 0 对应于无界传输缓冲区。

sync_ratelimit = 125 ms

在同一套接字上响应序列无效数据包而发送的后续 DCCP 同步数据包之间的超时 (RFC 4340, 7.5.4)。此参数的单位为毫秒;值 0 禁用速率限制。

IOCTLS

FIONREAD

与 udp(7) 中的功能相同:在 int 参数指针中返回下一个挂起数据报的大小(以字节为单位),或者在没有挂起数据报时返回 0。

SIOCOUTQ

将套接字发送队列中未发送的数据字节数以 int 格式返回到参数指针指定的缓冲区中。

其他可调参数

每个路由的 rto_min 支持

CCID-2 支持每个路由的 RTAX_RTO_MIN 设置,用于设置 RTO 计时器的最小值。此设置可以通过 iproute2 的 ‘rto_min’ 选项进行修改;例如:

> ip route change 10.0.0.0/24   rto_min 250j dev wlan0
> ip route add    10.0.0.254/32 rto_min 800j dev wlan0
> ip route show dev wlan0

CCID-3 也支持 rto_min 设置:它用于定义无反馈定时器过期的下限。这在具有非常低 RTT 的 LAN(例如,环回,千兆以太网)上很有用。

注意事项

目前,DCCP 在许多设备上无法成功穿越 NAT。这是因为校验和覆盖了伪报头,就像 TCP 和 UDP 一样。 Linux 对 DCCP 的 NAT 支持已经添加。