mirror of
https://github.com/golang/go
synced 2024-11-11 20:20:23 -07:00
net: mptcp: implement dialMPTCP
This function is called when the user has requested MPTCP via SetMultipathTCP in the Dialer. This new function falls back to dialTCP on operating systems that do not support MPTCP or if MPTCP is not supported. On Dialer side, MultipathTCP function can be used to know if the package will try to use MPTCP or not when Dial is called. Note that this new dialMPTCP function returns a TCPConn object, like dialTCP. A new MPTCPConn object using the following composition could have been returned: type MPTCPConn struct { *TCPConn } But the drawback is that if MPTCP is used by default one day (see #56539 issue on GitHub), Dial will return a different object: this new MPTCPConn type instead of the previously expected TCPConn. This can cause issues for apps checking the returned object. This work has been co-developped by Gregory Detal <gregory.detal@tessares.net>. Updates #56539 Change-Id: I0f9b5b81f630b39142bdd553d4f1b4c775f1dff0 Reviewed-on: https://go-review.googlesource.com/c/go/+/471136 Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com> Run-TryBot: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
6615324f79
commit
0bd94e4387
2
api/next/56539.txt
Normal file
2
api/next/56539.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pkg net, method (*Dialer) MultipathTCP() bool #56539
|
||||||
|
pkg net, method (*Dialer) SetMultipathTCP(bool) #56539
|
@ -141,6 +141,11 @@ type Dialer struct {
|
|||||||
//
|
//
|
||||||
// If ControlContext is not nil, Control is ignored.
|
// If ControlContext is not nil, Control is ignored.
|
||||||
ControlContext func(ctx context.Context, network, address string, c syscall.RawConn) error
|
ControlContext func(ctx context.Context, network, address string, c syscall.RawConn) error
|
||||||
|
|
||||||
|
// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
|
||||||
|
// used, any call to Dial with "tcp(4|6)" as network will use MPTCP if
|
||||||
|
// supported by the operating system.
|
||||||
|
mptcpStatus mptcpStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) dualStack() bool { return d.FallbackDelay >= 0 }
|
func (d *Dialer) dualStack() bool { return d.FallbackDelay >= 0 }
|
||||||
@ -314,6 +319,24 @@ func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string
|
|||||||
return naddrs, nil
|
return naddrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MultipathTCP reports whether MPTCP will be used.
|
||||||
|
//
|
||||||
|
// This method doesn't check if MPTCP is supported by the operating
|
||||||
|
// system or not.
|
||||||
|
func (d *Dialer) MultipathTCP() bool {
|
||||||
|
return d.mptcpStatus.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMultipathTCP directs the Dial methods 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 server,
|
||||||
|
// the Dial methods will fall back to TCP.
|
||||||
|
func (d *Dialer) SetMultipathTCP(use bool) {
|
||||||
|
d.mptcpStatus.set(use)
|
||||||
|
}
|
||||||
|
|
||||||
// Dial connects to the address on the named network.
|
// Dial connects to the address on the named network.
|
||||||
//
|
//
|
||||||
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
|
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
|
||||||
@ -610,7 +633,11 @@ func (sd *sysDialer) dialSingle(ctx context.Context, ra Addr) (c Conn, err error
|
|||||||
switch ra := ra.(type) {
|
switch ra := ra.(type) {
|
||||||
case *TCPAddr:
|
case *TCPAddr:
|
||||||
la, _ := la.(*TCPAddr)
|
la, _ := la.(*TCPAddr)
|
||||||
c, err = sd.dialTCP(ctx, la, ra)
|
if sd.MultipathTCP() {
|
||||||
|
c, err = sd.dialMPTCP(ctx, la, ra)
|
||||||
|
} else {
|
||||||
|
c, err = sd.dialTCP(ctx, la, ra)
|
||||||
|
}
|
||||||
case *UDPAddr:
|
case *UDPAddr:
|
||||||
la, _ := la.(*UDPAddr)
|
la, _ := la.(*UDPAddr)
|
||||||
c, err = sd.dialUDP(ctx, la, ra)
|
c, err = sd.dialUDP(ctx, la, ra)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"internal/poll"
|
"internal/poll"
|
||||||
"sync"
|
"sync"
|
||||||
@ -41,3 +42,12 @@ func initMPTCPavailable() {
|
|||||||
mptcpAvailable = true
|
mptcpAvailable = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
||||||
|
// Fallback to dialTCP if Multipath TCP isn't supported on this operating system.
|
||||||
|
if !supportsMultipathTCP() {
|
||||||
|
return sd.dialTCP(ctx, laddr, raddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd.doDialTCPProto(ctx, laddr, raddr, _IPPROTO_MPTCP)
|
||||||
|
}
|
||||||
|
@ -5,3 +5,11 @@
|
|||||||
//go:build !linux
|
//go:build !linux
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
||||||
|
return sd.dialTCP(ctx, laddr, raddr)
|
||||||
|
}
|
||||||
|
@ -65,13 +65,17 @@ func (sd *sysDialer) dialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
|
||||||
|
return sd.doDialTCPProto(ctx, laddr, raddr, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sd *sysDialer) doDialTCPProto(ctx context.Context, laddr, raddr *TCPAddr, proto int) (*TCPConn, error) {
|
||||||
ctrlCtxFn := sd.Dialer.ControlContext
|
ctrlCtxFn := sd.Dialer.ControlContext
|
||||||
if ctrlCtxFn == nil && sd.Dialer.Control != nil {
|
if ctrlCtxFn == nil && sd.Dialer.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 sd.Dialer.Control(network, address, c)
|
return sd.Dialer.Control(network, address, c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial", ctrlCtxFn)
|
fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, proto, "dial", ctrlCtxFn)
|
||||||
|
|
||||||
// TCP has a rarely used mechanism called a 'simultaneous connection' in
|
// TCP has a rarely used mechanism called a 'simultaneous connection' in
|
||||||
// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
|
// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
|
||||||
@ -101,7 +105,7 @@ func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCP
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
fd.Close()
|
fd.Close()
|
||||||
}
|
}
|
||||||
fd, err = internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial", ctrlCtxFn)
|
fd, err = internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, proto, "dial", ctrlCtxFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user