ipn/ipnlocal: re-advertise appc routes on startup, take 2 (#14740)
* Reapply "ipn/ipnlocal: re-advertise appc routes on startup (#14609)"
This reverts commit 51adaec35a.
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
* ipn/ipnlocal: fix a deadlock in readvertiseAppConnectorRoutes
Don't hold LocalBackend.mu while calling the methods of
appc.AppConnector. Those methods could call back into LocalBackend and
try to acquire it's mutex.
Fixes https://github.com/tailscale/corp/issues/25965
Fixes #14606
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
---------
Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
@@ -1501,6 +1501,53 @@ func TestReconfigureAppConnector(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackfillAppConnectorRoutes(t *testing.T) {
|
||||
// Create backend with an empty app connector.
|
||||
b := newTestBackend(t)
|
||||
if err := b.Start(ipn.Options{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := b.EditPrefs(&ipn.MaskedPrefs{
|
||||
Prefs: ipn.Prefs{
|
||||
AppConnector: ipn.AppConnectorPrefs{Advertise: true},
|
||||
},
|
||||
AppConnectorSet: true,
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b.reconfigAppConnectorLocked(b.netMap, b.pm.prefs)
|
||||
|
||||
// Smoke check that AdvertiseRoutes doesn't have the test IP.
|
||||
ip := netip.MustParseAddr("1.2.3.4")
|
||||
routes := b.Prefs().AdvertiseRoutes().AsSlice()
|
||||
if slices.Contains(routes, netip.PrefixFrom(ip, ip.BitLen())) {
|
||||
t.Fatalf("AdvertiseRoutes %v on a fresh backend already contains advertised route for %v", routes, ip)
|
||||
}
|
||||
|
||||
// Store the test IP in profile data, but not in Prefs.AdvertiseRoutes.
|
||||
b.ControlKnobs().AppCStoreRoutes.Store(true)
|
||||
if err := b.storeRouteInfo(&appc.RouteInfo{
|
||||
Domains: map[string][]netip.Addr{
|
||||
"example.com": {ip},
|
||||
},
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Mimic b.authReconfigure for the app connector bits.
|
||||
b.mu.Lock()
|
||||
b.reconfigAppConnectorLocked(b.netMap, b.pm.prefs)
|
||||
b.mu.Unlock()
|
||||
b.readvertiseAppConnectorRoutes()
|
||||
|
||||
// Check that Prefs.AdvertiseRoutes got backfilled with routes stored in
|
||||
// profile data.
|
||||
routes = b.Prefs().AdvertiseRoutes().AsSlice()
|
||||
if !slices.Contains(routes, netip.PrefixFrom(ip, ip.BitLen())) {
|
||||
t.Fatalf("AdvertiseRoutes %v was not backfilled from stored app connector routes with %v", routes, ip)
|
||||
}
|
||||
}
|
||||
|
||||
func resolversEqual(t *testing.T, a, b []*dnstype.Resolver) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user