mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-12 00:52:00 +00:00
appc,ipn/ipnlocal,types/appctype: implement control provided routes
Control can now send down a set of routes along with the domains, and the routes will be advertised, with any newly overlapped routes being removed to reduce the size of the routing table. Fixes tailscale/corp#16833 Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
committed by
James Tucker
parent
543e7ed596
commit
24df1ef1ee
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
xmaps "golang.org/x/exp/maps"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"tailscale.com/util/mak"
|
||||
"tailscale.com/util/must"
|
||||
)
|
||||
|
||||
@@ -36,6 +37,30 @@ func TestUpdateDomains(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateRoutes(t *testing.T) {
|
||||
rc := &routeCollector{}
|
||||
a := NewAppConnector(t.Logf, rc)
|
||||
routes := []netip.Prefix{netip.MustParsePrefix("192.0.2.0/24")}
|
||||
a.UpdateRoutes(routes)
|
||||
|
||||
if !slices.EqualFunc(routes, rc.routes, prefixEqual) {
|
||||
t.Fatalf("got %v, want %v", rc.routes, routes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateRoutesUnadvertisesContainedRoutes(t *testing.T) {
|
||||
rc := &routeCollector{}
|
||||
a := NewAppConnector(t.Logf, rc)
|
||||
mak.Set(&a.domains, "example.com", []netip.Addr{netip.MustParseAddr("192.0.2.1")})
|
||||
rc.routes = []netip.Prefix{netip.MustParsePrefix("192.0.2.1/32")}
|
||||
routes := []netip.Prefix{netip.MustParsePrefix("192.0.2.0/24")}
|
||||
a.UpdateRoutes(routes)
|
||||
|
||||
if !slices.EqualFunc(routes, rc.routes, prefixEqual) {
|
||||
t.Fatalf("got %v, want %v", rc.routes, routes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomainRoutes(t *testing.T) {
|
||||
rc := &routeCollector{}
|
||||
a := NewAppConnector(t.Logf, rc)
|
||||
@@ -79,7 +104,19 @@ func TestObserveDNSResponse(t *testing.T) {
|
||||
// don't re-advertise routes that have already been advertised
|
||||
a.ObserveDNSResponse(dnsResponse("example.com.", "2001:db8::1"))
|
||||
if !slices.Equal(rc.routes, wantRoutes) {
|
||||
t.Errorf("got %v; want %v", rc.routes, wantRoutes)
|
||||
t.Errorf("rc.routes: got %v; want %v", rc.routes, wantRoutes)
|
||||
}
|
||||
|
||||
// don't advertise addresses that are already in a control provided route
|
||||
pfx := netip.MustParsePrefix("192.0.2.0/24")
|
||||
a.UpdateRoutes([]netip.Prefix{pfx})
|
||||
wantRoutes = append(wantRoutes, pfx)
|
||||
a.ObserveDNSResponse(dnsResponse("example.com.", "192.0.2.1"))
|
||||
if !slices.Equal(rc.routes, wantRoutes) {
|
||||
t.Errorf("rc.routes: got %v; want %v", rc.routes, wantRoutes)
|
||||
}
|
||||
if !slices.Contains(a.domains["example.com"], netip.MustParseAddr("192.0.2.1")) {
|
||||
t.Errorf("missing %v from %v", "192.0.2.1", a.domains["exmaple.com"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,3 +197,18 @@ func (rc *routeCollector) AdvertiseRoute(pfx netip.Prefix) error {
|
||||
rc.routes = append(rc.routes, pfx)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rc *routeCollector) UnadvertiseRoute(pfx netip.Prefix) error {
|
||||
routes := rc.routes
|
||||
rc.routes = rc.routes[:0]
|
||||
for _, r := range routes {
|
||||
if r != pfx {
|
||||
rc.routes = append(rc.routes, r)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prefixEqual(a, b netip.Prefix) bool {
|
||||
return a.Addr().Compare(b.Addr()) == 0 && a.Bits() == b.Bits()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user