wgengine: unify NewUserspaceEngine, NewUserspaceEngineAdvanced

Also rename EngineConfig to Config to avoid wgengine.EngineConfig
stutter.

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2021-02-27 21:42:34 -08:00
parent dda03a911e
commit ee6475a44d
4 changed files with 84 additions and 75 deletions

View File

@ -12,7 +12,10 @@ depaware:
go run github.com/tailscale/depaware --check tailscale.com/cmd/tailscaled go run github.com/tailscale/depaware --check tailscale.com/cmd/tailscaled
go run github.com/tailscale/depaware --check tailscale.com/cmd/tailscale go run github.com/tailscale/depaware --check tailscale.com/cmd/tailscale
check: staticcheck vet depaware buildwindows:
GOOS=windows GOARCH=amd64 go install tailscale.com/cmd/tailscale tailscale.com/cmd/tailscaled
check: staticcheck vet depaware buildwindows
staticcheck: staticcheck:
go run honnef.co/go/tools/cmd/staticcheck -- $$(go list ./... | grep -v tempfork) go run honnef.co/go/tools/cmd/staticcheck -- $$(go list ./... | grep -v tempfork)

View File

@ -198,7 +198,10 @@ func run() error {
} }
e, err = wgengine.NewFakeUserspaceEngine(logf, 0, impl) e, err = wgengine.NewFakeUserspaceEngine(logf, 0, impl)
} else { } else {
e, err = wgengine.NewUserspaceEngine(logf, args.tunname, args.port) e, err = wgengine.NewUserspaceEngine(logf, wgengine.Config{
TUNName: args.tunname,
ListenPort: args.port,
})
} }
if err != nil { if err != nil {
logf("wgengine.New: %v", err) logf("wgengine.New: %v", err)

View File

@ -114,7 +114,10 @@ func startIPNServer(ctx context.Context, logid string) error {
var err error var err error
getEngine := func() (wgengine.Engine, error) { getEngine := func() (wgengine.Engine, error) {
eng, err := wgengine.NewUserspaceEngine(logf, "Tailscale", 41641) eng, err := wgengine.NewUserspaceEngine(logf, wgengine.Config{
TUNName: "Tailscale",
ListenPort: 41641,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -85,17 +85,18 @@
) )
type userspaceEngine struct { type userspaceEngine struct {
logf logger.Logf logf logger.Logf
wgLogger *wglog.Logger //a wireguard-go logging wrapper wgLogger *wglog.Logger //a wireguard-go logging wrapper
reqCh chan struct{} reqCh chan struct{}
waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool waitCh chan struct{} // chan is closed when first Close call completes; contrast with closing bool
timeNow func() time.Time timeNow func() time.Time
tundev *tstun.TUN tundev *tstun.TUN
wgdev *device.Device wgdev *device.Device
router router.Router router router.Router
resolver *tsdns.Resolver resolver *tsdns.Resolver
magicConn *magicsock.Conn magicConn *magicsock.Conn
linkMon *monitor.Mon linkMon *monitor.Mon
linkMonUnregister func() // unsubscribes from changes; used regardless of linkMonOwned
testMaybeReconfigHook func() // for tests; if non-nil, fires if maybeReconfigWireguardLocked called testMaybeReconfigHook func() // for tests; if non-nil, fires if maybeReconfigWireguardLocked called
@ -133,15 +134,24 @@ type userspaceEngine struct {
// router.Router. // router.Router.
type RouterGen func(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (router.Router, error) type RouterGen func(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (router.Router, error)
type EngineConfig struct { // Config is the engine configuration.
// Logf is the logging function used by the engine. type Config struct {
Logf logger.Logf // TUN is the TUN device used by the engine.
// TUN is the tun device used by the engine. // Exactly one of either TUN or TUNName must be specified.
TUN tun.Device TUN tun.Device
// TUNName is the TUN device to create.
// Exactly one of either TUN or TUNName must be specified.
TUNName string
// RouterGen is the function used to instantiate the router. // RouterGen is the function used to instantiate the router.
// If nil, wgengine/router.New is used.
RouterGen RouterGen RouterGen RouterGen
// ListenPort is the port on which the engine will listen. // ListenPort is the port on which the engine will listen.
// If zero, a port is automatically selected.
ListenPort uint16 ListenPort uint16
// Fake determines whether this engine is running in fake mode, // Fake determines whether this engine is running in fake mode,
// which disables such features as DNS configuration and unrestricted ICMP Echo responses. // which disables such features as DNS configuration and unrestricted ICMP Echo responses.
Fake bool Fake bool
@ -156,7 +166,7 @@ type EngineConfig struct {
} }
// FakeImpl is a fake or alternate version of Engine that can be started. See // FakeImpl is a fake or alternate version of Engine that can be started. See
// EngineConfig.FakeImplFactory for details. // Config.FakeImplFactory for details.
type FakeImpl interface { type FakeImpl interface {
Start() error Start() error
} }
@ -166,78 +176,54 @@ type FakeImpl interface {
func NewFakeUserspaceEngine(logf logger.Logf, listenPort uint16, impl FakeImplFactory) (Engine, error) { func NewFakeUserspaceEngine(logf logger.Logf, listenPort uint16, impl FakeImplFactory) (Engine, error) {
logf("Starting userspace wireguard engine (with fake TUN device)") logf("Starting userspace wireguard engine (with fake TUN device)")
conf := EngineConfig{ return NewUserspaceEngine(logf, Config{
Logf: logf,
TUN: tstun.NewFakeTUN(), TUN: tstun.NewFakeTUN(),
RouterGen: router.NewFake, RouterGen: router.NewFake,
ListenPort: listenPort, ListenPort: listenPort,
Fake: true, Fake: true,
FakeImplFactory: impl, FakeImplFactory: impl,
} })
return NewUserspaceEngineAdvanced(conf)
} }
// NewUserspaceEngine creates the named tun device and returns a // NewUserspaceEngine creates the named tun device and returns a
// Tailscale Engine running on it. // Tailscale Engine running on it.
func NewUserspaceEngine(logf logger.Logf, tunName string, listenPort uint16) (Engine, error) { func NewUserspaceEngine(logf logger.Logf, conf Config) (Engine, error) {
if tunName == "" { if conf.TUN != nil && conf.TUNName != "" {
return nil, fmt.Errorf("--tun name must not be blank") return nil, errors.New("TUN and TUNName are mutually exclusive")
} }
if conf.TUN == nil && conf.TUNName == "" {
logf("Starting userspace wireguard engine with tun device %q", tunName) return nil, errors.New("either TUN or TUNName are required")
tun, err := tun.CreateTUN(tunName, minimalMTU)
if err != nil {
diagnoseTUNFailure(tunName, logf)
logf("CreateTUN: %v", err)
return nil, err
} }
logf("CreateTUN ok.") tunDev := conf.TUN
var err error
if tunName := conf.TUNName; tunName != "" {
logf("Starting userspace wireguard engine with tun device %q", tunName)
tunDev, err = tun.CreateTUN(tunName, minimalMTU)
if err != nil {
diagnoseTUNFailure(tunName, logf)
logf("CreateTUN: %v", err)
return nil, err
}
logf("CreateTUN ok.")
if err := waitInterfaceUp(tun, 90*time.Second, logf); err != nil { if err := waitInterfaceUp(tunDev, 90*time.Second, logf); err != nil {
return nil, err return nil, err
}
conf := EngineConfig{
Logf: logf,
TUN: tun,
RouterGen: router.New,
ListenPort: listenPort,
}
e, err := NewUserspaceEngineAdvanced(conf)
if err != nil {
return nil, err
}
return e, err
}
type closeOnErrorPool []func()
func (p *closeOnErrorPool) add(c io.Closer) { *p = append(*p, func() { c.Close() }) }
func (p *closeOnErrorPool) addFunc(fn func()) { *p = append(*p, fn) }
func (p closeOnErrorPool) closeAllIfError(errp *error) {
if *errp != nil {
for _, closeFn := range p {
closeFn()
} }
} }
if conf.RouterGen == nil {
conf.RouterGen = router.New
}
return newUserspaceEngine(logf, tunDev, conf)
} }
// NewUserspaceEngineAdvanced is like NewUserspaceEngine func newUserspaceEngine(logf logger.Logf, rawTUNDev tun.Device, conf Config) (_ Engine, reterr error) {
// but provides control over all config fields.
func NewUserspaceEngineAdvanced(conf EngineConfig) (Engine, error) {
return newUserspaceEngineAdvanced(conf)
}
func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
logf := conf.Logf
var closePool closeOnErrorPool var closePool closeOnErrorPool
defer closePool.closeAllIfError(&reterr) defer closePool.closeAllIfError(&reterr)
tunDev := tstun.WrapTUN(logf, conf.TUN) tsTUNDev := tstun.WrapTUN(logf, rawTUNDev)
closePool.add(tunDev) closePool.add(tsTUNDev)
rconf := tsdns.ResolverConfig{ rconf := tsdns.ResolverConfig{
Logf: logf, Logf: logf,
@ -248,7 +234,7 @@ func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
logf: logf, logf: logf,
reqCh: make(chan struct{}, 1), reqCh: make(chan struct{}, 1),
waitCh: make(chan struct{}), waitCh: make(chan struct{}),
tundev: tunDev, tundev: tsTUNDev,
resolver: tsdns.NewResolver(rconf), resolver: tsdns.NewResolver(rconf),
pingers: make(map[wgkey.Key]*pinger), pingers: make(map[wgkey.Key]*pinger),
} }
@ -261,12 +247,13 @@ func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
return nil, err return nil, err
} }
closePool.add(mon) closePool.add(mon)
unregisterMonWatch := mon.RegisterChangeCallback(func() { e.linkMon = mon
unregisterMonWatch := e.linkMon.RegisterChangeCallback(func() {
e.LinkChange(false) e.LinkChange(false)
tshttpproxy.InvalidateCache() tshttpproxy.InvalidateCache()
}) })
closePool.addFunc(unregisterMonWatch) closePool.addFunc(unregisterMonWatch)
e.linkMon = mon e.linkMonUnregister = unregisterMonWatch
endpointsFn := func(endpoints []string) { endpointsFn := func(endpoints []string) {
e.mu.Lock() e.mu.Lock()
@ -1249,6 +1236,7 @@ func (e *userspaceEngine) Close() {
e.wgdev.IpcSetOperation(r) e.wgdev.IpcSetOperation(r)
e.resolver.Close() e.resolver.Close()
e.magicConn.Close() e.magicConn.Close()
e.linkMonUnregister()
e.linkMon.Close() e.linkMon.Close()
e.router.Close() e.router.Close()
e.wgdev.Close() e.wgdev.Close()
@ -1475,3 +1463,15 @@ func diagnoseLinuxTUNFailure(tunName string, logf logger.Logf) {
} }
} }
} }
type closeOnErrorPool []func()
func (p *closeOnErrorPool) add(c io.Closer) { *p = append(*p, func() { c.Close() }) }
func (p *closeOnErrorPool) addFunc(fn func()) { *p = append(*p, fn) }
func (p closeOnErrorPool) closeAllIfError(errp *error) {
if *errp != nil {
for _, closeFn := range p {
closeFn()
}
}
}