mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-16 18:08:40 +00:00
magicsock: set the don't fragment sockopt (#8715)
This sets the Don't Fragment flag, for now behind the TS_DEBUG_ENABLE_PMTUD envknob. Updates #311. Signed-off-by: Val <valerie@tailscale.com> Signed-off-by: salman <salman@tailscale.com>
This commit is contained in:
parent
16bc9350e3
commit
99e06d3544
@ -47,6 +47,8 @@ var (
|
||||
// debugRingBufferMaxSizeBytes overrides the default size of the endpoint
|
||||
// history ringbuffer.
|
||||
debugRingBufferMaxSizeBytes = envknob.RegisterInt("TS_DEBUG_MAGICSOCK_RING_BUFFER_MAX_SIZE_BYTES")
|
||||
// debugPMTUD enables path MTU discovery. Currently only sets the Don't Fragment sockopt.
|
||||
debugPMTUD = envknob.RegisterBool("TS_DEBUG_ENABLE_PMTUD")
|
||||
// Hey you! Adding a new debugknob? Make sure to stub it out in the debugknob_stubs.go
|
||||
// file too.
|
||||
)
|
||||
|
@ -20,6 +20,7 @@ func debugAlwaysDERP() bool { return false }
|
||||
func debugUseDERPHTTP() bool { return false }
|
||||
func debugEnableSilentDisco() bool { return false }
|
||||
func debugSendCallMeUnknownPeer() bool { return false }
|
||||
func debugPMTUD() bool { return false }
|
||||
func debugUseDERPAddr() string { return "" }
|
||||
func debugUseDerpRouteEnv() string { return "" }
|
||||
func debugUseDerpRoute() opt.Bool { return "" }
|
||||
|
35
wgengine/magicsock/dontfrag_darwin.go
Normal file
35
wgengine/magicsock/dontfrag_darwin.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build darwin && !ios
|
||||
|
||||
package magicsock
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"tailscale.com/types/nettype"
|
||||
)
|
||||
|
||||
func setDontFragment(pconn nettype.PacketConn, network string) (err error) {
|
||||
if c, ok := pconn.(*net.UDPConn); ok {
|
||||
rc, err := c.SyscallConn()
|
||||
if err == nil {
|
||||
rc.Control(func(fd uintptr) {
|
||||
if network == "udp4" {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, unix.IP_DONTFRAG, 1)
|
||||
}
|
||||
if network == "udp6" {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, unix.IPV6_DONTFRAG, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func CanPMTUD() bool {
|
||||
return debugPMTUD() // only if the envknob is for now.
|
||||
}
|
24
wgengine/magicsock/dontfrag_default.go
Normal file
24
wgengine/magicsock/dontfrag_default.go
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build (!linux && !darwin) || android || ios
|
||||
|
||||
package magicsock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"tailscale.com/types/nettype"
|
||||
)
|
||||
|
||||
// setDontFragment sets the dontfragment sockopt on pconn on the platforms that support it,
|
||||
// for both IPv4 and IPv6.
|
||||
// (C.f. https://datatracker.ietf.org/doc/html/rfc3542#section-11.2 for IPv6 fragmentation)
|
||||
func setDontFragment(pconn nettype.PacketConn, network string) (err error) {
|
||||
return errors.New("setting don't fragment bit not supported on this OS")
|
||||
}
|
||||
|
||||
// CanPMTUD returns whether this platform supports performing peet path MTU discovery.
|
||||
func CanPMTUD() bool {
|
||||
return false
|
||||
}
|
34
wgengine/magicsock/dontfrag_linux.go
Normal file
34
wgengine/magicsock/dontfrag_linux.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build linux && !android
|
||||
|
||||
package magicsock
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"tailscale.com/types/nettype"
|
||||
)
|
||||
|
||||
func setDontFragment(pconn nettype.PacketConn, network string) (err error) {
|
||||
if c, ok := pconn.(*net.UDPConn); ok {
|
||||
rc, err := c.SyscallConn()
|
||||
if err == nil {
|
||||
rc.Control(func(fd uintptr) {
|
||||
if network == "udp4" {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_DO)
|
||||
}
|
||||
if network == "udp6" {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_DO)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func CanPMTUD() bool {
|
||||
return debugPMTUD() // only if the envknob is enabled, for now.
|
||||
}
|
@ -2233,6 +2233,16 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
|
||||
continue
|
||||
}
|
||||
trySetSocketBuffer(pconn, c.logf)
|
||||
|
||||
if CanPMTUD() {
|
||||
err = setDontFragment(pconn, network)
|
||||
if err != nil {
|
||||
c.logf("magicsock: set dontfragment failed for %v port %d: %v", network, port, err)
|
||||
// TODO disable PMTUD in this case. We don't expect the setsockopt to fail on
|
||||
// supported platforms, but we might as well be paranoid.
|
||||
}
|
||||
}
|
||||
|
||||
// Success.
|
||||
if debugBindSocket() {
|
||||
c.logf("magicsock: bindSocket: successfully listened %v port %d", network, port)
|
||||
|
Loading…
x
Reference in New Issue
Block a user