python-ivi/python-vxi11

TCP Retransmissions happens in Linux connecting to older VXI-11 devices

Opened this issue · 0 comments

I don't think it is really an issue, but I think it will make the application better than before.
I was working with an old device (I think it was created around nineties) that has an VXI-11 TCP server on it. I was trying to communicate with this device using both a Linux(Ubuntu 14,04) and a Windows machine. In the Windows machine, the communication was successful but on the Linux side it was not. In the Linux client, there was a lot of re-transmission and the calls started to become even more delayed because the way Linux deal with TCP protocol. I figured out it using Wireshark and analyzing the packets. After a while breaking my head on it, I figured out a solution.
In Linux we have a TCP feature called TCP_QUICKACK that is used to send out acknowledgements as early as possible than delayed under some protocol level exchanging, and it's not stable/permanent, subsequent TCP transactions. This feature was causing a lot of double ACK in the TCP communication because the device I was using can not deal with this quick ack packets. What I did to temporally fix the problem was disabling the socket TCP_QUICKACK in the socket properties in my application, but I think it would be more elegant and correct if we could add this option in the python-vxi11 library. I am running out of time so I forked the project and I will make a commit with this new option as soon as I get some time. If you guys have some better ideas than mine, I would be very grateful to listen from you. Thank you a lot.

Following is what I did to make my application work without changing anything on the python-vxi11 library. It is important to say that TCP_QUICKACK is restarted every socket send and recv command, so it has to be changed every time we send a command:

#!/usr/bin/python

import socket
import vxi11

def generateSocketSendAllWithoutTcpQuickAck(oldSocketSendAll, *args, **kwargs):
    def newSocketSendAll(*args, **kwargs):
        args[0].setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 0)
        oldSocketSendAll(*args, **kwargs)
    return newSocketSendAll

socket.socket.sendall = generateSocketSendAllWithoutTcpQuickAck(socket.socket.sendall)

oldDevice = vxi11.Instrument("192.168.170.33")

oldDevice.open()

answer = oldDevice.ask("*IDN?\n\r")

print "Version of Device: " + answer

oldDevice.close()