quicwg / base-drafts

Internet-Drafts that make up the base QUIC specification
https://quicwg.org
1.63k stars 204 forks source link

Flow/congestion control and rejected 0-RTT #390

Closed martinthomson closed 5 years ago

martinthomson commented 7 years ago

We need to be very clear about what the rules are regarding 0-RTT packets that are rejected by the server. I think that this should be:

RyanTheOptimist commented 7 years ago

On Sun, Mar 12, 2017 at 5:23 PM, Martin Thomson notifications@github.com wrote:

We need to be very clear about what the rules are regarding 0-RTT packets that are rejected by the server. I think that this should be:

​Thanks for bringing this up. Clarity here seems critical.​

-

Rejected 0-RTT packets don't count toward flow control. The server can't see them, so we have to assume that they don't exist for this purpose.

​Hm. It's true that the server doesn't see these packets. But flow-control happens at the stream layer, not the packet layer.​ ​(For example, when a normal packet is retransmitted, the flow control limits are obviously not affected). ​ If the client decides to retransmit the data in the rejected packets (the common behavior, I think) then the client ​does not need to change the flow control counts from their state when the data was sent.

But yet, if a client choses to do drop the data in those packets then, yes, I agree that they should not count against flow control limits.

  • Rejected 0-RTT packets do count toward congestion control limits. Congestion control is a local thing, and the packets were sent, which means that they are causing congestion.

​Keep in mind that if a 0-RTT handshake is rejected, then the sever will not be able to ACK the 0-RTT packets, because it will not be able to decrypt them. So I think this mean that when a client receives the reject, it needs to act as if the 0-RTT packets were lost which means to no longer consider them in flight, and not count against the congestion window.​

martinthomson commented 7 years ago

Ahh, yes, the point about retransmission is a good one. If the model is that 0-RTT packets are just "lost", then retransmissions will take care of everything. We should say that.

BTW, @RyanAtGoogle , I had to edit your response. Email responses have terrible quoting if you do this:

> quoted text
reply
RyanTheOptimist commented 7 years ago

On Sun, Mar 12, 2017 at 11:13 PM, Martin Thomson notifications@github.com wrote:

Ahh, yes, the point about retransmission is a good one. If the model is that 0-RTT packets are just "lost", then retransmissions will take care of everything. We should say that.

SGTM

BTW, @RyanAtGoogle , I had to edit your response. Email responses have terrible quoting if you do this:

quoted text reply

Weird, I don't think that's how I replied, though I don't do plain text email so perhaps I screwed up. Here's what I see:

boggle Oh, I guess I didn't realize this is a github issue and not just an email thread. That's probably how I screwed this up.

ianswett commented 7 years ago

One important point is that even if the 0RTT packets are 'lost' and need to be retransmitted, they should not be considered lost from a congestion control perspective.

If we could say rejected 0RTT packets don't count towards flow control, I think we would no longer have to exempt stream 1 from counting towards connection level flow control, which would be nice.

RyanTheOptimist commented 7 years ago

On Tue, Mar 14, 2017 at 8:18 AM, ianswett notifications@github.com wrote:

One important point is that even if the 0RTT packets are 'lost' and need to be retransmitted, they should not be considered lost from a congestion control perspective.

​To clarify, you mean that the client should not react to rejected 0-RTT packets in the same way it reacts to conventionally lost packet by reducing the congestion window, right? So they need to be removed from in flight, retransmitted, ​but not "marked lost".

martinthomson commented 7 years ago

One important point is that even if the 0RTT packets are 'lost' and need to be retransmitted, they should not be considered lost from a congestion control perspective.

Yes, that is why I had separate points for this. "lost" doesn't quite cut it.

If we could say rejected 0RTT packets don't count towards flow control, I think we would no longer have to exempt stream 1 from counting towards connection level flow control, which would be nice.

Since they can't count, that's academic. I'm more concerned about flow control when 0-RTT is accepted. Connection flow control can still kick in.

There is an alternative design, which would require rolling back a change (it's one that I don't like so I am biased a little, but I really like this alternative).

