[go: up one dir, main page]

|
|
Log in / Subscribe / Register

SOCK_DESTROY: an old Android patch aims upstream

By Jonathan Corbet
December 2, 2015
TCP is a patient protocol; if a remote peer stops responding, it will wait a long time (measured in minutes, by default) in the hope that connectivity will eventually return. Sometimes, however, that wait is undesirable; that is especially true when it is known that the connection will not be coming back, but that the establishment of a replacement connection may succeed. As it happens, mobile networking often presents such situations. The SOCK_DESTROY patch set from Lorenzo Colitti is an attempt to improve the user experience in such situations. It fills a clear need, but has run into some opposition anyway; it also shows that the rift between the Android and kernel projects has not yet been entirely closed.

Imagine, for a moment, a user streaming $SPORTING_EVENT on a phone handset over a WiFi connection. Said user walks out the door, away from the WiFi network's coverage; that will cause the stream to freeze, probably at the beginning of the bit of action that decides the entire game. The WiFi connection is gone and is not coming back, but the streaming application does not know that, so it will wait a long time, in vain, for data to show up on its network socket. After several minutes, the connection will time out. The application will then realize that it has been disconnected and will try to reconnect; that new connection, going over the phone's broadband interface, will succeed. Streaming recommences, and our poor user gets to watch the post-game sportscasters talking about the one-of-a-kind play that happened while the stream was frozen. The resulting handset-destroying rage could have been avoided if the application had not waited for the network timeout to occur.

There are other scenarios that can create similar problems; placing a system onto a virtual private network (VPN) is another example. When this kind of network change occurs, things would work better if applications knew immediately that their open connection was never going to produce another packet. There are a number of ways this information could be conveyed, but one of the more straightforward ways would be to simply close the socket, returning an error to the application. That is what the SOCK_DESTROY patch set makes possible.

In particular, it adds a SOCK_DESTROY to the netlink-based "socket diag" mechanism, first added to the kernel in the 3.10 development cycle. A suitably privileged process (CAP_NET_ADMIN is required) can use this operation to close an arbitrary socket owned by another process; that process will see an ETIMEDOUT error. As it happens, that error is the same that is returned when a socket times out, but the pain of actually waiting for the timeout has been taken away. Any application that is prepared for such errors (and applications running in mobile environments, at least, should be) should recover and reconnect with no changes required.

As it happens, the Android kernel has had this capability since 2008, though in a different form: Android currently supports an ioctl() command called SIOCKILLADDR. This patch set is an attempt to move this capability upstream, cleaning it up a bit along the way. The fact that this feature has been shipped with Android suggests that there is a real need for it, but a number of concerns were raised anyway.

Tom Herbert worried that this facility could be used by an administrator to close sockets for any reason and that the affected application would have no way to know that this had happened. He suggested that the error code returned could be changed to ENETRESET, so that an explicit action to close a socket would not be presented as if it were a passive timeout. A later version of the patch set changes the return code to ECONNABORTED, which was chosen to be compatible with what BSD systems do.

Hannes Frederic Sowa suggested that, in some cases, quickly closing a socket in this manner could cause old data to be delivered to the wrong socket. Networking maintainer David Miller agreed with that concern, and suggested an alternative: the closing of sockets could be handled by the operation that disconnects them from the network in the first place. So, for example, the removal of a route associated with a disappeared network could cause any sockets bound to that network to be closed. David made it clear that he wants to have the kernel, rather than user space, in charge of deciding which sockets should be closed.

The problem with that approach, according to Lorenzo, is that the kernel doesn't always have a way to know which sockets have been affected by a networking change. The VPN case, in particular, can muddy the waters considerably. Beyond that, it was pointed out that user space can also force sockets to be closed by killing applications directly or installing special firewall rules. The new operation just makes this kind of action easier to carry out. Lorenzo did, however, change the patch to send a reset (set the RST bit) to the peer when a socket is closed as a way of reducing the chances of protocol confusion.

Eric Dumazet came in with a request that the change be merged. He noted that: "Every time I make a change in linux TCP stack, this code breaks, and this a real pain because Android changes need to be carried over to vendors." Getting the SOCK_DESTROY patch merged would spare him the phone calls and allow him to get more work done on the rest of the networking code. He also noted that the commonly suggested alternative of having applications do their own keep-alive processing is not really viable in the mobile environment for a couple of reasons.

Finally, Eric pointed out that TCP is competing with the QUIC protocol in the mobile space. QUIC is based on UDP and can react quickly to changes in the networking environment; without a similar ability to react, he said, TCP is not competitive.

David then complained that the Android developers still do not really care about the upstream kernel — a complaint that your editor still occasionally hears over beer at conferences. The fact that Android has been carrying this patch for something like seven years does not, in his mind, constitute a reason to merge it quickly into the mainline. Indeed, he said, Android's developers should be prepared to wait for a while as the patch's merits are considered:

