Using TCP-LP with pycurl in Python

Intro

TCP-LP (low priority) is a TCP congestion control algorithm that is meant to be used by TCP connections that don’t want to compete with other connections for bandwidth. Its goal is to use the idle bandwidth for file transfers. The details of TCP-LP are here.

With Linux’ plugable congestion control algorithms, it is possible to change both the default algorithm for the whole system and the one used per connection. For the latter, one needs to be root.

Note: Changing the CC algorithm will only affect the transmissions. You cannot alter the remote end’s behavior. This means that the below only make sense when you are going to upload data.

PyCurl

Changing the CC algorithm is a matter of using setsockopt on a socket. Doing this with pycurl can be a bit tricky. Even though pycurl supports the SOCKOPTFUNCTION, this is only for newer pycurl versions. For older, one can exploit pycurl’s OPENSOCKETFUNCTION instead.

The trick is done with this piece of code:

import pycurl
import socket

def _getsock(family, socktype, protocol, addr):
    s=socket.socket(family, socktype, protocol)
    s.setsockopt(socket.IPPROTO_TCP, 13, 'lp' )
    return s

c = pycurl.Curl()
c.setopt(c.OPENSOCKETFUNCTION, _getsock)
c.setopt(c.URL, 'http://127.0.0.1/')
c.perform()
c.close()

In the above, pycurl will call _getsock and expect it to return a socket. The function creates a new socket, then calls setsockopt with IPPPROTO_TCP and 13 (which is TCP_CONGESTION – see /usr/include/linux/tcp.h,  /usr/include/netinet/tcp.h). It then attempts to set the algorithm to “lp” which is the TCP-LP congestion control algorithm.

You most probably want to wrap the setsockopt around a try/except clause as it may fail if “lp” is not available (needs the module tcp_lp loaded) or if the program doesn’t run as root.

The _getsock function also depends on the pycurl version, as its arguments have changed over time. Consult the docs for the fine details.

Results

Example of uploading two 500MB files in parallel on an already busy production network. One is with TCP-LP and the other with the default (TCP Cubic):

TCP-Cubic: 9.38 seconds
TCP-LP: 23.08 seconds

Same test, for 100MB files, again in parallel, on the same network:

TCP-Cubic: 3.14 seconds
TCP-LP: 5.38 seconds

Note: The above are random runs, presented to give an idea of the impact. For actual experimental results we would need to have  multiple runs and also monitor the background traffic.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.