1
0
mirror of https://github.com/golang/go synced 2024-11-26 05:17:58 -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:
Matthieu Baerts 2023-02-24 17:51:58 +01:00 committed by Gopher Robot
parent 0bd94e4387
commit 7dc10dbf45
5 changed files with 48 additions and 2 deletions

View File

@ -1,2 +1,4 @@
pkg net, method (*Dialer) MultipathTCP() bool #56539
pkg net, method (*Dialer) SetMultipathTCP(bool) #56539
pkg net, method (*ListenConfig) MultipathTCP() bool #56539
pkg net, method (*ListenConfig) SetMultipathTCP(bool) #56539

View File

@ -673,6 +673,29 @@ type ListenConfig struct {
// that do not support keep-alives ignore this field.
// If negative, keep-alives are disabled.
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.
@ -693,7 +716,11 @@ func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (Li
la := addrs.first(isIPv4)
switch la := la.(type) {
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:
l, err = sl.listenUnix(ctx, la)
default:

View File

@ -51,3 +51,12 @@ func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCP
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)
}

View File

@ -13,3 +13,7 @@ import (
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
return sd.dialTCP(ctx, laddr, raddr)
}
func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
return sl.listenTCP(ctx, laddr)
}

View File

@ -169,13 +169,17 @@ func (ln *TCPListener) file() (*os.File, 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
if sl.ListenConfig.Control != nil {
ctrlCtxFn = func(cxt context.Context, network, address string, c syscall.RawConn) error {
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 {
return nil, err
}