wgengine/magicsock: apply peer MTU sockopts through net/sockopts

And merge repeated don't fragment code paths between Linux and Darwin.

Updates tailscale/corp#48168

Signed-off-by: Alex Valiushko <alexvaliushko@tailscale.com>
Change-Id: I5aef408f037c8def99522b4d820c853a6a6a6964
This commit is contained in:
Alex Valiushko committed 2026-10-19 19:23:28 +00:00
1 parent e9d5cdc323
commit 3bdf85ab6f
4 files changed
+52 -87

No files matched your search

+5 -4
View File
@@ -10,6 +10,7 @@ import (
"golang.org/x/sys/unix"
"tailscale.com/disco"
"tailscale.com/net/sockopts"
"tailscale.com/net/tstun"
)
@@ -18,16 +19,16 @@ import (
// DontFragSetting returns true if at least one of the underlying sockets of
// this connection is a UDP socket with the don't fragment bit set, otherwise it
// returns false. It also returns an error if either connection returned an error
// other than errUnsupportedConnType.
// other than [sockopts.ErrNoSocket].
func (c *Conn) DontFragSetting() (bool, error) {
df4, err4 := c.getDontFragment("udp4")
df6, err6 := c.getDontFragment("udp6")
df := df4 || df6
err := err4
if err4 != nil && err4 != errUnsupportedConnType {
if err4 != nil && !errors.Is(err4, sockopts.ErrNoSocket) {
err = err6
}
if err == errUnsupportedConnType {
if errors.Is(err, sockopts.ErrNoSocket) {
err = nil
}
return df, err
@@ -103,7 +104,7 @@ func (c *Conn) UpdatePMTUD() {
err4 := c.setDontFragment("udp4", enable)
err6 := c.setDontFragment("udp6", enable)
anySuccess := err4 == nil || err6 == nil
noFailures := (err4 == nil || err4 == errUnsupportedConnType) && (err6 == nil || err6 == errUnsupportedConnType)
noFailures := (err4 == nil || errors.Is(err4, sockopts.ErrNoSocket)) && (err6 == nil || errors.Is(err6, sockopts.ErrNoSocket))
if anySuccess && noFailures {
c.logf("magicsock: peermtu: peer MTU status updated to %v", newStatus)
+6 -34
View File
@@ -6,46 +6,18 @@
package magicsock
import (
"syscall"
"golang.org/x/sys/unix"
)
// dontFrag{Enabled,Disabled} are the values of the don't fragment sockopt.
const (
dontFragEnabled = 1
dontFragDisabled = 0
)
func getDontFragOpt(network string) int {
if network == "udp4" {
return unix.IP_DONTFRAG
}
return unix.IPV6_DONTFRAG
}
func (c *Conn) setDontFragment(network string, enable bool) error {
optArg := 1
if enable == false {
optArg = 0
}
var err error
rcErr := c.connControl(network, func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network), optArg)
})
if rcErr != nil {
return rcErr
}
return err
}
func (c *Conn) getDontFragment(network string) (bool, error) {
var v int
var err error
rcErr := c.connControl(network, func(fd uintptr) {
v, err = syscall.GetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network))
})
if rcErr != nil {
return false, rcErr
}
if v == 1 {
return true, err
}
return false, err
}
+6 -32
View File
@@ -9,41 +9,15 @@ import (
"syscall"
)
// dontFrag{Enabled,Disabled} are the values of the don't fragment sockopt.
const (
dontFragEnabled = syscall.IP_PMTUDISC_DO
dontFragDisabled = syscall.IP_PMTUDISC_DONT
)
func getDontFragOpt(network string) int {
if network == "udp4" {
return syscall.IP_MTU_DISCOVER
}
return syscall.IPV6_MTU_DISCOVER
}
func (c *Conn) setDontFragment(network string, enable bool) error {
optArg := syscall.IP_PMTUDISC_DO
if enable == false {
optArg = syscall.IP_PMTUDISC_DONT
}
var err error
rcErr := c.connControl(network, func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network), optArg)
})
if rcErr != nil {
return rcErr
}
return err
}
func (c *Conn) getDontFragment(network string) (bool, error) {
var v int
var err error
rcErr := c.connControl(network, func(fd uintptr) {
v, err = syscall.GetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network))
})
if rcErr != nil {
return false, rcErr
}
if v == syscall.IP_PMTUDISC_DO {
return true, err
}
return false, err
}
+35 -17
View File
@@ -7,6 +7,9 @@ package magicsock
import (
"syscall"
"tailscale.com/net/sockopts"
"tailscale.com/types/nettype"
)
// getIPProto returns the value of the get/setsockopt proto argument necessary
@@ -19,24 +22,39 @@ func getIPProto(network string) int {
return syscall.IPPROTO_IPV6
}
// connControl allows the caller to run a system call on the socket underlying
// Conn specified by the string network, which must be "udp4" or "udp6". If the
// pconn type implements the syscall method, this function returns the value of
// of the system call fn called with the fd of the socket as its arg (or the
// error from rc.Control() if that fails). Otherwise it returns the error
// errUnsupportedConnType.
func (c *Conn) connControl(network string, fn func(fd uintptr)) error {
pconn := c.pconn4.pconn
// connControl runs the system call fn on the fds of the sockets underlying the
// Conn specified by the string network, which must be "udp4" or "udp6".
// See [sockopts.ControlEach] for what it returns.
func (c *Conn) connControl(network string, fn func(fd uintptr) error) error {
pconn := &c.pconn4
if network == "udp6" {
pconn = c.pconn6.pconn
pconn = &c.pconn6
}
sc, ok := pconn.(syscall.Conn)
if !ok {
return errUnsupportedConnType
return sockopts.ControlEach([]nettype.PacketConn{pconn.currentConn()}, fn)
}
// setDontFragment sets or clears the don't fragment bit on the network sockets.
// Network must be "udp4" or "udp6".
func (c *Conn) setDontFragment(network string, enable bool) error {
optArg := dontFragEnabled
if !enable {
optArg = dontFragDisabled
}
rc, err := sc.SyscallConn()
if err != nil {
return err
}
return rc.Control(fn)
return c.connControl(network, func(fd uintptr) error {
return syscall.SetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network), optArg)
})
}
// getDontFragment reports whether the network sockets have the don't fragment bit set.
func (c *Conn) getDontFragment(network string) (bool, error) {
var set bool
err := c.connControl(network, func(fd uintptr) error {
v, err := syscall.GetsockoptInt(int(fd), getIPProto(network), getDontFragOpt(network))
if err != nil {
return err
}
set = v == dontFragEnabled
return nil
})
return set, err
}