wgengine/netstack: store values from lb to avoid acquiring a lock

Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
kevin/allow_service_host_access_hosted_service
KevinLiang10 3 days ago
parent c7342225c5
commit 355bfcd572

@ -927,6 +927,9 @@ func (b *LocalBackend) SetIPServiceMappingsForTesting(m netmap.IPServiceMappings
b.mu.Lock()
defer b.mu.Unlock()
b.ipVIPServiceMap = m
if ns, ok := b.sys.Netstack.GetOK(); ok {
ns.UpdateIPServiceMappings(m)
}
}
// setConfigLocked uses the provided config to update the backend's prefs
@ -4509,6 +4512,12 @@ func (b *LocalBackend) onEditPrefsLocked(_ ipnauth.Actor, mp *ipn.MaskedPrefs, o
}
}
if mp.AdvertiseServicesSet {
if ns, ok := b.sys.Netstack.GetOK(); ok {
ns.UpdateActiveVIPServices(newPrefs.AdvertiseServices().AsSlice())
}
}
// This is recorded here in the EditPrefs path, not the setPrefs path on purpose.
// recordForEdit records metrics related to edits and changes, not the final state.
// If, in the future, we want to record gauge-metrics related to the state of prefs,
@ -6238,7 +6247,12 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(b.pm.CurrentPrefs())
if buildfeatures.HasServe {
b.ipVIPServiceMap = nm.GetIPVIPServiceMap()
ipsvMap := nm.GetIPVIPServiceMap()
b.ipVIPServiceMap = ipsvMap
if ns, ok := b.sys.Netstack.GetOK(); ok {
ns.UpdateIPServiceMappings(ipsvMap)
}
}
if !oldSelf.Equal(nm.SelfNodeOrZero()) {

@ -111,6 +111,8 @@ type LocalBackend = any
type NetstackImpl interface {
Start(LocalBackend) error
UpdateNetstackIPs(*netmap.NetworkMap)
UpdateIPServiceMappings(netmap.IPServiceMappings)
UpdateActiveVIPServices([]string)
}
// Set is a convenience method to set a subsystem value.

@ -209,6 +209,10 @@ type Impl struct {
atomicIsVIPServiceIPFunc syncs.AtomicValue[func(netip.Addr) bool]
atomicIpVIPServiceMap syncs.AtomicValue[netmap.IPServiceMappings]
// make this a set of strings for faster lookup
atomicActiveVIPServices syncs.AtomicValue[set.Set[string]]
// forwardDialFunc, if non-nil, is the net.Dialer.DialContext-style
// function that is used to make outgoing connections when forwarding a
// TCP connection to another host (e.g. in subnet router mode).
@ -761,6 +765,22 @@ func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) {
}
}
// UpdateIPServiceMappings updates the IPServiceMappings when there is a change
// in this value in localbackend. This is usually triggered from a netmap update.
func (ns *Impl) UpdateIPServiceMappings(mappings netmap.IPServiceMappings) {
ns.mu.Lock()
defer ns.mu.Unlock()
ns.atomicIpVIPServiceMap.Store(mappings)
}
// UpdateActiveVIPServices updates the set of active VIP services names.
func (ns *Impl) UpdateActiveVIPServices(activeServices []string) {
ns.mu.Lock()
defer ns.mu.Unlock()
activeServicesSet := set.SetOf(activeServices)
ns.atomicActiveVIPServices.Store(activeServicesSet)
}
func (ns *Impl) isLoopbackPort(port uint16) bool {
if ns.loopbackPort != nil && int(port) == *ns.loopbackPort {
return true
@ -780,9 +800,7 @@ func (ns *Impl) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper, gro *gro.
// Determine if we care about this local packet.
dst := p.Dst.Addr()
var IPServiceMappings netmap.IPServiceMappings
if ns.lb != nil {
IPServiceMappings = ns.lb.IPServiceMappings()
}
IPServiceMappings = ns.atomicIpVIPServiceMap.Load()
serviceName, isVIPServiceIP := IPServiceMappings[dst]
switch {
case dst == serviceIP || dst == serviceIPv6:
@ -804,19 +822,11 @@ func (ns *Impl) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper, gro *gro.
if p.IPProto != ipproto.TCP {
return filter.Accept, gro
}
// returns all configured VIP services, since the IPServiceMappings contains
// inactive service IPs when node hosts the service, we need to check the
// service is active or not before dropping the packet.
VIPServices := ns.lb.VIPServices()
serviceActive := false
for _, svc := range VIPServices {
// Even though control only send service IP down when there is a config
// for the service, we want to still check that the config still exists
// before passing the packet to netstack.
if svc.Name == serviceName {
serviceActive = svc.Active
}
}
// returns all active VIP services in a set, since the IPServiceMappings
// contains inactive service IPs when node hosts the service, we need to
// check the service is active or not before dropping the packet.
activeServices := ns.atomicActiveVIPServices.Load()
_, serviceActive := activeServices[serviceName.String()]
if !serviceActive {
return filter.Accept, gro
}

@ -126,6 +126,7 @@ func makeNetstack(tb testing.TB, config func(*Impl)) *Impl {
tb.Fatal(err)
}
tb.Cleanup(func() { ns.Close() })
sys.Set(ns)
lb, err := ipnlocal.NewLocalBackend(logf, logid.PublicID{}, sys, 0)
if err != nil {

Loading…
Cancel
Save