mirror of
https://github.com/tailscale/tailscale.git
synced 2025-06-11 02:08:36 +00:00
go.mod,wgengine/magicsock: update wireguard-go (#16148)
Our conn.Bind implementation is updated to make Send() offset-aware for future VXLAN/Geneve encapsulation support. Updates tailscale/corp#27502 Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
parent
c9a5d638e9
commit
5f35143d83
2
go.mod
2
go.mod
@ -90,7 +90,7 @@ require (
|
|||||||
github.com/tailscale/setec v0.0.0-20250205144240-8898a29c3fbb
|
github.com/tailscale/setec v0.0.0-20250205144240-8898a29c3fbb
|
||||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976
|
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976
|
||||||
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6
|
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250304000100-91a0587fb251
|
github.com/tailscale/wireguard-go v0.0.0-20250530210235-65cd6eed7d7f
|
||||||
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e
|
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e
|
||||||
github.com/tc-hib/winres v0.2.1
|
github.com/tc-hib/winres v0.2.1
|
||||||
github.com/tcnksm/go-httpstat v0.2.0
|
github.com/tcnksm/go-httpstat v0.2.0
|
||||||
|
4
go.sum
4
go.sum
@ -975,8 +975,8 @@ github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 h1:U
|
|||||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976/go.mod h1:agQPE6y6ldqCOui2gkIh7ZMztTkIQKH049tv8siLuNQ=
|
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976/go.mod h1:agQPE6y6ldqCOui2gkIh7ZMztTkIQKH049tv8siLuNQ=
|
||||||
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6 h1:l10Gi6w9jxvinoiq15g8OToDdASBni4CyJOdHY1Hr8M=
|
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6 h1:l10Gi6w9jxvinoiq15g8OToDdASBni4CyJOdHY1Hr8M=
|
||||||
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6/go.mod h1:ZXRML051h7o4OcI0d3AaILDIad/Xw0IkXaHM17dic1Y=
|
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6/go.mod h1:ZXRML051h7o4OcI0d3AaILDIad/Xw0IkXaHM17dic1Y=
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250304000100-91a0587fb251 h1:h/41LFTrwMxB9Xvvug0kRdQCU5TlV1+pAMQw0ZtDE3U=
|
github.com/tailscale/wireguard-go v0.0.0-20250530210235-65cd6eed7d7f h1:vg3PmQdq1BbB2V81iC1VBICQtfwbVGZ/4A/p7QKXTK0=
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250304000100-91a0587fb251/go.mod h1:BOm5fXUBFM+m9woLNBoxI9TaBXXhGNP50LX/TGIvGb4=
|
github.com/tailscale/wireguard-go v0.0.0-20250530210235-65cd6eed7d7f/go.mod h1:BOm5fXUBFM+m9woLNBoxI9TaBXXhGNP50LX/TGIvGb4=
|
||||||
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e h1:zOGKqN5D5hHhiYUp091JqK7DPCqSARyUfduhGUY8Bek=
|
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e h1:zOGKqN5D5hHhiYUp091JqK7DPCqSARyUfduhGUY8Bek=
|
||||||
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e/go.mod h1:orPd6JZXXRyuDusYilywte7k094d7dycXXU5YnWsrwg=
|
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e/go.mod h1:orPd6JZXXRyuDusYilywte7k094d7dycXXU5YnWsrwg=
|
||||||
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
||||||
|
@ -21,5 +21,5 @@ var (
|
|||||||
type batchingConn interface {
|
type batchingConn interface {
|
||||||
nettype.PacketConn
|
nettype.PacketConn
|
||||||
ReadBatch(msgs []ipv6.Message, flags int) (n int, err error)
|
ReadBatch(msgs []ipv6.Message, flags int) (n int, err error)
|
||||||
WriteBatchTo(buffs [][]byte, addr netip.AddrPort) error
|
WriteBatchTo(buffs [][]byte, addr netip.AddrPort, offset int) error
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ const (
|
|||||||
|
|
||||||
// coalesceMessages iterates msgs, coalescing them where possible while
|
// coalesceMessages iterates msgs, coalescing them where possible while
|
||||||
// maintaining datagram order. All msgs have their Addr field set to addr.
|
// maintaining datagram order. All msgs have their Addr field set to addr.
|
||||||
func (c *linuxBatchingConn) coalesceMessages(addr *net.UDPAddr, buffs [][]byte, msgs []ipv6.Message) int {
|
func (c *linuxBatchingConn) coalesceMessages(addr *net.UDPAddr, buffs [][]byte, msgs []ipv6.Message, offset int) int {
|
||||||
var (
|
var (
|
||||||
base = -1 // index of msg we are currently coalescing into
|
base = -1 // index of msg we are currently coalescing into
|
||||||
gsoSize int // segmentation size of msgs[base]
|
gsoSize int // segmentation size of msgs[base]
|
||||||
@ -106,6 +106,7 @@ func (c *linuxBatchingConn) coalesceMessages(addr *net.UDPAddr, buffs [][]byte,
|
|||||||
maxPayloadLen = maxIPv6PayloadLen
|
maxPayloadLen = maxIPv6PayloadLen
|
||||||
}
|
}
|
||||||
for i, buff := range buffs {
|
for i, buff := range buffs {
|
||||||
|
buff = buff[offset:]
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
msgLen := len(buff)
|
msgLen := len(buff)
|
||||||
baseLenBefore := len(msgs[base].Buffers[0])
|
baseLenBefore := len(msgs[base].Buffers[0])
|
||||||
@ -162,7 +163,7 @@ func (c *linuxBatchingConn) putSendBatch(batch *sendBatch) {
|
|||||||
c.sendBatchPool.Put(batch)
|
c.sendBatchPool.Put(batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linuxBatchingConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort) error {
|
func (c *linuxBatchingConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort, offset int) error {
|
||||||
batch := c.getSendBatch()
|
batch := c.getSendBatch()
|
||||||
defer c.putSendBatch(batch)
|
defer c.putSendBatch(batch)
|
||||||
if addr.Addr().Is6() {
|
if addr.Addr().Is6() {
|
||||||
@ -181,10 +182,10 @@ func (c *linuxBatchingConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort) er
|
|||||||
)
|
)
|
||||||
retry:
|
retry:
|
||||||
if c.txOffload.Load() {
|
if c.txOffload.Load() {
|
||||||
n = c.coalesceMessages(batch.ua, buffs, batch.msgs)
|
n = c.coalesceMessages(batch.ua, buffs, batch.msgs, offset)
|
||||||
} else {
|
} else {
|
||||||
for i := range buffs {
|
for i := range buffs {
|
||||||
batch.msgs[i].Buffers[0] = buffs[i]
|
batch.msgs[i].Buffers[0] = buffs[i][offset:]
|
||||||
batch.msgs[i].Addr = batch.ua
|
batch.msgs[i].Addr = batch.ua
|
||||||
batch.msgs[i].OOB = batch.msgs[i].OOB[:0]
|
batch.msgs[i].OOB = batch.msgs[i].OOB[:0]
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
|
"tailscale.com/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setGSOSize(control *[]byte, gsoSize uint16) {
|
func setGSOSize(control *[]byte, gsoSize uint16) {
|
||||||
@ -154,6 +155,10 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
getGSOSizeFromControl: getGSOSize,
|
getGSOSizeFromControl: getGSOSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withGeneveSpace := func(len, cap int) []byte {
|
||||||
|
return make([]byte, len+packet.GeneveFixedHeaderLength, cap+packet.GeneveFixedHeaderLength)
|
||||||
|
}
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
buffs [][]byte
|
buffs [][]byte
|
||||||
@ -163,7 +168,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "one message no coalesce",
|
name: "one message no coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
make([]byte, 1, 1),
|
withGeneveSpace(1, 1),
|
||||||
},
|
},
|
||||||
wantLens: []int{1},
|
wantLens: []int{1},
|
||||||
wantGSO: []int{0},
|
wantGSO: []int{0},
|
||||||
@ -171,8 +176,8 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "two messages equal len coalesce",
|
name: "two messages equal len coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
make([]byte, 1, 2),
|
withGeneveSpace(1, 2),
|
||||||
make([]byte, 1, 1),
|
withGeneveSpace(1, 1),
|
||||||
},
|
},
|
||||||
wantLens: []int{2},
|
wantLens: []int{2},
|
||||||
wantGSO: []int{1},
|
wantGSO: []int{1},
|
||||||
@ -180,8 +185,8 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "two messages unequal len coalesce",
|
name: "two messages unequal len coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
make([]byte, 2, 3),
|
withGeneveSpace(2, 3),
|
||||||
make([]byte, 1, 1),
|
withGeneveSpace(1, 1),
|
||||||
},
|
},
|
||||||
wantLens: []int{3},
|
wantLens: []int{3},
|
||||||
wantGSO: []int{2},
|
wantGSO: []int{2},
|
||||||
@ -189,9 +194,9 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "three messages second unequal len coalesce",
|
name: "three messages second unequal len coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
make([]byte, 2, 3),
|
withGeneveSpace(2, 3),
|
||||||
make([]byte, 1, 1),
|
withGeneveSpace(1, 1),
|
||||||
make([]byte, 2, 2),
|
withGeneveSpace(2, 2),
|
||||||
},
|
},
|
||||||
wantLens: []int{3, 2},
|
wantLens: []int{3, 2},
|
||||||
wantGSO: []int{2, 0},
|
wantGSO: []int{2, 0},
|
||||||
@ -199,9 +204,9 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "three messages limited cap coalesce",
|
name: "three messages limited cap coalesce",
|
||||||
buffs: [][]byte{
|
buffs: [][]byte{
|
||||||
make([]byte, 2, 4),
|
withGeneveSpace(2, 4),
|
||||||
make([]byte, 2, 2),
|
withGeneveSpace(2, 2),
|
||||||
make([]byte, 2, 2),
|
withGeneveSpace(2, 2),
|
||||||
},
|
},
|
||||||
wantLens: []int{4, 2},
|
wantLens: []int{4, 2},
|
||||||
wantGSO: []int{2, 0},
|
wantGSO: []int{2, 0},
|
||||||
@ -219,7 +224,7 @@ func Test_linuxBatchingConn_coalesceMessages(t *testing.T) {
|
|||||||
msgs[i].Buffers = make([][]byte, 1)
|
msgs[i].Buffers = make([][]byte, 1)
|
||||||
msgs[i].OOB = make([]byte, 0, 2)
|
msgs[i].OOB = make([]byte, 0, 2)
|
||||||
}
|
}
|
||||||
got := c.coalesceMessages(addr, tt.buffs, msgs)
|
got := c.coalesceMessages(addr, tt.buffs, msgs, packet.GeneveFixedHeaderLength)
|
||||||
if got != len(tt.wantLens) {
|
if got != len(tt.wantLens) {
|
||||||
t.Fatalf("got len %d want: %d", got, len(tt.wantLens))
|
t.Fatalf("got len %d want: %d", got, len(tt.wantLens))
|
||||||
}
|
}
|
||||||
|
@ -927,7 +927,7 @@ var (
|
|||||||
errPingTooBig = errors.New("ping size too big")
|
errPingTooBig = errors.New("ping size too big")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (de *endpoint) send(buffs [][]byte) error {
|
func (de *endpoint) send(buffs [][]byte, offset int) error {
|
||||||
de.mu.Lock()
|
de.mu.Lock()
|
||||||
if de.expired {
|
if de.expired {
|
||||||
de.mu.Unlock()
|
de.mu.Unlock()
|
||||||
@ -961,7 +961,7 @@ func (de *endpoint) send(buffs [][]byte) error {
|
|||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if udpAddr.IsValid() {
|
if udpAddr.IsValid() {
|
||||||
_, err = de.c.sendUDPBatch(udpAddr, buffs)
|
_, err = de.c.sendUDPBatch(udpAddr, buffs, offset)
|
||||||
|
|
||||||
// If the error is known to indicate that the endpoint is no longer
|
// If the error is known to indicate that the endpoint is no longer
|
||||||
// usable, clear the endpoint statistics so that the next send will
|
// usable, clear the endpoint statistics so that the next send will
|
||||||
@ -972,7 +972,7 @@ func (de *endpoint) send(buffs [][]byte) error {
|
|||||||
|
|
||||||
var txBytes int
|
var txBytes int
|
||||||
for _, b := range buffs {
|
for _, b := range buffs {
|
||||||
txBytes += len(b)
|
txBytes += len(b[offset:])
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -993,6 +993,7 @@ func (de *endpoint) send(buffs [][]byte) error {
|
|||||||
allOk := true
|
allOk := true
|
||||||
var txBytes int
|
var txBytes int
|
||||||
for _, buff := range buffs {
|
for _, buff := range buffs {
|
||||||
|
buff = buff[offset:]
|
||||||
const isDisco = false
|
const isDisco = false
|
||||||
ok, _ := de.c.sendAddr(derpAddr, de.publicKey, buff, isDisco)
|
ok, _ := de.c.sendAddr(derpAddr, de.publicKey, buff, isDisco)
|
||||||
txBytes += len(buff)
|
txBytes += len(buff)
|
||||||
|
@ -1264,8 +1264,8 @@ func (c *Conn) networkDown() bool { return !c.networkUp.Load() }
|
|||||||
|
|
||||||
// Send implements conn.Bind.
|
// Send implements conn.Bind.
|
||||||
//
|
//
|
||||||
// See https://pkg.go.dev/golang.zx2c4.com/wireguard/conn#Bind.Send
|
// See https://pkg.go.dev/github.com/tailscale/wireguard-go/conn#Bind.Send
|
||||||
func (c *Conn) Send(buffs [][]byte, ep conn.Endpoint) (err error) {
|
func (c *Conn) Send(buffs [][]byte, ep conn.Endpoint, offset int) (err error) {
|
||||||
n := int64(len(buffs))
|
n := int64(len(buffs))
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1278,7 +1278,7 @@ func (c *Conn) Send(buffs [][]byte, ep conn.Endpoint) (err error) {
|
|||||||
return errNetworkDown
|
return errNetworkDown
|
||||||
}
|
}
|
||||||
if ep, ok := ep.(*endpoint); ok {
|
if ep, ok := ep.(*endpoint); ok {
|
||||||
return ep.send(buffs)
|
return ep.send(buffs, offset)
|
||||||
}
|
}
|
||||||
// If it's not of type *endpoint, it's probably *lazyEndpoint, which means
|
// If it's not of type *endpoint, it's probably *lazyEndpoint, which means
|
||||||
// we don't actually know who the peer is and we're waiting for wireguard-go
|
// we don't actually know who the peer is and we're waiting for wireguard-go
|
||||||
@ -1294,7 +1294,7 @@ var errNoUDP = errors.New("no UDP available on platform")
|
|||||||
|
|
||||||
var errUnsupportedConnType = errors.New("unsupported connection type")
|
var errUnsupportedConnType = errors.New("unsupported connection type")
|
||||||
|
|
||||||
func (c *Conn) sendUDPBatch(addr netip.AddrPort, buffs [][]byte) (sent bool, err error) {
|
func (c *Conn) sendUDPBatch(addr netip.AddrPort, buffs [][]byte, offset int) (sent bool, err error) {
|
||||||
isIPv6 := false
|
isIPv6 := false
|
||||||
switch {
|
switch {
|
||||||
case addr.Addr().Is4():
|
case addr.Addr().Is4():
|
||||||
@ -1304,9 +1304,9 @@ func (c *Conn) sendUDPBatch(addr netip.AddrPort, buffs [][]byte) (sent bool, err
|
|||||||
panic("bogus sendUDPBatch addr type")
|
panic("bogus sendUDPBatch addr type")
|
||||||
}
|
}
|
||||||
if isIPv6 {
|
if isIPv6 {
|
||||||
err = c.pconn6.WriteBatchTo(buffs, addr)
|
err = c.pconn6.WriteBatchTo(buffs, addr, offset)
|
||||||
} else {
|
} else {
|
||||||
err = c.pconn4.WriteBatchTo(buffs, addr)
|
err = c.pconn4.WriteBatchTo(buffs, addr, offset)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errGSO neterror.ErrUDPGSODisabled
|
var errGSO neterror.ErrUDPGSODisabled
|
||||||
|
@ -3147,7 +3147,7 @@ func TestNetworkDownSendErrors(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
conn.SetNetworkUp(false)
|
conn.SetNetworkUp(false)
|
||||||
if err := conn.Send([][]byte{{00}}, &lazyEndpoint{}); err == nil {
|
if err := conn.Send([][]byte{{00}}, &lazyEndpoint{}, 0); err == nil {
|
||||||
t.Error("expected error, got nil")
|
t.Error("expected error, got nil")
|
||||||
}
|
}
|
||||||
resp := httptest.NewRecorder()
|
resp := httptest.NewRecorder()
|
||||||
|
@ -71,12 +71,13 @@ func (c *RebindingUDPConn) ReadFromUDPAddrPort(b []byte) (int, netip.AddrPort, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteBatchTo writes buffs to addr.
|
// WriteBatchTo writes buffs to addr.
|
||||||
func (c *RebindingUDPConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort) error {
|
func (c *RebindingUDPConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort, offset int) error {
|
||||||
for {
|
for {
|
||||||
pconn := *c.pconnAtomic.Load()
|
pconn := *c.pconnAtomic.Load()
|
||||||
b, ok := pconn.(batchingConn)
|
b, ok := pconn.(batchingConn)
|
||||||
if !ok {
|
if !ok {
|
||||||
for _, buf := range buffs {
|
for _, buf := range buffs {
|
||||||
|
buf = buf[offset:]
|
||||||
_, err := c.writeToUDPAddrPortWithInitPconn(pconn, buf, addr)
|
_, err := c.writeToUDPAddrPortWithInitPconn(pconn, buf, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -84,7 +85,7 @@ func (c *RebindingUDPConn) WriteBatchTo(buffs [][]byte, addr netip.AddrPort) err
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err := b.WriteBatchTo(buffs, addr)
|
err := b.WriteBatchTo(buffs, addr, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if pconn != c.currentConn() {
|
if pconn != c.currentConn() {
|
||||||
continue
|
continue
|
||||||
|
@ -242,9 +242,9 @@ type noopBind struct{}
|
|||||||
func (noopBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
func (noopBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
||||||
return nil, 1, nil
|
return nil, 1, nil
|
||||||
}
|
}
|
||||||
func (noopBind) Close() error { return nil }
|
func (noopBind) Close() error { return nil }
|
||||||
func (noopBind) SetMark(mark uint32) error { return nil }
|
func (noopBind) SetMark(mark uint32) error { return nil }
|
||||||
func (noopBind) Send(b [][]byte, ep conn.Endpoint) error { return nil }
|
func (noopBind) Send(b [][]byte, ep conn.Endpoint, offset int) error { return nil }
|
||||||
func (noopBind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
func (noopBind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
||||||
return dummyEndpoint(s), nil
|
return dummyEndpoint(s), nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user