mirror of
https://github.com/golang/go
synced 2024-11-26 07:27:59 -07:00
net: mptcp: implement listenMPTCP
Similar to dialMPTCP, this listenMPTCP function is called when the user has requested MPTCP via SetMultipathTCP in the ListenConfig. This function falls back to listenTCP on operating systems that do not support MPTCP or if MPTCP is not supported. On ListenConfig side, MultipathTCP function can be used to know if the package will try to use MPTCP or not when Listen is called. Note that this new listenMPTCP function returns a TCPListener object and not a new MPTCP dedicated one. The reasons are similar as the ones explained in the parent commit introducing dialTCP: if MPTCP is used by default later, Listen will return a different object that could break existing applications expecting TCPListener. This work has been co-developped by Gregory Detal <gregory.detal@tessares.net>. Updates #56539 Change-Id: I010f1d87f921bbac9e157cef2212c51917852353 Reviewed-on: https://go-review.googlesource.com/c/go/+/471137 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
0bd94e4387
commit
7dc10dbf45
@ -1,2 +1,4 @@
|
|||||||
pkg net, method (*Dialer) MultipathTCP() bool #56539
|
pkg net, method (*Dialer) MultipathTCP() bool #56539
|
||||||
pkg net, method (*Dialer) SetMultipathTCP(bool) #56539
|
pkg net, method (*Dialer) SetMultipathTCP(bool) #56539
|
||||||
|
pkg net, method (*ListenConfig) MultipathTCP() bool #56539
|
||||||
|
pkg net, method (*ListenConfig) SetMultipathTCP(bool) #56539
|
||||||
|
@ -673,6 +673,29 @@ type ListenConfig struct {
|
|||||||
// that do not support keep-alives ignore this field.
|
// that do not support keep-alives ignore this field.
|
||||||
// If negative, keep-alives are disabled.
|
// If negative, keep-alives are disabled.
|
||||||
KeepAlive time.Duration
|
KeepAlive time.Duration
|
||||||
|
|
||||||
|
// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
|
||||||
|
// used, any call to Listen with "tcp(4|6)" as network will use MPTCP if
|
||||||
|
// supported by the operating system.
|
||||||
|
mptcpStatus mptcpStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultipathTCP reports whether MPTCP will be used.
|
||||||
|
//
|
||||||
|
// This method doesn't check if MPTCP is supported by the operating
|
||||||
|
// system or not.
|
||||||
|
func (lc *ListenConfig) MultipathTCP() bool {
|
||||||
|
return lc.mptcpStatus.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMultipathTCP directs the Listen method to use, or not use, MPTCP,
|
||||||
|
// if supported by the operating system. This method overrides the
|
||||||
|
// system default.
|
||||||
|
//
|
||||||
|
// If MPTCP is not available on the host or not supported by the client,
|
||||||
|
// the Listen method will fall back to TCP.
|
||||||
|
func (lc *ListenConfig) SetMultipathTCP(use bool) {
|
||||||
|
lc.mptcpStatus.set(use)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen announces on the local network address.
|
// Listen announces on the local network address.
|
||||||
@ -693,7 +716,11 @@ func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (Li
|
|||||||
la := addrs.first(isIPv4)
|
la := addrs.first(isIPv4)
|
||||||
switch la := la.(type) {
|
switch la := la.(type) {
|
||||||
case *TCPAddr:
|
case *TCPAddr:
|
||||||
l, err = sl.listenTCP(ctx, la)
|
if sl.MultipathTCP() {
|
||||||
|
l, err = sl.listenMPTCP(ctx, la)
|
||||||
|
} else {
|
||||||
|
l, err = sl.listenTCP(ctx, la)
|
||||||
|
}
|
||||||
case *UnixAddr:
|
case *UnixAddr:
|
||||||
l, err = sl.listenUnix(ctx, la)
|
l, err = sl.listenUnix(ctx, la)
|
||||||
default:
|
default:
|
||||||
|
@ -51,3 +51,12 @@ func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCP
|
|||||||
|
|
||||||
return sd.doDialTCPProto(ctx, laddr, raddr, _IPPROTO_MPTCP)
|
return sd.doDialTCPProto(ctx, laddr, raddr, _IPPROTO_MPTCP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
|
||||||
|
// Fallback to listenTCP if Multipath TCP isn't supported on this operating system.
|
||||||
|
if !supportsMultipathTCP() {
|
||||||
|
return sl.listenTCP(ctx, laddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sl.listenTCPProto(ctx, laddr, _IPPROTO_MPTCP)
|
||||||
|
}
|
||||||
|
@ -13,3 +13,7 @@ import (
|
|||||||
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
||||||
return sd.dialTCP(ctx, laddr, raddr)
|
return sd.dialTCP(ctx, laddr, raddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
|
||||||
|
return sl.listenTCP(ctx, laddr)
|
||||||
|
}
|
||||||
|
@ -169,13 +169,17 @@ func (ln *TCPListener) file() (*os.File, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
|
func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
|
||||||
|
return sl.listenTCPProto(ctx, laddr, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sl *sysListener) listenTCPProto(ctx context.Context, laddr *TCPAddr, proto int) (*TCPListener, error) {
|
||||||
var ctrlCtxFn func(cxt context.Context, network, address string, c syscall.RawConn) error
|
var ctrlCtxFn func(cxt context.Context, network, address string, c syscall.RawConn) error
|
||||||
if sl.ListenConfig.Control != nil {
|
if sl.ListenConfig.Control != nil {
|
||||||
ctrlCtxFn = func(cxt context.Context, network, address string, c syscall.RawConn) error {
|
ctrlCtxFn = func(cxt context.Context, network, address string, c syscall.RawConn) error {
|
||||||
return sl.ListenConfig.Control(network, address, c)
|
return sl.ListenConfig.Control(network, address, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_STREAM, 0, "listen", ctrlCtxFn)
|
fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_STREAM, proto, "listen", ctrlCtxFn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user