-
Notifications
You must be signed in to change notification settings - Fork 18k
net: add support for TCP Fast Open #4842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Re #2: IIUC, that's related, but against spec. TCP permits such a packet, but also says that the recipient isn't supposed to act on it until the connection is verified, since the initial SYN packet could've had its source IP/port spoofed. TCP_FASTOPEN is a formalized version of that which isn't susceptible to spoofing. I never knew that AcceptEx makes that optional. I suppose a Windows webserver could use AcceptEx w/ data and verify first it's a GET request to a public resource and send the response immediately. I remember IE / Microsoft doing this years ago (to win HTTP benchmarks?), but I didn't remember how. Interesting. |
Now that DialOpt is in (https://code.google.com/p/go/source/detail?r=54731addb542 / docs: http://tip.golang.org/pkg/net/#DialOpt), this is easier. There are two API possibilities. a) lazy. b) explicit. In the lazy API, the connect would be like: conn, err := net.DialOpt("google.com:80", net.FastOpen()) ... and a fake net.Conn is returned immediately. No possibility for timeouts or errors. Not until the first Write does the actual sendto system call (on Linux) get called. This is what Chrome does. With the explicit API alternative (my preference), the API will probably be like: conn, err := net.DialOpt("google.com:80", net.InitialData("GET / HTTP/1.0\r\n\r\n")) Where net.InitialData returns a DialOption (http://tip.golang.org/pkg/net/#DialOption) that enables TFO if the client supports it (on Linux: checking the low bit of /proc/sys/net/ipv6/tcp_fastopen) and otherwise just does a Write after connect. Speaking with Yuchung Cheng, it seems there's enough momentum beh that something like it will be formalized one way or another, it will be formalized one way or another. And Linux 3.8 supporting it (client & server) is promising (and Windows in an alternate form). Thus I'd like to keep "TFO" or "TCPFastOpen" out of the Go API name and make the DialOption be just net.InitialData(...). Up for debate whether that's a []byte, string, or io.Reader. Probably a []byte for consistency with Write. |
This issue was updated by revision abf5700. R=golang-dev, r CC=golang-dev https://golang.org/cl/7369060 |
Published, at last: http://tools.ietf.org/html/rfc7413 |
how to make tfo work with http package? http's persist cache depend on established connections. |
@JunfengJia you can use syscall to dial a new connection in http.Transport to work with http package. |
Still thinking. We need to handle the entire stack, TCP through HTTP 1.x, HTTP/2, or WebSocket w/ or w/o TLS, effectively. Once HTTP/2 support lands, I will revisit this issue. |
http will make a read call first, then the connect will fall into 3whs. |
Thanks.It looks like my library will not work with net/http library right now. |
FWIW, old changelist 27150044 has moved to https://go-review.googlesource.com/#/c/7121/. |
In addition to TFO, we need to figure out APIs for /cc @agl |
The change golang.org/cl/7121 is ready to land. However I'm not sure whether crypto/tls and net/http packages really need this feature. Please ping golang.org/cl/7121 when the time comes. |
It says "DO NOT REVIEW" so I stopped reviewing. |
Thanks for the notice, just did s/DO NOT REVIEW/FOR DISCUSSION/ |
CL https://golang.org/cl/7121 mentions this issue. |
Are we going to get this in GO 1.11? |
@riobard, no. This bug is still open. |
Isn't fastopen just a socket option that should be possible in go 1.11 atleast on linux? |
Yeah, this bug was about adding nice, portable API for it (ioctls aren't great API), and using it where it makes sense (the top comment mentions net/http for instance) But it's true that in Go 1.11 you could use https://tip.golang.org/pkg/net/#ListenConfig |
For the server yes. The client needs to send the initial data with sendto(2), continuing with read(2)/write(2). connect(2) triggers a three way handshake instead. UPDATE: I missed this one: torvalds/linux@19f6d3f |
Are we going to get this in GO 2? |
This has little if anything to do with Go 2. |
Any progress? |
Hello. Is there still interest in this? Given the flow described in torvalds/linux@19f6d3f, assuming support for TFO only for Linux 4.11+, the code could be simplified greatly, compared to what CL 7121 does. Adoption in other places in the standard library would also be easier, since caller code would not need to change. @mikioh, @bradfitz: would it be okay if I tried this from scratch in the upcoming cycle? It looks like https://go-review.googlesource.com/c/go/+/7121/ would need a pretty complicated rebase to bring it into the present. |
@acln0, oh, nice! I hadn't seen that. Given that new API, this is basically trivial. In fact, people can do it already today with Go 1.11 and its new: https://tip.golang.org/pkg/net/#Dialer.Control Then you can just do the (Of course, if you do so, you should only use that http.Client for GET/HEAD/idempotent requests.) But sure, you could work on it. |
If you are talking about stuff in the net package, probably still not the time. If net/http, crypto/tls, or net/http over crypto/tls, it should be another issue and probably it's fine unless you try to introduce a) a quick hack for message boundary handling; especially without considering byte-seq.+partial read/writes vs. datagram/chunks+full reads/writes, b) a quick hack for multipath transport functionality. |
@bradfitz, I had the net/http use case for idempotent requests in mind. I don't know the intricacies of how crypto/tls might make use of TFO in the larger context of TLS 1.3 etc., so I cannot comment on that. Yes, people can do it at the net.Dialer level themselves today, but I thought there might be some value in adding options to the net package as well. If the standard library is going to use TFO, my thought was the following: instead of making net/http and crypto/tls set socket options themselves, we could try to introduce FastOpen knobs to net.Dialer and net.Listener, to consolidate that code in one well defined place. Once the new API existed in the net package, both the standard library and other clients could start adopting it, at whichever pace they like. I wrote my initial message in this bug because I was interested in giving the ground work in package net another try. @mikioh, can you please clarify what you mean about "stuff in the net package, probably still not the time"? Do you mean the possibility of FastOpen knobs on net.Dialer and net.Listener? It seems to me like Linux and FreeBSD support both passive and active sides pretty easily. And OS X supports active side too. Do you think this level of support across operating systems is not wide enough to warrant an option in package net? |
Yes.
As far as I can see, on FreeBSD, a few GENERIC conf files include TCP_RFC7413 option by default from 12-STABLE, but not all, also unlike passive-open side operation, enabling active-open operation still needs sysctl tweaking.
As far as I can see, it still supports active-open operation only and requires connectx thru syscall.Syscall9.
Still a bit early to me. If it's pretty fine within the real world, it's better to be enabled by default (and we should avoid introducing a control knob each time we need to fix something user uncomfortable on the operation of TCP Fast Open option, including configuring cookie-related life-duration/invalidation/capacity control.) |
Any more complete example? |
@qJkee, call the Control method on the syscall.RawConn. Its argument is a function of the integer file descriptor. You can call setsockopt in that function. |
@acln0 thank you! I will try to implement it asap, and maybe post some bech. |
I'm going to close this. No longer desired. See: |
The text was updated successfully, but these errors were encountered: