
Lying to TCP makes it a best-effort streaming protocol - tonyg
https://eighty-twenty.org/2018/02/01/lying-to-tcp
======
lumisota
It’s been shown that leaving holes in the sequence space isn’t good for
middleboxes [0]. Wanting TCP to behave more like UDP is a reasonable goal
(e.g., for reachability), but you throw the benefits away if 20% of
connections are disrupted by middleboxes. Other approaches, like Minion [1] or
TCP Hollywood [2], see deployability because they adhere to the assumptions
made about TCP by middleboxes.

[0]: “Is it Still Possible to Extend TCP?” -
[http://www0.cs.ucl.ac.uk/staff/ucacmha/papers/extend-
tcp.pdf](http://www0.cs.ucl.ac.uk/staff/ucacmha/papers/extend-tcp.pdf)

[1]: Minion - [https://tools.ietf.org/html/draft-iyengar-minion-
protocol-01](https://tools.ietf.org/html/draft-iyengar-minion-protocol-01)

[2]: TCP Hollywood -
[http://ieeexplore.ieee.org/document/7497221/](http://ieeexplore.ieee.org/document/7497221/)

~~~
bostonvaulter2
What are middleboxes? This is something that I've never heard of before.

~~~
staunch
Middlebox is a technically imprecise term that is not in common usage among
technical people anywhere. Why people in this thread are trotting it out is
anyone's guess.

~~~
dfox
Middlebox has quite precise technical meaning: anything that works at higher
layer than on which it is visible to neighboring network.

Usualy this refers to various "security" "solutions" which attempt to do deep
packet inspection and generally break various things, but it also can mean NAT
or L2 bridges that do filtering on L3/L4 headers (for example DOCSIS CMs and
CMTSes are such middleboxes)

------
kevin_nisbet
So this is an interesting idea, however, I suspect it may be quite problematic
on the receive side if implemented.

Once upon a time, I used to write network protocol sniffers. I basically
simulated a partial TCP stack, in order to allow higher layer protocols decode
traffic that was out of order. If a packet was lost in the capture, it's
basically the same thing as the "lying ack" in the article, where the real
endpoint would ack a frame the capture engine never saw.

This becomes really difficult to process, because TCP simulates a stream, and
if you lose a packet, and skip some bytes in the stream, where you pick up and
continue may not be the beginning of a new message. So you also need to create
heuristics, on how do you discard received data, until you get to a point
where you can understand the stream again, and continue processing.

As others have commented, UDP is likely a better choice here, as ordering
semantics can be added, but on packet loss, the next received packet can
always be parsed. Or look at SCTP, which allows turning on/off in order
deliver, and I believe through an extension allows turning on/off reliability
(but I'm not sure if this ever got implemented).

~~~
sly010
> This becomes really difficult to process, because TCP simulates a stream ...

The irony of TCP is that in almost every use case you end up creating "frames"
within the stream. Turtles all the way up I guess.

~~~
toast0
The frames inside your TCP stream are sized to your data, not to your physical
layer, this makes a huge difference in usability. The framing can also be as
simple or complex as you like.

~~~
dfox
Exposing TCP framing to the application at the receiver side does not make
much sense. On the other hand I'm somewhat puzzled by the fact that TLS
specifications explicitly discourage exposing TLS record boundaries to
applications which is exactly the case of turtles framed in turtles all the
way down.

Edit: we can all collectively make fun of telco protocols that are HDLC-in-
HDLC all the way down, but such things usually do framing only on the
outermost layer.

------
yarg
The problem here is that it fails to take into account why any packets might
be missing.

If it's due to congestion, you've just subverted the mechanism TCP uses to
relieve it - and the more people that are using the deviant implementation,
the bigger the problem becomes, which impacts everyone.

~~~
jrockway
I'm not convinced it matters in this case, lying only prevents the other end
from being extra-smart.

We'll stick with the VoIP example. Packets are going to be dropped
independently of any information in the TCP headers. If there's too much load,
some of them will disappear. If your client says "yeah I got that data" when
it didn't actually get the data, it doesn't increase load any more -- if
you're sending a real-time 256kbps audio stream, then you need to be able to
send 256,000 bits every second regardless of whether or not the network is
capable of that. By not retransmitting packets you don't care about, you're
decreasing load.

Of course, if you push the information all the way up the stack to the
application, you can do interesting things. You can notice that packets are
being dropped and switch to a codec that sounds worse but sends fewer bits per
second, and maybe you'll get a better quality call going on with fewer
dropouts.

Now that I think about it, I'm surprised this isn't how we deal with degrading
things over slow connections in general. I would much prefer to only get the
"mobile friendly" version of a page if I'm actually on a mobile connection.
Right now, the hueristic seems to be "if screen < desktop; send mobile page".
That of course is silly because my home WiFi can happily pipe huge images into
my phone faster than the web server can send them to me, while my 8 core
laptop with a 4k screen tethered to my phone can't magically make 4G faster.
Interesting interesting.

~~~
cryptonector
It matters.

Suppose there is congestion, and that if the sender(s) don't slow down, it
will just get worse. Well, they don't find out about the congestion if the
receivers lie (and congestion is asymmetric, so that the ACKs get through just
fine).

That's not good.

Now, one way to deal with this is to lie but only for a bit. After a while of
not receiving anything, the receiver should stop sending ACKs and the sender
should notice the congestion. That might help. But the underlying problem is
real: lying ACks -> failure to detect congestion -> worse congestion.

~~~
CapacitorSet
Maybe the client should lie probabilistically, so that there is still a
relationship between what the sender sees and the actual congestion.

~~~
cryptonector
If you really want this just use SACK and let the sender never retransmit, no?

------
Animats
I suppose that's the answer to Random Early Drop.

I used to argue that you want to use fair queuing and drop the _newest_ packet
in a stream, so all the old packets get delivered. But Random Early Drop,
which is trivial to implement, caught on in routers. That means you lose
random packets from the stream, and they have to be retransmitted.

There's nothing awful about acknowledging a TCP sequence number for a valid
packet received even if some previous packets are missing. You know the
missing packets were sent, or you wouldn't have the later packet. If you don't
need them, why ask for retransmission? The receiving TCP doing this should
notice that packets are being lost and cut down the congestion window a bit,
so the sender will slow down.

This is purely a receive-side thing. It shouldn't bother upstream middleboxes.
But, as someone pointed out, about 25% of middleboxes don't like it.

------
jacob019
Could be quite useful for TCP/TCP VPN type applications. It is widely accepted
that TCP/TCP degrades performance, hence TCP/UDP is preferred. But UDP isn't
always available.

------
kazinator
I have read about this long ago. This was in the context not of ignoring
don't-care data, but using premature ACKs as a way of garnering more
bandwidth.

The idea is to send ACKs ahead of time to provoke the sender into transmitting
faster, defeating some of the congestion control mechanisms in TCP.

The network has to be reliable to make it work (the pipe has to buffer all the
excess spew), and the sending stack has to ignore situations when it gets a
premature ACK, ahead of the sequence number it has actually sent.

------
jgrip
So basically redoing a less useful version of SCTP with the same issues in
regards to middle boxes. I wish Microsoft would finally get their thumbs out
and put SCTP into Windows.

------
dogecoinbase
This, like many other current network flow innovations (see: QUIC), is greedy-
algorithm short-sightedness that only works as a result of the improvements to
regional/inter-datacenter networking over the last decade. They fall down
miserably in the face of actual unreliability/variable latency/packet
duplication, which still exist on many less developed networks worldwide.

~~~
stingraycharles
From that point of view, UDP streaming is also short-sighted. Practically,
this is nothing more than a type of "QoS" flag, where of course things would
also break down if everything started giving themselves priority 1.

So it depends more upon whether the use case is appropriate than it does about
technical implementation.

------
mixedbit
In TCP if you ACK something that wasn't sent the ACK is dropped.

~~~
kelnos
That's not what's being talked about here. The idea is that you ACK packets
that you believe _have_ been sent, but have been dropped or delayed, because
you've received a later packet.

~~~
adrianmonk
Good point. Though that puts this somewhere in a middle ground between a best
effort stream and a reliable stream. The ability to throw away data you don't
care about is not absolute but is instead conditional upon successfully
receiving more data.

In a true best effort streaming system, the sender wouldn't retransmit. With
this scheme, the sender might retransmit, sometimes, depending on whether
certain packets get through and allow certain acks to get sent.

------
makira
So, UDP.

~~~
andreasvc
No. UDP is connectionless, which makes it harder to use with NAT.

~~~
xxpor
Not sure why you say that, UDP conntracking has been around for a long time.

~~~
trav4225
I _suspect_ that what andreasvc meant is that the default "NAT" configuration
of most consumer-grade gear is such that it will block UDP (unless some other
mechanism such as UPnP is used)...

~~~
lmns
That's true for TCP as well. Almost all consumer-grade routers block all
incoming connection attempts, not just UDP.

From a stateful firewall's point of view both UDP and TCP have state.

~~~
trav4225
Right. I was assuming that the context here was connections being initiated by
the client (as most are).

~~~
kelnos
... in which case blocking is not an issue. Consumer-grade NAT hardware will
no more block client-initiated UDP than it'll block client-initiated TCP, at
least not without extra configuration.

------
kazinator
Proposed socket-level API: allow _llseek_ on the descriptor, in the forward
direction only.

------
whiletrue84
Why would anyone implement VoIP over TCP to then lie to TCP in order ot make
it practically UDP?

