The Datagram Congestion Control Protocol
(DCCP)

DCCP is a networking protocol that provides congestion control without guaranteeing reliability or in-order delivery of data. As such, it neatly bridges the gap between TCP, which provides reliable delivery with congestion control, and UDP, which provides neither reliable delivery nor congestion control.

DCCP is ideal for applications where old data is substantially less valuable than the most recent data. A classic example is VoIP (Voice over Internet Protocol); if a packet is lost, you don't want to wait for it to be retransmitted, you want to continue to receive the most recent packets. Other potential applications include real-time streaming video and Internet-connected video games.

These applications typically use UDP with application level congestion control. Unfortunately, experience has shown that congestion control algorithms are difficult to design and implement correctly. In addition, there is massive duplication of effort since each application needs to design and implement its own scheme. DCCP simplifies this situation, by providing congestion control automatically without any additional effort on the part of the application programmer.

On a more technical level, DCCP utilizes a datagram model; that is, content is seen as individual datagrams, like UDP, and not as a stream of bytes, as in TCP. However, DCCP is a connection oriented protocol with a handshake similar to TCP. In addition, DCCP is designed to support multiple congestion control algorithms, or CCIDs.

For details on the DCCP protocol see RFC 4340. Two CCIDs are currently standardized: CCID 2 or TCP-Like Congestion Control in RFC 4341 and CCID 3 or TCP-Friendly Rate Control in RFC 4342. A few other CCIDs are currently under development, including CCID 4 (RFC 5622) and CCID 5 ( announcement here). DCCP is implemented in Linux and a testing tree is maintained at http://eden-feed.erg.abdn.ac.uk/cgi-bin/gitweb.cgi?p=dccp_exp.git.



Dccp2tcp

I developed a tool called dccp2tcp to help analyze DCCP packet captures. This tool takes a DCCP packet capture and converts it to a semantically similar TCP capture which can then be analyzed with Dr. Shawn Ostermann's tcptrace utility ( http://www.tcptrace.org). This provides a vast amount of information about a DCCP connection in an easy to understand graphical format.

I have released dccp2tcp under the GNU GPL. You may obtain the prgram from my git repository at github. Dccp2tcp will only compile on Linux because it requires the Linux Kernel DCCP headers. My testing has been restricted to 64bit Ubuntu/Debian, but dccp2tcp should work fine on any Linux variant with a kernel greater than 2.6.18.

The following graph provides an example of the output that dccp2tcp (in combination with tcptrace) produces. The white line segments represent data packets that were sent. Increases in the green line represent packets being acknowledged, and the purple line segments represent acknowledgment vectors that indicate a loss. The yellow line is an artifact of the DCCP to TCP conversion and has no meaning for DCCP.




Major Bug Fixes in Linux 3.2

Several major bug fixes for DCCP, particularly CCID 2, were included in Linux 3.2. These fixes improved dramatically improved the stability of CCID 2 and the durability of the DCCP implementation in general. For details, see this message on the DCCP Linux mailing list. If you are planning on testing or utilizing DCCP, I strongly recommend that you use a version of the Linux kernel newer than 3.2.



Notes on using DCCP in a Virtual Machine

Over the course of my research, I discovered that running DCCP on a virtual machine without virtualization extensions (AMD-V or VT-x) results in very poor performance. If you are considering using DCCP in a virtualized environment, I strongly recommend you ensure that your host machine supports these extensions.

The reason for the poor performance is that DCCP is a datagram-based protocol. This means that every packet that is sent or received requires a system call.

As a result, in order to achieve even 10Mbits/sec the virtual machine needs to make about 766,000 system calls per second. Without virtualization extensions, each of these is an extremely expensive operation. In my tests, even 10Mbits/sec was too fast for the system: within milliseconds the receiver's kernel socket buffer overflowed and DCCP dropped an entire window of packets. When that happens, RFC 4340 requires DCCP to pause for 200ms.

This results in a pattern of network traffic where DCCP sends for a few milliseconds, looses an entire window of packets, waits 200 milliseconds, and then starts sending again only to repeat the cycle a few milliseconds later.

TCP and UDP get around this issue by allowing userspace to dump arbitrary sized buffers into the kernel. TCP silently splits these buffers into many packets, and UDP fragments the resulting large datagrams at the IP layer. Unfortunately, RFC 4340 strongly discourages DCCP fragmentation, so neither of these solutions is viable for DCCP.

A partial solution is to give the receiving process a high priority using the UNIX "nice" command. If the process runs at high priority, it can do a pretty good job of emptying the kernel socket buffer.



Publications