mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-04 00:55:11 +00:00 
			
		
		
		
	appc: optimize dns response observation for large route tables
Advertise DNS discovered addresses as a single preference update rather than one at a time. Sort the list of observed addresses and use binary search to consult the list. Updates tailscale/corp#16636 Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
		
				
					committed by
					
						
						James Tucker
					
				
			
			
				
	
			
			
			
						parent
						
							db3776d5bf
						
					
				
				
					commit
					0f5e031133
				
			@@ -52,8 +52,8 @@ type AppConnector struct {
 | 
				
			|||||||
	// mu guards the fields that follow
 | 
						// mu guards the fields that follow
 | 
				
			||||||
	mu sync.Mutex
 | 
						mu sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// domains is a map of lower case domain names with no trailing dot, to a
 | 
						// domains is a map of lower case domain names with no trailing dot, to an
 | 
				
			||||||
	// list of resolved IP addresses.
 | 
						// ordered list of resolved IP addresses.
 | 
				
			||||||
	domains map[string][]netip.Addr
 | 
						domains map[string][]netip.Addr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// controlRoutes is the list of routes that were last supplied by control.
 | 
						// controlRoutes is the list of routes that were last supplied by control.
 | 
				
			||||||
@@ -297,14 +297,15 @@ func (e *AppConnector) ObserveDNSResponse(res []byte) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		// advertise each address we have learned for the routed domain, that
 | 
							// advertise each address we have learned for the routed domain, that
 | 
				
			||||||
		// was not already known.
 | 
							// was not already known.
 | 
				
			||||||
 | 
							var toAdvertise []netip.Prefix
 | 
				
			||||||
		for _, addr := range addrs {
 | 
							for _, addr := range addrs {
 | 
				
			||||||
			e.logf("[v2] observed routed DNS response for %s: %s", domain, addr)
 | 
								if !e.isAddrKnownLocked(domain, addr) {
 | 
				
			||||||
			if e.isAddrKnownLocked(domain, addr) {
 | 
									toAdvertise = append(toAdvertise, netip.PrefixFrom(addr, addr.BitLen()))
 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			e.scheduleAdvertisement(domain, addr)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							e.logf("[v2] observed new routes for %s: %s", domain, toAdvertise)
 | 
				
			||||||
 | 
							e.scheduleAdvertisement(domain, toAdvertise...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -344,35 +345,58 @@ func (e *AppConnector) findRoutedDomainLocked(domain string, cnameChain map[stri
 | 
				
			|||||||
// up future matches.
 | 
					// up future matches.
 | 
				
			||||||
// e.mu must be held.
 | 
					// e.mu must be held.
 | 
				
			||||||
func (e *AppConnector) isAddrKnownLocked(domain string, addr netip.Addr) bool {
 | 
					func (e *AppConnector) isAddrKnownLocked(domain string, addr netip.Addr) bool {
 | 
				
			||||||
	if slices.Contains(e.domains[domain], addr) {
 | 
						if e.hasDomainAddrLocked(domain, addr) {
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, route := range e.controlRoutes {
 | 
						for _, route := range e.controlRoutes {
 | 
				
			||||||
		if route.Contains(addr) {
 | 
							if route.Contains(addr) {
 | 
				
			||||||
			// record the new address associated with the domain for faster matching in subsequent
 | 
								// record the new address associated with the domain for faster matching in subsequent
 | 
				
			||||||
			// requests and for diagnostic records.
 | 
								// requests and for diagnostic records.
 | 
				
			||||||
			e.domains[domain] = append(e.domains[domain], addr)
 | 
								e.addDomainAddrLocked(domain, addr)
 | 
				
			||||||
			return true
 | 
								return true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// scheduleAdvertisement schedules an advertisement of the given address
 | 
					// scheduleAdvertisement schedules an advertisement of the given address
 | 
				
			||||||
// associated with the given domain.
 | 
					// associated with the given domain.
 | 
				
			||||||
func (e *AppConnector) scheduleAdvertisement(domain string, addr netip.Addr) {
 | 
					func (e *AppConnector) scheduleAdvertisement(domain string, routes ...netip.Prefix) {
 | 
				
			||||||
	e.queue.Add(func() {
 | 
						e.queue.Add(func() {
 | 
				
			||||||
		if err := e.routeAdvertiser.AdvertiseRoute(netip.PrefixFrom(addr, addr.BitLen())); err != nil {
 | 
							if err := e.routeAdvertiser.AdvertiseRoute(routes...); err != nil {
 | 
				
			||||||
			e.logf("failed to advertise route for %s: %v: %v", domain, addr, err)
 | 
								e.logf("failed to advertise routes for %s: %v: %v", domain, routes, err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		e.mu.Lock()
 | 
							e.mu.Lock()
 | 
				
			||||||
		defer e.mu.Unlock()
 | 
							defer e.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !slices.Contains(e.domains[domain], addr) {
 | 
							for _, route := range routes {
 | 
				
			||||||
			e.logf("[v2] advertised route for %v: %v", domain, addr)
 | 
								if !route.IsSingleIP() {
 | 
				
			||||||
			e.domains[domain] = append(e.domains[domain], addr)
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								addr := route.Addr()
 | 
				
			||||||
 | 
								if !e.hasDomainAddrLocked(domain, addr) {
 | 
				
			||||||
 | 
									e.addDomainAddrLocked(domain, addr)
 | 
				
			||||||
 | 
									e.logf("[v2] advertised 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 {
 | 
				
			||||||
 | 
						_, ok := slices.BinarySearchFunc(e.domains[domain], addr, compareAddr)
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// addDomainAddrLocked adds the address to the list of addresses resolved for
 | 
				
			||||||
 | 
					// domain and ensures the list remains sorted. Does not attempt to deduplicate.
 | 
				
			||||||
 | 
					func (e *AppConnector) addDomainAddrLocked(domain string, addr netip.Addr) {
 | 
				
			||||||
 | 
						e.domains[domain] = append(e.domains[domain], addr)
 | 
				
			||||||
 | 
						slices.SortFunc(e.domains[domain], compareAddr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func compareAddr(l, r netip.Addr) int {
 | 
				
			||||||
 | 
						return l.Compare(r)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user