mirror of
https://github.com/tailscale/tailscale.git
synced 2026-10-23 03:37:19 +09:00
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:
1 parent
e9d5cdc323
commit
3bdf85ab6f
4 files changed
+52
-87
No files matched your search
@@ -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,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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user