We require clients to remember transport parameters. In particular, we require that clients remember the connection-level flow control limit. We define a new transport parameter that only applies to 0-RTT: maximum bytes. The same limit exists in TLS, and I was going to propose that we include this anyway (I've opened #405 to do this, since I obviously neglected to do so).

If we choose to apply that limit to STREAM payloads (my preference), then we can say that this value MUST be at least X octets less than the initial connection flow control offset (Finished is usually the hash output, so I imagine that 128 octets would be plenty of slack). Then, you always have space for at least a Finished message.

Note: Client authentication doesn't interfere with this because it can't be used in conjunction with 0-RTT.

ianswett commented 7 years ago

That seems like a fine solution to me.

hardie commented 7 years ago

On Tue, Mar 14, 2017 at 4:24 PM, Martin Thomson notifications@github.com wrote:

There is an alternative design, which would require rolling back a change

(it's one that I don't like so I am biased a little, but I really like this alternative).

We require clients to remember transport parameters. In particular, we require that clients remember the connection-level flow control limit.

So, I'm always a little worried with a mandate on clients like "MUST remeber" unless it has some bound. In this case, it seems like the bound "is for as long as you want/could do 0-RTT", so there is some cover. But I confess that I wonder if the transport parameter validity and the 0-RTT credential lifetime really do match.

We define a new transport parameter that only applies to 0-RTT: maximum

bytes. The same limit exists in TLS, and I was going to propose that we include this anyway (I've opened #405 https://github.com/quicwg/base-drafts/issues/405 to do this, since I obviously neglected to do so).

If we choose to apply that limit to STREAM payloads (my preference), then we can say that this value MUST be at least X octets less than the initial connection flow control offset (Finished is usually the hash output, so I imagine that 128 octets would be plenty of slack). Then, you always have space for at least a Finished message.

Ted

martinthomson commented 7 years ago

Yes, this all binds to the 0-RTT credentials, so that places an upper bound on how long this is valid for.

I'm going to concede straight up that the lifetime of things like "how much memory I am going to commit" is 100% not the same as the credential lifetime. But the client doesn't have anything else to go on.

Ultimately, when the new session is created with a 0-RTT offer, the server can always choose to reject 0-RTT if it can't live up to that promise. That's all it has, and we can ever hope for. Given the dynamics involved, this is going to be a per-connection decision.

Sure, that means that you have a bunch of pressures that eventually end up with a flat success/fail decision, and you might be sad about that, but I'm far more sad about the current design lacking any real control or determinism. At least this way the server can tune in the values it provides so that it gets the best result (for whatever metrics the server cares about).

hardie commented 7 years ago

On Wed, Mar 15, 2017 at 10:11 PM, Martin Thomson notifications@github.com wrote:

Yes, this all binds to the 0-RTT credentials, so that places an upper bound on how long this is valid for.

I'm going to concede straight up that the lifetime of things like "how much memory I am going to commit" is 100% not the same as the credential lifetime. But the client doesn't have anything else to go on.

I agree that it doesn't have anything else to go on now. We could, in theory, create methods to give it more to go on (e.g. a separate transport parameter lifetime provided by the server), but I seriously doubt that's worth it.

That assessment makes me wonder, though, how the success rate of the 0RTT connections with defaults will compare with that of connections using remembered parameters. If the remembered parameter connections succeed as often or more often, then they are clearly double plus good; if they succeed less often, then the delta is the trade-off. I don't, unfortunately, have any data on what the delta is going to be in different network conditions, and I distrust my own instincts here (I fear, but without data, that they will fail more often in the cases where the failures hurt worst).

Ultimately, when the new session is created with a 0-RTT offer, the server can always choose to reject 0-RTT if it can't live up to that promise. That's all it has, and we can ever hope for.

Well, that and clear signaling that this was why it was closed.

Given the dynamics involved, this is going to be a per-connection decision.

Sure, that means that you have a bunch of pressures that eventually end up with a flat success/fail decision, and you might be sad about that, but I'm far more sad about the current design lacking any real control or determinism. At least this way the server can tune in the values it provides so that it gets the best result (for whatever metrics the server cares about).

I think the control surface is very hard to use. You can't the credential life time, so you can provide a value that is "generally useful", but no more. That may be better than nothing, but I don't think it stands much tuning.

Ted

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/quicwg/base-drafts/issues/390#issuecomment-286959699, or mute the thread https://github.com/notifications/unsubscribe-auth/ABVb5L-bGcJigmRvTLi3NnNJIsry30AEks5rmMRqgaJpZM4MavGm .

martinthomson commented 7 years ago

My hypothesis (caveat with the same distrust of intuition you have) is that if you let a client use the default OR remembered value for connection flow control, then you will have to reject more often. That is, when remembered < default, a server can't know whether the client bothered to remember and so will have to assume the worst.

Creating clear signaling for this might not be feasible. "I don't have enough memory for your 0-RTT data" is another way of saying "please DoS me more" to some people.

martinthomson commented 6 years ago

@janaiyengar's proposal here:

  1. mark these packets as lost (this will cause the data to be sent again)
  2. reset the congestion controller, but keep sRTT and similar