=====Contents=====
* [[https://www.linuxfoundation.org/#Datagram_Congestion_Control_Protocol|1 Datagram Congestion Control Protocol]]
* [[https://www.linuxfoundation.org/#DCCP_stack_for_Linux|1.1 DCCP stack for Linux]]
* [[https://www.linuxfoundation.org/#Experimental_Work|1.1.1 Experimental Work]]
* [[https://www.linuxfoundation.org/#Choosing_and_initialising_your_CCID|1.2 Choosing and initialising your CCID]]
* [[https://www.linuxfoundation.org/#Applications|1.3 Applications]]
* [[https://www.linuxfoundation.org/#tcpdump_support|1.3.1 tcpdump support]]
* [[https://www.linuxfoundation.org/#ethereal.2Fwireshark_support|1.3.2 ethereal/wireshark support]]
* [[https://www.linuxfoundation.org/#iperf__support|1.3.3 iperf support]]
* [[https://www.linuxfoundation.org/#GStreamer|1.3.4 DCCP Plugin for GStreamer]]
* [[https://www.linuxfoundation.org/#D-ITG|1.3.5 D-ITG]]
* [[https://www.linuxfoundation.org/#netcat_support|1.3.6 netcat support]]
* [[https://www.linuxfoundation.org/#Python_support|1.3.7 Python support]]
* [[https://www.linuxfoundation.org/#Ruby_support|1.3.8 Ruby support]]
* [[https://www.linuxfoundation.org/#PHP|1.3.9 PHP]]
* [[https://www.linuxfoundation.org/#C_Application_Programming_Interface_to_DCCP|1.3.10 C Application Programming Interface to DCCP]]
* [[https://www.linuxfoundation.org/#Some_Important_Details|1.3.9.1 Some Important Details]]
* [[https://www.linuxfoundation.org/#Other_applications|1.3.11 Other applications]]
* [[https://www.linuxfoundation.org/#TIMEWAIT_sockets|1.4 TIMEWAIT sockets]]
* [[https://www.linuxfoundation.org/#Mailing_List_Archives|1.5 Mailing List Archives]]
* [[https://www.linuxfoundation.org/#TODO_.26_testing|1.6 TODO & testing]]
* [[https://www.linuxfoundation.org/#FAQ|1.7 FAQ]]
* [[https://www.linuxfoundation.org/#IRC|1.8 IRC]]
====== Datagram Congestion Control Protocol ======
This site was derived from [[http://wlug.org.nz/DCCP|http://wlug.org.nz/DCCP]] but this is now the master site for the DCCP implementation for Linux.
DCCP is a transport level protocol (like [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP]] and [[http://en.wikipedia.com/wiki/User_Datagram_Protocol|UDP]]) which aims to solve many different congestion issues. This is useful for applications that don't need the data reliability/re-transmission of [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP]], but want a session and want congestion control unlike [[http://en.wikipedia.com/wiki/User_Datagram_Protocol|UDP]].
DCCP is currently at proposed standard [[http://en.wikipedia.com/wiki/Request_for_Comments|RFC]] status (4340-4342).
[[http://www.ietf.org/html.charters/dccp-charter.html|The main reference page on the web for DCCP]].
There is also a [[http://lwn.net/Articles/149756/|writeup at LWN]].
DCCP stack for Linux
There is a [[http://en.wikipedia.com/wiki/GPL|GPL]] version of DCCP in the [[http://en.wikipedia.com/wiki/Linux_Kernel|Linux Kernel]]. This is being maintained by [[http://oops.ghostprotocols.net:81/blog|Arnaldo C. Melo]] at present. The history of this is that it draws from the code of Patrick McManus, Lulea and the [[http://www.wand.net.nz/|WAND]] group that [[http://blog.next-genit.co.uk|Ian McDonald]] is part of.
The core DCCP stack was written by [[http://oops.ghostprotocols.net:81/blog|Arnaldo C. Melo]] using the Linux [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP]] implementation as a model, with DCCP being used as a way to identify code in the [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP]] implementation that could be made generic and shared with other INET transport level implementations. This resulted in the generalisation of code related to the minisockets representing both TCP_SYN_RECV/DCCP_RESPOND and TCP_TIME_WAIT/DCCP_TIME_WAIT status, code related to established/timewait/listen sockets (inet_lookup, inet_lookup_established, etc), the interface to get sock information (tcp_diag), and many other functions and data structures, with more expected to be generalised and eventually used by [[http://en.wikipedia.com/wiki/SCTP|SCTP]] and any other INET transport protocols that may be introduced in the future.
The [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]]3 code was drawn from the [[http://www.wand.net.nz/|WAND group]], that in turn got it initially from the [[http://www.freebsd.dccp.org/|Lulea FreeBSD codebase]] and made it work in the core DCCP stack written by Patrick McManus. Ian McDonald got it relicensed from BSD license to GPL by getting written permission via email from the original Lulea authors of the code. It was modified by [[http://oops.ghostprotocols.net:81/blog|Arnaldo C. Melo]] to fit Linux standards wrt list handling and several other aspects. Since then Gerrit Renker and Ian McDonald have spent a lot of time improving [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]]3.
The [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]]4 code was drawn from the [[http://www.embeddedlab.org/|Embedded Laboratory]], by Leandro Melo de Sales, Ivo Calado and Erivaldo Xavier, that in turn got it initially from the CCID 3 and made it work in the core DCCP stack, adding the differences for CCID4 available in the [[http://www.ietf.org/rfc/rfc5622.txt|RFC 5622]]. The CCID 4 can be considered to be a working in progress implementation, while now Gerrit Renker has been also provide efforts on the implementation of CCID 4.
The [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]] 5/249 code was drawn from the [[http://www.embeddedlab.org/|Embedded Laboratory]], by Ivo Calado and Leandro Melo de Sales. This CCID implements the Cubic congestion control in a attempt to achieve similar performance of TCP Cubic in long fat network. The code is based on a mix of TCP-Cubic and CCID-2 implementations. The CCID 5/249 can be considered to be a working in progress implementation.
\\
The [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]] modular infrastructure was written to fit the [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]]3 existing interface, but will probably be changed in the near future in the effort to have a generic CA (Congestion Avoidance) infrastructure shared with [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP | CCID ]] (and others, who knows), continuing work on the existing [[http://en.wikipedia.com/wiki/Transmission_Control_Protocol|TCP | CCID ]] CA infrastructure put in place by Stephen Hemminger.
To have a look at the theoretical performance of [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| CCID ]]3 see [[http://wand.net.nz/~iam4/dccp/xcalc.sxc|xcalc spreadsheet]] - the codebase currently assumes s=256, unless you override with an option.
There is a mailing list for DCCP work which is dccp at vger dot kernel dot org. Discussion also occurs on the main Linux networking mailing list - netdev at vger dot kernel dot org.
Experimental Work
Andrea Bittau is experimenting with wiring the TCP plugabble congestion control to DCCP, graphs can be seen [[http://darkircop.org/dccp/tcp/|here]].
Gerrit Renker is fixing up the CCID3 implementation and his notes can be found [[http://www.erg.abdn.ac.uk/users/gerrit/dccp/|here]]
At present Gerrit's tree has a substantial number of improvements and is where most work should be done. Details of using this can be found at [[https://www.linuxfoundation.org/collaborate/workgroups/networking/dccp_testing#experimental_dccp_source_tree| DCCP_Testing#Experimental_DCCP_source_tree ]]
Choosing and initialising your CCID
To use CCID2 do something like:
sudo modprobe dccp
sudo modprobe dccp_ccid2
sudo sysctl -w net.dccp.default.seq_window=10000
sudo sysctl -w net.dccp.default.rx_ccid=2
sudo sysctl -w net.dccp.default.tx_ccid=2
To use CCID3 do something like:
sudo modprobe dccp
sudo modprobe dccp_ccid3
sudo sysctl -w net.dccp.default.seq_window=10000
sudo sysctl -w net.dccp.default.rx_ccid=3
sudo sysctl -w net.dccp.default.tx_ccid=3
The seq_window increases the sequence window validation from the default of 100 which can cause problems. send_ackvec sets the appropriate setting for the CCID. This should be fixed so it defaults correctly really.
Applications
tcpdump support
[[http://www.tcpdump.org|tcpdump]] now has DCCP support in the tree. There is tcpdump support available at [[http://wand.cs.waikato.ac.nz/~iam4/dccp/tcpdump8.diff|here]] for older versions. This applies to many versions and at least the weekly build from CVS of tcpdump dated 22nd August 2005. This is in the process of being tidied up for submission to tcpdump maintainers. Remember to run tcpdump(8) with a -s0 parameter to capture all data (or some other value) as the default size gets the base DCCP header, but not the options, in many cases. Also, if you want to capture only DCCP traffic, you can use the primitive ip[9] == 33 in the filter expression.
==== ethereal/wireshark support ====
See [[http://www.jp.nishida.org/dccp/|here]]
Latest version of Wireshark seems to work just fine with DCCP.
[[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| iperf ]] support
There is a patch for DCCP available on the [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| iperf ]] page.
====GStreamer support====
GStreamer is a library for constructing graphs of media-handling components. The applications it supports range from simple Ogg/Vorbis playback, audio/video streaming to complex audio (mixing) and video (non-linear editing) processing. Applications can take advantage of advances in codec and filter technology transparently. Developers can add new codecs and filters by writing a simple plugin with a clean, generic interface. For more about gstreamer go to [[http://www.gstreamer.net/|GStreamer.net]]
* [[http://www.gstreamer.net/data/doc/gstreamer/head/gst-plugins-bad-plugins/html/gst-plugins-bad-plugins-plugin-dccp.html|Documentation about DCCP on GStreamer]]
* [[http://www.linux-magazine.com/content/view/full/36244/%28offset%29/3|Article: DCCP Plugin for GStreamer @ Linux Magazine]]
[[https://www.linuxfoundation.org/collaborate/workgroups/networking/d-itg| D-ITG ]]
D-ITG supports DCCP. It is available on the [[https://www.linuxfoundation.org/collaborate/workgroups/networking/d-itg| D-ITG ]] page.
netcat support
A patch for [[http://netcat.sf.net|netcat]] is available [[http://oops.ghostprotocols.net:81/dccp/netcat-0.7.1.dccp.patch|here]] or [[http://wand.net.nz/~iam4/dccp/netcat-0.7.1.dccp.patch|here]]. The version of netcat that this is used against is 0.71 and was used on 8th September for, what we believe to be, the first public transmission of DCCP over the Internet.
The above patch doesn't handle service codes and Guillaume Teissier has modified the patch to do this. At some point it will be merged with the original or the original deleted but this new patch can be found at [[http://wand.net.nz/~iam4/dccp/netcat-0.7.1.complete.patch|http://wand.net.nz/~iam4/dccp/netcat-0.7.1.complete.patch]]
Python support
[[http://www.python.org|Python's]] low level socket library is transparent enough to support DCCP without even knowing it! Here is an //adaptation// of the [[http://wand.net.nz/~iam4/dccp/dccp-cs-0.01.tar.bz2|http://wand.net.nz/~iam4/dccp/dccp-cs-0.01.tar.bz2]] example code:
#!/usr/bin/python
import socket
socket.DCCP_SOCKOPT_PACKET_SIZE = 1
socket.DCCP_SOCKOPT_SERVICE = 2
socket.SOCK_DCCP = 6
socket.IPPROTO_DCCP = 33
socket.SOL_DCCP = 269
packet_size = 256
address = (socket.gethostname(),12345)
# Create sockets
server,client = [socket.socket(socket.AF_INET, socket.SOCK_DCCP,
socket.IPPROTO_DCCP) for i in range(2)]
for s in (server,client):
s.setsockopt(socket.SOL_DCCP, socket.DCCP_SOCKOPT_PACKET_SIZE, packet_size)
s.setsockopt(socket.SOL_DCCP, socket.DCCP_SOCKOPT_SERVICE, True)
# Connect sockets
server.bind(address)
server.listen(1)
client.connect(address)
s,a = server.accept()
# Echo
while True:
client.send(raw_input("IN: "))
print "OUT:", s.recv(1024)
Ruby support
[[http://www.ruby-lang.org/|Ruby's]] low level socket library is also able to support DCCP. Here is the corresponding Ruby code to the previous Python script :
#!/usr/bin/ruby
require 'socket'
class Socket
DCCP_SOCKOPT_PACKET_SIZE = 1
DCCP_SOCKOPT_SERVICE = 2
SOCK_DCCP = 6
IPPROTO_DCCP = 33
SOL_DCCP = 269
end
packet_size = 256
address = [12345,'localhost']
# Create sockets
server = Socket.new(Socket::AF_INET, Socket::SOCK_DCCP, Socket::IPPROTO_DCCP)
client = Socket.new(Socket::AF_INET, Socket::SOCK_DCCP, Socket::IPPROTO_DCCP)
[server,client].each do |s|
s.setsockopt(Socket::SOL_DCCP, Socket::DCCP_SOCKOPT_PACKET_SIZE, packet_size)
s.setsockopt(Socket::SOL_DCCP, Socket::DCCP_SOCKOPT_SERVICE, true)
end
# Connect sockets
sockaddr = Socket.pack_sockaddr_in(*address)
server.bind(sockaddr)
server.listen(1)
client.connect(sockaddr)
s,a = server.accept
# Send/receive stuff
client.send('tartine',0)
p s.recv(10)
PHP
[[http://www.php.org/|PHP's]] low level socket library is also able to support DCCP. Here is the corresponding Python and Ruby code of the previous scripts:
Server:
#!/usr/bin/php
$SOCK_DCCP = 6
$IPPROTO_DCCP = 33
$bind_address = "192.168.1.1";
$port = 9011;
// Connect sockets
$server_socket_fd = socket_create(AF_INET, $SOCK_DCCP, $IPPROTO_DCCP);
socket_bind ($server_socket_fd, $bind_address, $port);
socket_listen($server_socket_fd);
$client_socket_fd = socket_accept($server_socket_fd);
$recv = socket_read($client_socket_fd, 11);
echo $recv;
socket_close($server_socket_fd);
Client:
#!/usr/bin/php
$bind_address = "192.168.1.1";
$port = 9011;
$client_socket_fd = socket_create(AF_INET, $SOCK_DCCP, $IPPROTO_DCCP);
$message = "Hello world";
if (socket_connect ($client_socket_fd, $bind_address, $port)) {
socket_send($client_socket_fd, $message, strlen($message), 0);
}
socket_close($client_socket_fd);
C Application Programming Interface to DCCP
DCCP's implementation on Linux is based on the TCP implementation. The API provided is through the [[http://linux.die.net/man/7/socket|linux //socket// library]] and so, much of the code looks similar to initialization/send/receive code of a regular TCP socket. The server initializes a socket, binds it to a port, and waits to accept clients to connect. The client initializes a socket and connects to the server. Note that although the connection setup of DCCP is like TCP, transmission of data is unreliable like UDP.
Here's how to get started: There are some general //#includes// and //#defines// needed by both client and server. These are:
//----------------------------//
//General defines and includes needed
#include
#include
#define SOCK_DCCP 6
#define IPPROTO_DCCP 33 //it must be this number. This number is assigned by IANA to DCCP
#define SOL_DCCP 269
#define MAX_DCCP_CONNECTION_BACK_LOG 5
//----------------------------//
A DCCP server is much like a TCP server. The code for initializing, binding and accepting sockets is shown below. Note that the code for getting the local IP is not shown. Read [[http://sage.mc.yu.edu/kbeen/teaching/networking/resources/sockets.html|Brief Socket Tutorial]] for linux //socket// basics.
//----------------------------//
//DCCP Server inititialization
//get a socket handle just like TCP Server
int mSocketHandle = socket(PF_INET, SOCK_DCCP, IPPROTO_DCCP);
//turn off bind address checking, and allow port numbers to be reused - otherwise
// the TIME_WAIT phenomenon will prevent binding to these address.port combinations for (2 * MSL) seconds.
int on = 1;
int result = setsockopt(mSocketHandle, SOL_DCCP, SO_REUSEADDR, (const char *) &on, sizeof(on));
//bind the socket to the local address and port. mLocalName is sockaddr of local IP and port
result = bind(mSocketHandle, (struct sockaddr *)&mLocalName, sizeof(mLocalName));
//listen on that port for incoming connections
result = listen(mSocketHandle, MAX_DCCP_CONNECTION_BACK_LOG);
//wait to accept a client connecting. When a client joins, mRemoteName and mRemoteLength are filled out by accept()
mClientSocketHandle = accept(mSocketHandle, (struct sockaddr *)&mRemoteName, &mRemoteLength);
//----------------------------//
A DCCP client is also much like a TCP client in that in connects to a remote server.
//----------------------------//
//DCCP Client initialization
//get a socket handle just like TCP Server
int mSocketHandle = socket(PF_INET, SOCK_DCCP, IPPROTO_DCCP);
//turn off bind address checking, and allow port numbers to be reused - otherwise
// the TIME_WAIT phenomenon will prevent binding to these address.port combinations for (2 * MSL) seconds.
int on = 1;
int result = setsockopt(mSocketHandle, SOL_DCCP, SO_REUSEADDR, (const char *) &on, sizeof(on));
//connect to remote server: mRemoteName is sockaddr containing remote server IP address and port
result = connect(mSocketHandle, (struct sockaddr *)&mRemoteName, sizeof(mRemoteName));
//----------------------------//
Once the connection has been set up (client successfully connected to server and server got a valid socket for the client), they can exchange data. Take a look at the send routine and notice the checking for //errno//. This is because DCCP's congestion control can refuse to send a packet.
//----------------------------//
//DCCP client sends message to server
char sendbuffer[100];
int status;
do
{
status = send(mSocketHandle, sendbuffer, 100, 0);
}
while((status<0)&&(errno == EAGAIN));
//Note here the while loop tries to catch the errno
//DCCP's congestion control algorithm might result in
//data not being sent since congestion window is full (true?)
//in which case it sets errno to EAGAIN
The receive routine is simple.
//----------------------------//
//DCCP server receives the client's message
char receive_buff[100];
int rec_size = recv(mClientSocketHandle, receive_buff, 100, 0);
=== Some Important Details ===
1. //How do you know which congestion control algorithm is being used?//
By default, it should be CCID2 which is a TCP-like congestion control but you can make sure by typing this in a console:
sysctl -a | grep dccp
This should give you something like:
net.dccp.default.tx_qlen = 5
net.dccp.default.retries2 = 15
net.dccp.default.retries1 = 3
net.dccp.default.request_retries = 5
net.dccp.default.send_ndp = 1
net.dccp.default.send_ackvec = 0
net.dccp.default.ack_ratio = 2
net.dccp.default.tx_ccid = 2
net.dccp.default.rx_ccid = 2
net.dccp.default.seq_window = 100
which means that both the outgoing and incoming congestion control mechanisms are CCID2
2. //What if I want to change the congestion control algorithm to CCID3?//
See **Choosing and initialising your CCID ** above. Newer revisions of DCCP allow for setting of CCID through //setsockop()// functions of socket.
3. //Current implementation of DCCP on linux does NOT support packet fragmentation//
This means that if the packet you are sending over DCCP is greater than your //Maximum Transmission Unit// (MTU) it will not be sent! For example, if you call the send() routine with a size of 30000, chances are the packet will not be sent So you must take care to packetize your packets in sizes that are smaller than the MTU and still leave room for IP header (20 bytes) and DCCP header (32 bytes). packet size of about 1400 bytes is recommended [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| BR ]]
Other applications
More info on apps can be found at [[http://www.erg.abdn.ac.uk/users/gerrit/dccp/apps/|Gerrit's page]] or [[http://wand.net.nz/~iam4/dccp/|Ian's page]].
TIMEWAIT sockets
TIMEWAIT sockets are finally implemented and we have initial support for iproute2, so just enable INET_DIAG and if enabled as a module make sure it is load prior to using the [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| iproute2 ]] utilities, like ss.
The latest [[https://www.linuxfoundation.org/node/add/wiki?gids[]=5066| iproute2 ]] version now includes DCCP support directly.
Then use it:
[root@qemu ~]# ./ss -dane
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 0 *:5001 *:* ino:730 sk:cfd503a0
ESTAB 0 0 127.0.0.1:5001 127.0.0.1:32770 ino:731 sk:cfd51480
ESTAB 0 0 127.0.0.1:32770 127.0.0.1:5001 ino:741 sk:cfd517e0
[root@qemu ~]#
[root@qemu ~]# ./ss -dane
State Recv-Q Send-Q Local Address:Port Peer Address:Port
TIME-WAIT 0 0 127.0.0.1:32770 127.0.0.1:5001 timer:(timewait,59sec,0)
ino:0 sk:cf12a620
The above listing was with the ttcp test.
Mailing List Archives
[[http://www1.ietf.org/mail-archive/web/dccp/current/index.html|DCCP@IETF]] - A discussion of the DCCP protocol by the IETF
[[http://www.mail-archive.com/dccp@vger.kernel.org/|dccp@vger.kernel.org]] - a discussion of the Linux implementation of DCCP
[[http://osdir.com/ml/dccp@vger.kernel.org/|dccp@vger.kernel.org]] - Another archive for the DCCP@vger mailing list
===== TODO & testing =====
There is a [[:networking:todo| TODO ]] list also which tracks the issues needing working on.
There is a [[:networking:dccp_testing| DCCP Testing ]] page which also talks about how to test in ** DCCP Testing **.
FAQ
Q: Why do I get an errno 13 (EACCES) or permission denied?\\
A: You are running SELinux that does not have DCCP support. Disable SELinux or upgrade to a newer version of the kernel.
Q: Why do I get an errno 90 (EMSGSIZE) or Message too long?\\
A: The packet size used is bigger than the PMTU.
The initial idea was to set the packet size option, similar to the example below, but this option became deprecated.
void dccp_set_packet_size(int sock, int new_size)
{
/* This option is deprecated, DON'T USE THIS! */
return setsockopt(sock, SOL_DCCP, DCCP_SOCKOPT_PACKET_SIZE,
&new_size, sizeof(new_size));
}
Instead, you can get the current PMTU value, as shown below, and in your application you implement your sending mechanism filling the packets considering the mpu size:
int dccp_get_mtu_size(int sock, int new_size)
{
int mtu_size;
int ret = getsockopt(sock_fd, SOL_DCCP, DCCP_SOCKOPT_GET_CUR_MPS,
&mtu_size, sizeof(mtu_size));
return mtu_size;
}
...
Then use the dccp_get_mtu_size function to retrieve the mtu size and implement your sending mechanism considering this value.
IRC
server: irc.freenode.net\\
channel: #dccp-linux