SOCK_DESTROY: an old Android patch aims upstream
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:
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 | |
|---|---|
| Kernel | Networking |