tailscale/wgengine/bird_hooks.go
Brad Fitzpatrick 3d07b5d6e1 wgengine,cmd/tailscaled,feature/bird: move BIRD integration to ./feature
The BIRD (BGP) integration previously lived half in cmd/tailscaled
(which created a chirp client via a build-tag-gated file on some
platforms) and half in wgengine (which carried the client in its
Config and toggled the "tailscale" protocol as the node gained or
lost primary subnet router duty).

Move it all to a new feature/bird package, installed on the engine
via the new wgengine.HookNewBird hook, like other feature/* packages.
wgengine.Config.BIRDClient (and the wgengine.BIRDClient interface)
are replaced by a BIRDSocket path from which the engine constructs
the feature's Bird handle at startup. The subnet router overlap
detection and protocol toggling move into feature/bird, preserving
the previous ordering: state is recomputed before Reconfig's
ErrNoChanges early return and applied after the router is configured.

tailscaled keeps BIRD support by default on the platforms that
previously had it (linux, darwin, freebsd, openbsd) via
feature/condregister.

Also, add an integration test, as this feature lacked much test
coverage previously.

Updates #12614

Change-Id: I7866a50779e454c87933b358735f7dcd9e2b126f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2026-07-14 10:48:09 -07:00

42 lines
1.6 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
package wgengine
import (
"tailscale.com/feature"
"tailscale.com/tailcfg"
"tailscale.com/types/logger"
)
// Bird is the engine's handle on the BIRD Internet Routing Daemon
// integration, implemented by the feature/bird package. It enables the
// "tailscale" protocol in BIRD while this node is a primary subnet
// router and disables it otherwise.
//
// Reconfig and ReconfigDone are only called from [Engine.Reconfig],
// serialized by the engine's internal lock. Close is called from
// [Engine.Close].
type Bird interface {
// Reconfig recomputes from the given self node whether this node is
// a primary subnet router. It is called near the top of every
// [Engine.Reconfig], before its ErrNoChanges early return. It
// reports whether the primary subnet router state changed, which
// suppresses the engine's ErrNoChanges early return.
Reconfig(self tailcfg.NodeView) (changed bool)
// ReconfigDone is called at the end of [Engine.Reconfig], after the
// router is configured, and applies any protocol state change
// computed by the preceding Reconfig call.
ReconfigDone()
// Close disables the protocol and closes the connection to BIRD.
Close()
}
// HookNewBird is set by the feature/bird package to construct each
// engine's [Bird], connecting to the BIRD unix socket at socketPath.
// If unset, BIRD integration is not linked into the binary and
// [Config.BIRDSocket] must not be set.
var HookNewBird feature.Hook[func(logf logger.Logf, socketPath string) (Bird, error)]