Compare commits

...

4 Commits

Author SHA1 Message Date
Claire Wang
f3da16b06a wip 2024-01-22 11:40:25 -05:00
Claire Wang
e92cb93ba7 wip 2024-01-16 20:19:07 -05:00
Claire Wang
50dbdfd02d magicsock: receive ICMP errors
Updates #311
2024-01-16 20:17:50 -05:00
Claire Wang
ae5ba8467e wip 2024-01-16 15:03:58 -05:00
4 changed files with 53 additions and 1 deletions

View File

@@ -1176,6 +1176,9 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu
if neterror.PacketWasTruncated(err) {
continue
}
if c.peerMTUEnabled.Load() {
ruc.ReadICMPErrors(batch.msgs[:len(buffs)], c.logf)
}
return 0, err
}
@@ -2377,7 +2380,9 @@ func (c *Conn) bindSocket(ruc *RebindingUDPConn, network string, curPortFate cur
}
}
trySetSocketBuffer(pconn, c.logf)
if c.peerMTUEnabled.Load() {
trySetIPRECEVRR(pconn, c.logf)
}
// Success.
if debugBindSocket() {
c.logf("magicsock: bindSocket: successfully listened %v port %d", network, port)

View File

@@ -31,6 +31,8 @@ func getGSOSizeFromControl(control []byte) (int, error) {
func setGSOSizeInControl(control *[]byte, gso uint16) {}
func trySetIPRECEVRR(pconn nettype.PacketConn, logf logger.Logf) {}
const (
controlMessageSize = 0
)

View File

@@ -318,6 +318,25 @@ func trySetSocketBuffer(pconn nettype.PacketConn, logf logger.Logf) {
}
}
// trySetSocketBuffer attempts to set SO_SNDBUFFORCE and SO_RECVBUFFORCE which
// can overcome the limit of net.core.{r,w}mem_max, but require CAP_NET_ADMIN.
// It falls back to the portable implementation if that fails, which may be
// silently capped to net.core.{r,w}mem_max.
func trySetIPRECEVRR(pconn nettype.PacketConn, logf logger.Logf) {
if c, ok := pconn.(*net.UDPConn); ok {
var errRcv error
rc, err := c.SyscallConn()
if err == nil {
rc.Control(func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVERR, 1)
if errRcv != nil {
logf("magicsock: [warning] failed to enable IP_RECVERR: %v", errRcv)
}
})
}
}
}
// tryEnableUDPOffload attempts to enable the UDP_GRO socket option on pconn,
// and returns two booleans indicating TX and RX UDP offload support.
func tryEnableUDPOffload(pconn nettype.PacketConn) (hasTX bool, hasRX bool) {

View File

@@ -10,9 +10,12 @@ import (
"sync"
"sync/atomic"
"syscall"
"unsafe"
"golang.org/x/net/ipv6"
"golang.org/x/sys/unix"
"tailscale.com/net/netaddr"
"tailscale.com/types/logger"
"tailscale.com/types/nettype"
)
@@ -177,3 +180,26 @@ func (c *RebindingUDPConn) SyscallConn() (syscall.RawConn, error) {
}
return sc.SyscallConn()
}
func (c *RebindingUDPConn) ReadICMPErrors(msgs []ipv6.Message, logf logger.Logf) (int, error) {
for {
rc, err := c.SyscallConn()
if err == nil {
rc.Control(func(fd uintptr) {
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVERR, 1)
var p = make([]byte, 1500)
var oob = make([]byte, 1500)
_, oobn, _, _, err := syscall.Recvmsg(int(fd), p, oob, syscall.MSG_ERRQUEUE)
if err != nil {
logf("magicsock: failed to receive ICMP message %v", err)
} else if oobn <= 0 {
logf("magicsock: failed to receive ICMP message oobn")
}
se := (*unix.SockExtendedErr)(unsafe.Pointer(&oob[syscall.SizeofCmsghdr]))
if se.Origin == 2 {
logf("magicsock: received ICMP error type %v info %v", se.Type, se.Info)
}
})
}
}
}