You have been considering this non-stop for whatever time you have been working on this, everyone else is now considering and thinking about this for the first time right now. Therefore you must be understanding and patient. Just like I've been patiently waiting for my Nexus 6 to be updated to something newer than 2+ year old kernel technology.

Lorenzo responded that he would like to see things change in this area, with more Android code going upstream. The posting of the SOCK_DESTROY patch set was a part of the effort to bring that about. Almost everything that the Android networking group has done in the last two years has been sent upstream, he said.

As was recently discussed at the 2015 Kernel Summit, Android-based devices run a lot of out-of-tree code; indeed, they may be running more out-of-tree code than upstream code. The portion of that code contained within the Android project's repositories is relatively low, though, and there does appear to have been an effort to reduce it in recent years. But it's clear that some resentment remains in the kernel development community. In the end, though, that resentment is unlikely to prevent the merging of needed functionality. By the time it gets upstream, this feature may or may not look like SOCK_DESTROY, but it can be expected to do something similar. Mobile devices are not going away and the kernel community, in the end, wants to support them as well as possible.

Index entries for this article
KernelNetworking


to post comments

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 3, 2015 2:11 UTC (Thu) by luto (subscriber, #39314) [Link] (5 responses)

Yes, please! Windows has been able to do this for a *long* time, and it's great as a way to work around application bugs.

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 3, 2015 6:50 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (4 responses)

Except that it's mandatory in Windows. Which is less nice when you actually _want_ this behavior.

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 3, 2015 21:19 UTC (Thu) by luto (subscriber, #39314) [Link] (3 responses)

No, I mean that Windows has had an interface that allowed a suitably privleged application to explicitly kill individual TCP connections. It's not mandatory to use it.

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 3, 2015 22:03 UTC (Thu) by Cyberax (✭ supporter ✭, #52523) [Link] (2 responses)

Windows has another issue - if a network interface goes down then all the connections for this interface go down as well and you can't override it.

This is extremely annoying if you want, for example, to switch from wired to wireless connection (and your router is set up to assign the same IP to both).

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 4, 2015 14:19 UTC (Fri) by mstone_ (subscriber, #66309) [Link]

That annoys the hell out of me every time it happens

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 11, 2015 4:36 UTC (Fri) by toyotabedzrock (guest, #88005) [Link]

And what happens if you move from wireless to wired without turning off wireless? Not to mention your Mac changes which will confuse some routers.

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 7, 2015 0:57 UTC (Mon) by ras (subscriber, #33059) [Link] (2 responses)

> The problem with that approach, according to Lorenzo, is that the kernel doesn't always have a way to know which sockets have been affected by a networking change.

Since TCP is bound to a source IP address that would have to be pretty rare.

To me the issue is even if the kernel does know the interface the TCP connection runs over has gone down, at least for me it's nice if it doesn't destroy it immediately. Having your ssh connection stay up when there is a glitch in connectivity can be a real bonus, to the extent that I turn off keep-alives to ensure ssh doesn't notice. So changing kernel behaviour to unconditionally kill all TCP connections doesn't sound wonderful.

On the other hand, having a user space application that allows me to kill some sockets matching some criteria (IP address, interface or whatever) would be nice. Providing the functionality effectively pushes the policy into userspace, which is surely where it belongs.

SOCK_DESTROY: an old Android patch aims upstream

Posted Jan 14, 2016 12:22 UTC (Thu) by RobSeace (subscriber, #4435) [Link] (1 responses)

On the other hand, having a user space application that allows me to kill some sockets matching some criteria (IP address, interface or whatever) would be nice.

Dug Song's dsniff package of tools contains a nifty little app called "tcpkill" which can do this (the criteria specified via tcpdump-style BPF rules)... It just forges RSTs, so a nicer method like this would still be useful, but I just wanted to mention this tool, because it can sometimes be useful...

SOCK_DESTROY: an old Android patch aims upstream

Posted Mar 14, 2016 14:52 UTC (Mon) by federico3 (guest, #101963) [Link]

kcpkill works only if there is some traffic to be captured (and if so, you have to wait for such traffic to appear)

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 11, 2015 4:34 UTC (Fri) by toyotabedzrock (guest, #88005) [Link] (1 responses)

Given they are both using Android can their respective phones be hacked and programed to shock them until they work together better?

SOCK_DESTROY: an old Android patch aims upstream

Posted Dec 12, 2015 8:25 UTC (Sat) by scientes (guest, #83068) [Link]

> shock them

I know phones have been adding more and more gadgets (barometer anyone?) but this is new.


Copyright © 2015, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds