periodically remove dns looked up routes up on new look up results

This commit is contained in:
Kevin Liang 2024-03-21 17:17:37 +00:00
parent 4db1ea4729
commit f8ce2cbb75
5 changed files with 89 additions and 40 deletions

View File

@ -110,10 +110,10 @@ func (e *AppConnector) updateDomains(domains []string) {
defer e.mu.Unlock()
var oldDomains map[string][]netip.Addr
var oldDiscovered map[string]ipn.DatedRoute
var oldDiscovered map[string]*ipn.DatedRoute
routeInfo := e.routeAdvertiser.ReadRouteInfoFromStore()
oldDiscovered, routeInfo.Discovered = routeInfo.Discovered, make(map[string]ipn.DatedRoute, len(domains))
oldDiscovered, routeInfo.Discovered = routeInfo.Discovered, make(map[string]*ipn.DatedRoute, len(domains))
oldDomains, e.domains = e.domains, make(map[string][]netip.Addr, len(domains))
e.wildcards = e.wildcards[:0]
for _, d := range domains {
@ -335,7 +335,6 @@ func (e *AppConnector) ObserveDNSResponse(res []byte) {
// advertise each address we have learned for the routed domain, that
// was not already known.
var toAdvertise []netip.Prefix
// Kevin comment: Will this update be too frequent?
var toUpdateDate []netip.Prefix
for _, addr := range addrs {
if !e.isAddrKnownLocked(domain, addr) {
@ -352,12 +351,14 @@ func (e *AppConnector) ObserveDNSResponse(res []byte) {
routesToUpdate := append(toAdvertise, toUpdateDate...)
routeInfo := e.routeAdvertiser.ReadRouteInfoFromStore()
if routeInfo.Discovered == nil {
routeInfo.Discovered = make(map[string]ipn.DatedRoute)
routeInfo.Discovered = make(map[string]*ipn.DatedRoute)
}
routeInfo.UpdateRoutesInDiscoveredForDomain(domain, routesToUpdate)
outDated := routeInfo.OutDatedRoutesInDiscoveredForDomain(domain)
e.routeAdvertiser.UpdateRoutesInfoToStore(routeInfo)
// fmt.Println("Route infos after dns update: ", e.routeAdvertiser.ReadRouteInfoFromStore())
e.scheduleAdvertisement(domain, toAdvertise...)
e.scheduleUndvertisement(domain, outDated...)
}
}
@ -435,6 +436,27 @@ func (e *AppConnector) scheduleAdvertisement(domain string, routes ...netip.Pref
})
}
func (e *AppConnector) scheduleUndvertisement(domain string, routes ...netip.Prefix) {
e.queue.Add(func() {
if err := e.routeAdvertiser.UnadvertiseRoute(routes...); err != nil {
e.logf("failed to unadvertise routes for %s: %v: %v", domain, routes, err)
return
}
e.mu.Lock()
defer e.mu.Unlock()
for _, route := range routes {
if !route.IsSingleIP() {
continue
}
addr := route.Addr()
e.deleteDomainAddrLocked(domain, addr)
e.logf("[v2] unadvertised route for %v: %v", domain, addr)
}
})
}
// hasDomainAddrLocked returns true if the address has been observed in a
// resolution of domain.
func (e *AppConnector) hasDomainAddrLocked(domain string, addr netip.Addr) bool {
@ -449,6 +471,15 @@ func (e *AppConnector) addDomainAddrLocked(domain string, addr netip.Addr) {
slices.SortFunc(e.domains[domain], compareAddr)
}
func (e *AppConnector) deleteDomainAddrLocked(domain string, addr netip.Addr) {
ind, ok := slices.BinarySearchFunc(e.domains[domain], addr, compareAddr)
if !ok {
return
}
e.domains[domain] = slices.Delete(e.domains[domain], ind, ind+1)
slices.SortFunc(e.domains[domain], compareAddr)
}
func compareAddr(l, r netip.Addr) int {
return l.Compare(r)
}

View File

@ -727,7 +727,7 @@ func (lc *LocalClient) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn
if err != nil {
return nil, err
}
fmt.Println(decodeJSON[*ipn.Prefs](body)) // Kevin debug
// fmt.Println(decodeJSON[*ipn.Prefs](body)) // Kevin debug
return decodeJSON[*ipn.Prefs](body)
}

View File

@ -355,7 +355,6 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
return nil, err
}
}
// Kevin comment: no need to do this since tailscaled startup will not affect routes.
envknob.LogCurrent(logf)
if dialer == nil {
@ -3142,6 +3141,7 @@ func (b *LocalBackend) PatchPrefsHandler(mp *ipn.MaskedPrefs) (ipn.PrefsView, er
// up or set is used on the tailscale cli _not_ when we calculate the new advertisedRoutes field.
routeInfo := b.pm.CurrentRoutes()
curRoutes := routeInfo.CorpAndDiscoveredAsSlice()
// fmt.Println("Kevin cur route: ", curRoutes)
if mp.AdvertiseRoutesSet {
routeInfo.Local = mp.AdvertiseRoutes
b.pm.SetCurrentRoutes(routeInfo)
@ -3183,7 +3183,7 @@ func (b *LocalBackend) EditPrefs(mp *ipn.MaskedPrefs) (ipn.PrefsView, error) {
// in setPrefsLocksOnEntry instead.
// This should return the public prefs, not the private ones.
fmt.Println("Editpref in local", b.pm.CurrentRoutes())
// fmt.Println("Editpref in local", b.pm.CurrentRoutes()) //Kevin debug
return stripKeysFromPrefs(newPrefs), nil
}
@ -3562,8 +3562,6 @@ func (b *LocalBackend) reconfigAppConnectorLocked(nm *netmap.NetworkMap, prefs i
slices.SortFunc(routes, func(i, j netip.Prefix) int { return i.Addr().Compare(j.Addr()) })
domains = slices.Compact(domains)
routes = slices.Compact(routes)
fmt.Println("Connector Kevin: ", domains)
fmt.Println("Connector Kevin: ", routes)
b.appConnector.UpdateDomainsAndRoutes(domains, routes)
}
@ -5988,7 +5986,7 @@ func coveredRouteRangeNoDefault(finalRoutes []netip.Prefix, ipp netip.Prefix) bo
// UnadvertiseRoute implements the appc.RouteAdvertiser interface. It removes
// a route advertisement if one is present in the existing routes.
func (b *LocalBackend) UnadvertiseRoute(toRemove ...netip.Prefix) error {
fmt.Println("We are unadvertising routes: ", toRemove)
// fmt.Println("We are unadvertising routes: ", toRemove) //Kevin debug
currentRoutes := b.Prefs().AdvertiseRoutes().AsSlice()
finalRoutes := currentRoutes[:0]
@ -5998,7 +5996,7 @@ func (b *LocalBackend) UnadvertiseRoute(toRemove ...netip.Prefix) error {
}
finalRoutes = append(finalRoutes, ipp)
}
fmt.Println("We are advertising these routes in unadvertising routes: ", finalRoutes)
// fmt.Println("We are advertising these routes in unadvertising routes: ", finalRoutes) // Kevin debug
_, err := b.EditPrefs(&ipn.MaskedPrefs{
Prefs: ipn.Prefs{
AdvertiseRoutes: finalRoutes,
@ -6009,7 +6007,9 @@ func (b *LocalBackend) UnadvertiseRoute(toRemove ...netip.Prefix) error {
}
func (b *LocalBackend) ReadRouteInfoFromStore() *ipn.RouteInfo {
b.pm.ReadRoutesForCurrentProfile()
if b.pm.CurrentRoutes() == nil {
b.pm.ReadRoutesForCurrentProfile()
}
return b.pm.CurrentRoutes()
}

View File

@ -65,7 +65,6 @@ func (pm *profileManager) WriteRoutesForCurrentProfile() error {
if err != nil {
return err
}
return pm.writeStateForCurrentProfile("_routes", routeInfoInBytes)
}

View File

@ -957,48 +957,67 @@ type LoginProfile struct {
type RouteInfo struct {
Local []netip.Prefix
Corp []netip.Prefix
Discovered map[string]DatedRoute
Discovered map[string]*DatedRoute
}
func (r RouteInfo) UpdateRoutesInDiscoveredForDomain(domain string, addrs []netip.Prefix) {
newDatedRoutes := make(DatedRoute)
val, hasKey := r.Discovered[domain]
if !hasKey || val == nil {
r.Discovered[domain] = addAddrsToDatedRoute(newDatedRoutes, addrs)
dr, hasKey := r.Discovered[domain]
if !hasKey || dr == nil || dr.Routes == nil {
newDatedRoutes := &DatedRoute{make(map[netip.Prefix]time.Time), time.Now()}
newDatedRoutes.addAddrsToDatedRoute(addrs)
r.Discovered[domain] = newDatedRoutes
return
}
// kevin comment: we won't see any existing routes here because know addrs are filtered.
currentRoutes := r.Discovered[domain]
r.Discovered[domain] = addAddrsToDatedRoute(currentRoutes, addrs)
currentRoutes.addAddrsToDatedRoute(addrs)
r.Discovered[domain] = currentRoutes
return
}
func (r RouteInfo) CorpAndDiscoveredAsSlice() []netip.Prefix {
dr := r.Corp
for _, routes := range r.Discovered {
for k := range routes {
dr = append(dr, k)
func (r RouteInfo) OutDatedRoutesInDiscoveredForDomain(domain string) []netip.Prefix {
dr, hasKey := r.Discovered[domain]
var outdate []netip.Prefix
now := time.Now()
if !hasKey || dr == nil || dr.Routes == nil || now.Sub(dr.LastCleanUp) < 360 {
return nil
}
for addr, date := range dr.Routes {
if now.Sub(date).Hours() >= 360 {
// 15 days old when last seen
outdate = append(outdate, addr)
delete(dr.Routes, addr)
}
}
return dr
r.Discovered[domain] = dr
return outdate
}
type DatedRoute = map[netip.Prefix]time.Time
func addAddrsToDatedRoute(curDatedRoute DatedRoute, addrs []netip.Prefix) DatedRoute {
time := time.Now()
ret := curDatedRoute
for _, addr := range addrs {
ret[addr] = time
func (r RouteInfo) CorpAndDiscoveredAsSlice() []netip.Prefix {
ret := r.Corp
for _, dr := range r.Discovered {
if dr != nil && dr.Routes != nil {
for k := range dr.Routes {
ret = append(ret, k)
}
}
}
return ret
}
// func datedRouteToSlice(curDatedRoute DatedRoute) []netip.Prefix {
// r := make([]netip.Prefix, 0, len(curDatedRoute))
// for k := range curDatedRoute {
// r = append(r, k)
// }
// return r
// }
type DatedRoute struct {
Routes map[netip.Prefix]time.Time
LastCleanUp time.Time
}
func (d *DatedRoute) String() string {
return fmt.Sprintf("routes: %s, lastCleanUp: %v", d.Routes, d.LastCleanUp)
}
func (d *DatedRoute) addAddrsToDatedRoute(addrs []netip.Prefix) {
time := time.Now()
for _, addr := range addrs {
d.Routes[addr] = time
}
}