-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/sys/unix: add support for linux' TCP_CC_INFO #68232
Comments
Change https://go.dev/cl/595676 mentions this issue: |
This API is unusual for x/sys/unix, so sending it through the proposal process. Proposal is // GetsockoptTCPCCInfo returns algorithm specific congestion control information for the socket.
// It requires a type parameter to specify the type of congestion control algorithm being used. E.g. for BBR:
//
// info, err := unix.GetsockoptTCPCCInfo[TCPBBRInfo](fd, unix.IPPROTO_TCP, unix.TCP_CC_INFO)
//
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option.
func GetsockoptTCPCCInfo[T TCPVegasInfo | TCPDCTCPInfo | TCPBBRInfo](fd, level, opt int) (*T, error) {
var value tcpCCInfo
vallen := _Socklen(SizeofTCPCCInfo)
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
out := (*T)(unsafe.Pointer(&value[0]))
return out, err
}
type TCPVegasInfo struct {
...
}
type TCPDCTCPInfo struct {
...
}
type TCPBBRInfo struct {
...
} |
This is a puzzling API. I don't see how the caller knows which of the three structs to use. There must be some other getsockopt that tells you which congestion control algorithm the socket uses, and then you know which struct to provide. Given that the choice of argument type is not happening statically at compile time but instead dynamically based on that getsockopt (or perhaps reading a file in /proc, but surely different TCP sockets can use different algorithms), it seems like it would be better to take an any and document that it must be one of the three types and use a type switch inside the function to distinguish the three. It also seems like maybe the opt should be dropped, since it must be hard-coded to unxi.TCP_CC_INFO, right?
|
This proposal has been added to the active column of the proposals project |
Good point. // generic
func GetsockoptByte(fd, level, opt int) (value byte, err error)
func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, err error)
func GetsockoptInt(fd, level, opt int) (value int, err error)
func GetsockoptString(fd, level, opt int) (string, error)
func GetsockoptUint64(fd, level, opt int) (value uint64, err error)
// specialized
func GetsockoptICMPv6Filter(fd, level, opt int) (*ICMPv6Filter, error)
func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, error)
func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error)
func GetsockoptIPv6MTUInfo(fd, level, opt int) (*IPv6MTUInfo, error)
func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, error)
func GetsockoptLinger(fd, level, opt int) (*Linger, error)
func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) // <-- in particular
func GetsockoptTimeval(fd, level, opt int) (*Timeval, error)
func GetsockoptTpacketStats(fd, level, opt int) (*TpacketStats, error)
func GetsockoptTpacketStatsV3(fd, level, opt int) (*TpacketStatsV3, error)
func GetsockoptUcred(fd, level, opt int) (*Ucred, error) Following that line of thought, one could also return For completeness: a simpler alternative would be multiple functions that each return one of the supported types. func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error)
func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error)
func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error)
That's also related to the existing functions mentioned above. I totally agree that this seems weird, but I suspect it would be worse to have some functions in this family with a different pattern. Maybe something for |
I think this is most in keeping with the current x/sys:
I remain confused about how you are supposed to use these APIs though. How do you know which to call? It looks like you don't even get an error if you guess wrong, so "try all three" doesn't work. |
Yes, AFAIK there's no way to verify which of the C union types one got? I see two main realistic use-cases:
I'm not sure we can do much better without a higher level API? |
At the least we should document how to figure out which one to expect and make sure we have APIs to use to do that. What are the APIs? What is the specific Getsockopt call to use? |
The Getsockopt call is: algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) Note that not all of the current congestion control algorithms expose information via And yes, absolutely agree that this should be documented. |
Great, thanks. Then the API would be:
and we'd document for each one that you call
ahead of time and also document for each which algo to expect to make that call (e.g., GetsockoptTCPCCVegasInfo) meaningful. |
Have all remaining concerns about this proposal been addressed? The proposal is at #68232 (comment) |
Based on the discussion above, this proposal seems like a likely accept. The proposal is at #68232 (comment) |
No change in consensus, so accepted. 🎉 The proposal is at #68232 (comment) |
the current proposal implementation is in https://go-review.googlesource.com/c/sys/+/595676 if someone could "unhold" it, that would be awesome! 🙏 |
Update, Aug 14 2024 The proposal is #68232 (comment)
Proposal Details
The TCP_INFO support in x/sys/unix should be expanded to also cover TCP_CC_INFO.
There is at least one external package providing this functionality, but since it requires unsafe conversions of kernel structs, it is prone to subtle errors (e.g. "converted pointer straddles multiple allocations").
Therefore this functionality would profit from using the existing code-generation in
x/sys/unix
to keep it less error-prone.The text was updated successfully, but these errors were encountered: