very low throughput on Mac OS X

Tom Rodriguez tom.rodriguez at oracle.com
Thu Aug 18 10:13:59 PDT 2016


> On Aug 18, 2016, at 2:58 AM, David Woodhouse <dwmw2 at infradead.org> wrote:
> 
> On Wed, 2016-08-17 at 09:26 -0700, Tom Rodriguez wrote:
>>> I’ve been using open connect on Mac OS X and noticed that I’m
>> getting much worse throughput than the same setup running on linux on
>> a local virtual machine.  Almost an order of magnitude worse.  I’ve
>> googled for help on the issue but without any luck, so here I am.  
> 
> Under Linux I'd be pointing you at the profiling tools so you can see
> precisely where the *system* is spending its time.
> 
> For OS X I am unfamiliar with any such tools. One thing which comes to
> mind is the different tun devices. We'll be using utun on OS X these
> days by default... does it get better if you install the Tun/Tap driver
> and use that instead? There's plenty of scope for screwing performance
> up in the user/kernel interface...
> 
> 
>> I’ve tried a few different command line options and adjusting the MTU
>> but without luck.  Are there any known issues concerning this?  I do
>> get a lot of "Failed to write incoming packet: No buffer space
>> available” on the mac but it didn’t seem like enough to explain the
>> low throughput. 
> 
> That's on receiving a packet from the VPN, and feeding it to the kernel
> through (presumably) the utun interface. Which tends to support my
> first supposition above…

I’m actually using ocproxy to handle the traffic so I don’t think I’m going through the tunnel device.  So does that mean the packets are being lost on the datagram socket connecting me to ocproxy?  My actual command line is this:

openconnect -q --compression=none --script-tun --script "ocproxy -D 9998”  <host>

Maybe buffering in the unix socket talking to ocproxy is to blame?  In the output below  fd 9 is the UDP connection to the VPN and 8 is one half of the unix socket talking to ocproxy.

select(0xA, 0x7FFF50ABFDE0, 0x7FFF50ABFD60, 0x7FFF50ABFCE0, 0x7FFF50ABFE60)		 = 1 0
recvfrom(0x9, 0x7FC8BD800053, 0x495C)		 = 1117 0
recvfrom(0x9, 0x7FC8BD804A53, 0x495C)		 = 1117 0
recvfrom(0x9, 0x7FC8BD800053, 0x495C)		 = 1117 0
recvfrom(0x9, 0x7FC8BD804A53, 0x495C)		 = 1117 0
recvfrom(0x9, 0x7FC8BD800053, 0x495C)		 = 1117 0
recvfrom(0x9, 0x7FC8BD804A53, 0x495C)		 = -1 Err#35
recvfrom(0x6, 0x7FC8BD804A5B, 0x5)		 = -1 Err#35
read(0x8, "\0", 0x514)		 = -1 Err#35
write(0x8, "E\0", 0x428)		 = 1064 0
write(0x8, "E\0", 0x428)		 = 1064 0
write(0x8, "E\0", 0x428)		 = 1064 0
write(0x8, "E\0", 0x428)		 = 1064 0
write(0x8, "\0", 0x428)		 = -1 Err#55
write_nocancel(0x2, "Failed to write incoming packet: No buffer space available\n\0", 0x3B)		 = 59 0

Some googling led me to net.local.dgram.recvspace to tune the buffer space for unix domain sockets.  Running this:

sudo sysctl -w net.local.dgram.recvspace=82320

brought my mac performance back up.  The default value of that tunable is 8192 which I guess is too low.  Maybe setsockopt should be used to increase it on the Mac?  Presumably linux has a higher default which is why it works ok there.

tom

> 
> Note that we *drop* the packet when that happens. See the code at
> http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/tun.c#l551
> http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/mainloop.c#l95
> 
> So... the tun interface's queue is full and it stops accepting packets
> from us. We *drop* them, and that's going to screw your TCP connections
> up quite a lot.
> 
> In an ideal world, the poll() system call would let us know when the
> tun is writeable again, and we'd start shovelling packets then. In
> Linux that doesn't work so as the comments note, we don't bother with
> that. But perhaps we should, for OS X? You'd make os_write_tun()
> actually return -EAGAIN, and make mainlop.c react accordingly by
> calling monitor_write_fd() on the tun fd and only ever trying to write
> to it when it's... well, writeable.
> 
> And we'd still need a hack for Linux so that we don't just busy-wait
> trying to write the same packet over and over again until it's
> accepted. But first check if the utun interface really *does* support
> poll() for writeability at all, perhaps...
> 
> -- 
> dwmw2




More information about the openconnect-devel mailing list