Skip to content

Commit ad1cc6c

Browse files
committed
wgengine: use Go API rather than UAPI for status
Signed-off-by: James Tucker <james@tailscale.com>
1 parent 68d9d16 commit ad1cc6c

File tree

2 files changed

+25
-109
lines changed

2 files changed

+25
-109
lines changed

cmd/tailscaled/depaware.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
296296
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
297297
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
298298
tailscale.com/wgengine/wgcfg/nmcfg from tailscale.com/ipn/ipnlocal
299+
💣 tailscale.com/wgengine/wgint from tailscale.com/wgengine
299300
tailscale.com/wgengine/wglog from tailscale.com/wgengine
300301
W 💣 tailscale.com/wgengine/winnet from tailscale.com/wgengine/router
301302
golang.org/x/crypto/acme from tailscale.com/ipn/localapi

wgengine/userspace.go

Lines changed: 24 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package wgengine
66

77
import (
88
"bufio"
9-
"bytes"
109
crand "crypto/rand"
1110
"errors"
1211
"fmt"
@@ -19,7 +18,6 @@ import (
1918
"sync"
2019
"time"
2120

22-
"go4.org/mem"
2321
"golang.zx2c4.com/wireguard/device"
2422
"golang.zx2c4.com/wireguard/tun"
2523
"tailscale.com/control/controlclient"
@@ -53,6 +51,7 @@ import (
5351
"tailscale.com/wgengine/monitor"
5452
"tailscale.com/wgengine/router"
5553
"tailscale.com/wgengine/wgcfg"
54+
"tailscale.com/wgengine/wgint"
5655
"tailscale.com/wgengine/wglog"
5756
)
5857

@@ -990,126 +989,42 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
990989
derpConns := e.magicConn.DERPs()
991990

992991
e.wgLock.Lock()
993-
defer e.wgLock.Unlock()
994-
995-
e.mu.Lock()
996-
closing := e.closing
997-
e.mu.Unlock()
998-
if closing {
999-
return nil, ErrEngineClosing
1000-
}
992+
wgdev := e.wgdev
993+
e.wgLock.Unlock()
1001994

1002-
if e.wgdev == nil {
995+
// Assume that once created, wgdev is typically not replaced in-flight.
996+
if wgdev == nil {
1003997
// RequestStatus was invoked before the wgengine has
1004998
// finished initializing. This can happen when wgegine
1005999
// provides a callback to magicsock for endpoint
10061000
// updates that calls RequestStatus.
10071001
return nil, nil
10081002
}
10091003

1010-
pr, pw := io.Pipe()
1011-
defer pr.Close() // to unblock writes on error path returns
1012-
1013-
errc := make(chan error, 1)
1014-
go func() {
1015-
defer pw.Close()
1016-
// TODO(apenwarr): get rid of silly uapi stuff for in-process comms
1017-
// FIXME: get notified of status changes instead of polling.
1018-
err := e.wgdev.IpcGetOperation(pw)
1019-
if err != nil {
1020-
err = fmt.Errorf("IpcGetOperation: %w", err)
1021-
}
1022-
errc <- err
1023-
}()
1024-
1025-
pp := make(map[key.NodePublic]ipnstate.PeerStatusLite)
1026-
var p ipnstate.PeerStatusLite
1027-
1028-
var hst1, hst2, n int64
1029-
1030-
br := e.statusBufioReader
1031-
if br != nil {
1032-
br.Reset(pr)
1033-
} else {
1034-
br = bufio.NewReaderSize(pr, 1<<10)
1035-
e.statusBufioReader = br
1036-
}
1037-
for {
1038-
line, err := br.ReadSlice('\n')
1039-
if err == io.EOF {
1040-
break
1041-
}
1042-
if err != nil {
1043-
return nil, fmt.Errorf("reading from UAPI pipe: %w", err)
1044-
}
1045-
line = bytes.TrimSuffix(line, singleNewline)
1046-
k := line
1047-
var v mem.RO
1048-
if i := bytes.IndexByte(line, '='); i != -1 {
1049-
k = line[:i]
1050-
v = mem.B(line[i+1:])
1051-
}
1052-
switch string(k) {
1053-
case "public_key":
1054-
pk, err := key.ParseNodePublicUntyped(v)
1055-
if err != nil {
1056-
return nil, fmt.Errorf("IpcGetOperation: invalid key in line %q", line)
1057-
}
1058-
if !p.NodeKey.IsZero() {
1059-
pp[p.NodeKey] = p
1060-
}
1061-
p = ipnstate.PeerStatusLite{NodeKey: pk}
1062-
case "rx_bytes":
1063-
n, err = mem.ParseInt(v, 10, 64)
1064-
p.RxBytes = n
1065-
if err != nil {
1066-
return nil, fmt.Errorf("IpcGetOperation: rx_bytes invalid: %#v", line)
1067-
}
1068-
case "tx_bytes":
1069-
n, err = mem.ParseInt(v, 10, 64)
1070-
p.TxBytes = n
1071-
if err != nil {
1072-
return nil, fmt.Errorf("IpcGetOperation: tx_bytes invalid: %#v", line)
1073-
}
1074-
case "last_handshake_time_sec":
1075-
hst1, err = mem.ParseInt(v, 10, 64)
1076-
if err != nil {
1077-
return nil, fmt.Errorf("IpcGetOperation: hst1 invalid: %#v", line)
1078-
}
1079-
case "last_handshake_time_nsec":
1080-
hst2, err = mem.ParseInt(v, 10, 64)
1081-
if err != nil {
1082-
return nil, fmt.Errorf("IpcGetOperation: hst2 invalid: %#v", line)
1083-
}
1084-
if hst1 != 0 || hst2 != 0 {
1085-
p.LastHandshake = time.Unix(hst1, hst2)
1086-
} // else leave at time.IsZero()
1087-
}
1088-
}
1089-
if !p.NodeKey.IsZero() {
1090-
pp[p.NodeKey] = p
1091-
}
1092-
if err := <-errc; err != nil {
1093-
return nil, fmt.Errorf("IpcGetOperation: %v", err)
1094-
}
1095-
10961004
e.mu.Lock()
1097-
defer e.mu.Unlock()
1005+
closing := e.closing
1006+
peerKeys := make([]key.NodePublic, len(e.peerSequence))
1007+
copy(peerKeys, e.peerSequence)
1008+
e.mu.Unlock()
10981009

1099-
// Do two passes, one to calculate size and the other to populate.
1100-
// This code is sensitive to allocations.
1101-
npeers := 0
1102-
for _, pk := range e.peerSequence {
1103-
if _, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
1104-
npeers++
1105-
}
1010+
if closing {
1011+
return nil, ErrEngineClosing
11061012
}
11071013

1108-
peers := make([]ipnstate.PeerStatusLite, 0, npeers)
1109-
for _, pk := range e.peerSequence {
1110-
if p, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
1111-
peers = append(peers, p)
1014+
peers := make([]ipnstate.PeerStatusLite, 0, len(peerKeys))
1015+
for _, key := range peerKeys {
1016+
// LookupPeer is internally locked in wgdev.
1017+
peer := wgdev.LookupPeer(key.Raw32())
1018+
if peer == nil {
1019+
continue
11121020
}
1021+
1022+
var p ipnstate.PeerStatusLite
1023+
p.NodeKey = key
1024+
p.RxBytes = int64(wgint.PeerRxBytes(peer))
1025+
p.TxBytes = int64(wgint.PeerTxBytes(peer))
1026+
p.LastHandshake = time.Unix(0, wgint.PeerLastHandshakeNano(peer))
1027+
peers = append(peers, p)
11131028
}
11141029

11151030
return &Status{

0 commit comments

Comments
 (0)