all: use iterators over slice views more

This gets close to all of the remaining ones.

Updates #12912

Change-Id: I9c672bbed2654a6c5cab31e0cbece6c107d8c6fa
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-11-11 13:08:47 -08:00 committed by Brad Fitzpatrick
parent 00be1761b7
commit 4e0fc037e6
20 changed files with 62 additions and 86 deletions

View File

@ -272,8 +272,8 @@ func (i *jsIPN) run(jsCallbacks js.Value) {
name = p.Hostinfo().Hostname() name = p.Hostinfo().Hostname()
} }
addrs := make([]string, p.Addresses().Len()) addrs := make([]string, p.Addresses().Len())
for i := range p.Addresses().Len() { for i, ap := range p.Addresses().All() {
addrs[i] = p.Addresses().At(i).Addr().String() addrs[i] = ap.Addr().String()
} }
return jsNetMapPeerNode{ return jsNetMapPeerNode{
jsNetMapNode: jsNetMapNode{ jsNetMapNode: jsNetMapNode{
@ -589,8 +589,8 @@ func mapSlice[T any, M any](a []T, f func(T) M) []M {
func mapSliceView[T any, M any](a views.Slice[T], f func(T) M) []M { func mapSliceView[T any, M any](a views.Slice[T], f func(T) M) []M {
n := make([]M, a.Len()) n := make([]M, a.Len())
for i := range a.Len() { for i, v := range a.All() {
n[i] = f(a.At(i)) n[i] = f(v)
} }
return n return n
} }

View File

@ -354,9 +354,8 @@ func (b *LocalBackend) driveRemotesFromPeers(nm *netmap.NetworkMap) []*drive.Rem
// Check that the peer is allowed to share with us. // Check that the peer is allowed to share with us.
addresses := peer.Addresses() addresses := peer.Addresses()
for i := range addresses.Len() { for _, p := range addresses.All() {
addr := addresses.At(i) capsMap := b.PeerCaps(p.Addr())
capsMap := b.PeerCaps(addr.Addr())
if capsMap.HasCapability(tailcfg.PeerCapabilityTaildriveSharer) { if capsMap.HasCapability(tailcfg.PeerCapabilityTaildriveSharer) {
return true return true
} }

View File

@ -1811,8 +1811,7 @@ func setExitNodeID(prefs *ipn.Prefs, nm *netmap.NetworkMap, lastSuggestedExitNod
} }
for _, peer := range nm.Peers { for _, peer := range nm.Peers {
for i := range peer.Addresses().Len() { for _, addr := range peer.Addresses().All() {
addr := peer.Addresses().At(i)
if !addr.IsSingleIP() || addr.Addr() != prefs.ExitNodeIP { if !addr.IsSingleIP() || addr.Addr() != prefs.ExitNodeIP {
continue continue
} }
@ -4997,8 +4996,8 @@ func (b *LocalBackend) enterStateLockedOnEntry(newState ipn.State, unlock unlock
case ipn.Running: case ipn.Running:
var addrStrs []string var addrStrs []string
addrs := netMap.GetAddresses() addrs := netMap.GetAddresses()
for i := range addrs.Len() { for _, p := range addrs.All() {
addrStrs = append(addrStrs, addrs.At(i).Addr().String()) addrStrs = append(addrStrs, p.Addr().String())
} }
systemd.Status("Connected; %s; %s", activeLogin, strings.Join(addrStrs, " ")) systemd.Status("Connected; %s; %s", activeLogin, strings.Join(addrStrs, " "))
case ipn.NoState: case ipn.NoState:
@ -6089,8 +6088,7 @@ func (b *LocalBackend) SetDNS(ctx context.Context, name, value string) error {
func peerAPIPorts(peer tailcfg.NodeView) (p4, p6 uint16) { func peerAPIPorts(peer tailcfg.NodeView) (p4, p6 uint16) {
svcs := peer.Hostinfo().Services() svcs := peer.Hostinfo().Services()
for i := range svcs.Len() { for _, s := range svcs.All() {
s := svcs.At(i)
switch s.Proto { switch s.Proto {
case tailcfg.PeerAPI4: case tailcfg.PeerAPI4:
p4 = s.Port p4 = s.Port
@ -6122,8 +6120,7 @@ func peerAPIBase(nm *netmap.NetworkMap, peer tailcfg.NodeView) string {
var have4, have6 bool var have4, have6 bool
addrs := nm.GetAddresses() addrs := nm.GetAddresses()
for i := range addrs.Len() { for _, a := range addrs.All() {
a := addrs.At(i)
if !a.IsSingleIP() { if !a.IsSingleIP() {
continue continue
} }
@ -6145,10 +6142,9 @@ func peerAPIBase(nm *netmap.NetworkMap, peer tailcfg.NodeView) string {
} }
func nodeIP(n tailcfg.NodeView, pred func(netip.Addr) bool) netip.Addr { func nodeIP(n tailcfg.NodeView, pred func(netip.Addr) bool) netip.Addr {
for i := range n.Addresses().Len() { for _, pfx := range n.Addresses().All() {
a := n.Addresses().At(i) if pfx.IsSingleIP() && pred(pfx.Addr()) {
if a.IsSingleIP() && pred(a.Addr()) { return pfx.Addr()
return a.Addr()
} }
} }
return netip.Addr{} return netip.Addr{}
@ -6378,8 +6374,8 @@ func peerCanProxyDNS(p tailcfg.NodeView) bool {
// If p.Cap is not populated (e.g. older control server), then do the old // If p.Cap is not populated (e.g. older control server), then do the old
// thing of searching through services. // thing of searching through services.
services := p.Hostinfo().Services() services := p.Hostinfo().Services()
for i := range services.Len() { for _, s := range services.All() {
if s := services.At(i); s.Proto == tailcfg.PeerAPIDNS && s.Port >= 1 { if s.Proto == tailcfg.PeerAPIDNS && s.Port >= 1 {
return true return true
} }
} }

View File

@ -3041,12 +3041,10 @@ func deterministicNodeForTest(t testing.TB, want views.Slice[tailcfg.StableNodeI
var ret tailcfg.NodeView var ret tailcfg.NodeView
gotIDs := make([]tailcfg.StableNodeID, got.Len()) gotIDs := make([]tailcfg.StableNodeID, got.Len())
for i := range got.Len() { for i, nv := range got.All() {
nv := got.At(i)
if !nv.Valid() { if !nv.Valid() {
t.Fatalf("invalid node at index %v", i) t.Fatalf("invalid node at index %v", i)
} }
gotIDs[i] = nv.StableID() gotIDs[i] = nv.StableID()
if nv.StableID() == use { if nv.StableID() == use {
ret = nv ret = nv

View File

@ -430,8 +430,7 @@ func (b *LocalBackend) tkaBootstrapFromGenesisLocked(g tkatype.MarshaledAUM, per
} }
bootstrapStateID := fmt.Sprintf("%d:%d", genesis.State.StateID1, genesis.State.StateID2) bootstrapStateID := fmt.Sprintf("%d:%d", genesis.State.StateID1, genesis.State.StateID2)
for i := range persist.DisallowedTKAStateIDs().Len() { for _, stateID := range persist.DisallowedTKAStateIDs().All() {
stateID := persist.DisallowedTKAStateIDs().At(i)
if stateID == bootstrapStateID { if stateID == bootstrapStateID {
return fmt.Errorf("TKA with stateID of %q is disallowed on this node", stateID) return fmt.Errorf("TKA with stateID of %q is disallowed on this node", stateID)
} }
@ -572,8 +571,7 @@ func tkaStateFromPeer(p tailcfg.NodeView) ipnstate.TKAPeer {
TailscaleIPs: make([]netip.Addr, 0, p.Addresses().Len()), TailscaleIPs: make([]netip.Addr, 0, p.Addresses().Len()),
NodeKey: p.Key(), NodeKey: p.Key(),
} }
for i := range p.Addresses().Len() { for _, addr := range p.Addresses().All() {
addr := p.Addresses().At(i)
if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.Addr()) { if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.Addr()) {
fp.TailscaleIPs = append(fp.TailscaleIPs, addr.Addr()) fp.TailscaleIPs = append(fp.TailscaleIPs, addr.Addr())
} }

View File

@ -242,8 +242,7 @@ func (b *LocalBackend) updateServeTCPPortNetMapAddrListenersLocked(ports []uint1
} }
addrs := nm.GetAddresses() addrs := nm.GetAddresses()
for i := range addrs.Len() { for _, a := range addrs.All() {
a := addrs.At(i)
for _, p := range ports { for _, p := range ports {
addrPort := netip.AddrPortFrom(a.Addr(), p) addrPort := netip.AddrPortFrom(a.Addr(), p)
if _, ok := b.serveListeners[addrPort]; ok { if _, ok := b.serveListeners[addrPort]; ok {

View File

@ -121,8 +121,8 @@ func (b *LocalBackend) updateWebClientListenersLocked() {
} }
addrs := b.netMap.GetAddresses() addrs := b.netMap.GetAddresses()
for i := range addrs.Len() { for _, pfx := range addrs.All() {
addrPort := netip.AddrPortFrom(addrs.At(i).Addr(), webClientPort) addrPort := netip.AddrPortFrom(pfx.Addr(), webClientPort)
if _, ok := b.webClientListeners[addrPort]; ok { if _, ok := b.webClientListeners[addrPort]; ok {
continue // already listening continue // already listening
} }

View File

@ -82,8 +82,8 @@ func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool
pathForTest("bart") pathForTest("bart")
// Built a bart table. // Built a bart table.
t := &bart.Table[struct{}]{} t := &bart.Table[struct{}]{}
for i := range addrs.Len() { for _, p := range addrs.All() {
t.Insert(addrs.At(i), struct{}{}) t.Insert(p, struct{}{})
} }
return bartLookup(t) return bartLookup(t)
} }
@ -99,8 +99,8 @@ func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool
// General case: // General case:
pathForTest("ip-map") pathForTest("ip-map")
m := set.Set[netip.Addr]{} m := set.Set[netip.Addr]{}
for i := range addrs.Len() { for _, p := range addrs.All() {
m.Add(addrs.At(i).Addr()) m.Add(p.Addr())
} }
return ipInMap(m) return ipInMap(m)
} }

View File

@ -180,8 +180,7 @@ func PrefixIs6(p netip.Prefix) bool { return p.Addr().Is6() }
// IPv6 /0 route. // IPv6 /0 route.
func ContainsExitRoutes(rr views.Slice[netip.Prefix]) bool { func ContainsExitRoutes(rr views.Slice[netip.Prefix]) bool {
var v4, v6 bool var v4, v6 bool
for i := range rr.Len() { for _, r := range rr.All() {
r := rr.At(i)
if r == allIPv4 { if r == allIPv4 {
v4 = true v4 = true
} else if r == allIPv6 { } else if r == allIPv6 {
@ -194,8 +193,8 @@ func ContainsExitRoutes(rr views.Slice[netip.Prefix]) bool {
// ContainsExitRoute reports whether rr contains at least one of IPv4 or // ContainsExitRoute reports whether rr contains at least one of IPv4 or
// IPv6 /0 (exit) routes. // IPv6 /0 (exit) routes.
func ContainsExitRoute(rr views.Slice[netip.Prefix]) bool { func ContainsExitRoute(rr views.Slice[netip.Prefix]) bool {
for i := range rr.Len() { for _, r := range rr.All() {
if rr.At(i).Bits() == 0 { if r.Bits() == 0 {
return true return true
} }
} }
@ -205,8 +204,8 @@ func ContainsExitRoute(rr views.Slice[netip.Prefix]) bool {
// ContainsNonExitSubnetRoutes reports whether v contains Subnet // ContainsNonExitSubnetRoutes reports whether v contains Subnet
// Routes other than ExitNode Routes. // Routes other than ExitNode Routes.
func ContainsNonExitSubnetRoutes(rr views.Slice[netip.Prefix]) bool { func ContainsNonExitSubnetRoutes(rr views.Slice[netip.Prefix]) bool {
for i := range rr.Len() { for _, r := range rr.All() {
if rr.At(i).Bits() != 0 { if r.Bits() != 0 {
return true return true
} }
} }

View File

@ -42,8 +42,8 @@ func dnsMapFromNetworkMap(nm *netmap.NetworkMap) dnsMap {
if dnsname.HasSuffix(nm.Name, suffix) { if dnsname.HasSuffix(nm.Name, suffix) {
ret[canonMapKey(dnsname.TrimSuffix(nm.Name, suffix))] = ip ret[canonMapKey(dnsname.TrimSuffix(nm.Name, suffix))] = ip
} }
for i := range addrs.Len() { for _, p := range addrs.All() {
if addrs.At(i).Addr().Is4() { if p.Addr().Is4() {
have4 = true have4 = true
} }
} }
@ -52,9 +52,8 @@ func dnsMapFromNetworkMap(nm *netmap.NetworkMap) dnsMap {
if p.Name() == "" { if p.Name() == "" {
continue continue
} }
for i := range p.Addresses().Len() { for _, pfx := range p.Addresses().All() {
a := p.Addresses().At(i) ip := pfx.Addr()
ip := a.Addr()
if ip.Is4() && !have4 { if ip.Is4() && !have4 {
continue continue
} }

View File

@ -433,8 +433,7 @@ func (s *Server) TailscaleIPs() (ip4, ip6 netip.Addr) {
return return
} }
addrs := nm.GetAddresses() addrs := nm.GetAddresses()
for i := range addrs.Len() { for _, addr := range addrs.All() {
addr := addrs.At(i)
ip := addr.Addr() ip := addr.Addr()
if ip.Is6() { if ip.Is6() {
ip6 = ip ip6 = ip

View File

@ -279,15 +279,14 @@ func (a *NetworkMap) equalConciseHeader(b *NetworkMap) bool {
// in nodeConciseEqual in sync. // in nodeConciseEqual in sync.
func printPeerConcise(buf *strings.Builder, p tailcfg.NodeView) { func printPeerConcise(buf *strings.Builder, p tailcfg.NodeView) {
aip := make([]string, p.AllowedIPs().Len()) aip := make([]string, p.AllowedIPs().Len())
for i := range aip { for i, a := range p.AllowedIPs().All() {
a := p.AllowedIPs().At(i) s := strings.TrimSuffix(a.String(), "/32")
s := strings.TrimSuffix(fmt.Sprint(a), "/32")
aip[i] = s aip[i] = s
} }
ep := make([]string, p.Endpoints().Len()) epStrs := make([]string, p.Endpoints().Len())
for i := range ep { for i, ep := range p.Endpoints().All() {
e := p.Endpoints().At(i).String() e := ep.String()
// Align vertically on the ':' between IP and port // Align vertically on the ':' between IP and port
colon := strings.IndexByte(e, ':') colon := strings.IndexByte(e, ':')
spaces := 0 spaces := 0
@ -295,7 +294,7 @@ func printPeerConcise(buf *strings.Builder, p tailcfg.NodeView) {
spaces++ spaces++
colon-- colon--
} }
ep[i] = fmt.Sprintf("%21v", e+strings.Repeat(" ", spaces)) epStrs[i] = fmt.Sprintf("%21v", e+strings.Repeat(" ", spaces))
} }
derp := p.DERP() derp := p.DERP()
@ -316,7 +315,7 @@ func printPeerConcise(buf *strings.Builder, p tailcfg.NodeView) {
discoShort, discoShort,
derp, derp,
strings.Join(aip, " "), strings.Join(aip, " "),
strings.Join(ep, " ")) strings.Join(epStrs, " "))
} }
// nodeConciseEqual reports whether a and b are equal for the fields accessed by printPeerConcise. // nodeConciseEqual reports whether a and b are equal for the fields accessed by printPeerConcise.

View File

@ -67,7 +67,7 @@ func (ss *Slice[T]) Add(vs ...T) {
// AddSlice adds all elements in vs to the set. // AddSlice adds all elements in vs to the set.
func (ss *Slice[T]) AddSlice(vs views.Slice[T]) { func (ss *Slice[T]) AddSlice(vs views.Slice[T]) {
for i := range vs.Len() { for _, v := range vs.All() {
ss.Add(vs.At(i)) ss.Add(v)
} }
} }

View File

@ -102,8 +102,7 @@ type kv struct {
sort.Slice(ent, func(i, j int) bool { return ent[i].pub.Less(ent[j].pub) }) sort.Slice(ent, func(i, j int) bool { return ent[i].pub.Less(ent[j].pub) })
peers := map[key.NodePublic]tailcfg.NodeView{} peers := map[key.NodePublic]tailcfg.NodeView{}
for i := range c.peers.Len() { for _, p := range c.peers.All() {
p := c.peers.At(i)
peers[p.Key()] = p peers[p.Key()] = p
} }

View File

@ -9,6 +9,7 @@
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"iter"
"math" "math"
"math/rand/v2" "math/rand/v2"
"net" "net"
@ -1384,20 +1385,18 @@ func (de *endpoint) updateFromNode(n tailcfg.NodeView, heartbeatDisabled bool, p
} }
func (de *endpoint) setEndpointsLocked(eps interface { func (de *endpoint) setEndpointsLocked(eps interface {
Len() int All() iter.Seq2[int, netip.AddrPort]
At(i int) netip.AddrPort
}) { }) {
for _, st := range de.endpointState { for _, st := range de.endpointState {
st.index = indexSentinelDeleted // assume deleted until updated in next loop st.index = indexSentinelDeleted // assume deleted until updated in next loop
} }
var newIpps []netip.AddrPort var newIpps []netip.AddrPort
for i := range eps.Len() { for i, ipp := range eps.All() {
if i > math.MaxInt16 { if i > math.MaxInt16 {
// Seems unlikely. // Seems unlikely.
break break
} }
ipp := eps.At(i)
if !ipp.IsValid() { if !ipp.IsValid() {
de.c.logf("magicsock: bogus netmap endpoint from %v", eps) de.c.logf("magicsock: bogus netmap endpoint from %v", eps)
continue continue

View File

@ -1120,8 +1120,8 @@ func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, erro
// re-run. // re-run.
eps = c.endpointTracker.update(time.Now(), eps) eps = c.endpointTracker.update(time.Now(), eps)
for i := range c.staticEndpoints.Len() { for _, ep := range c.staticEndpoints.All() {
addAddr(c.staticEndpoints.At(i), tailcfg.EndpointExplicitConf) addAddr(ep, tailcfg.EndpointExplicitConf)
} }
if localAddr := c.pconn4.LocalAddr(); localAddr.IP.IsUnspecified() { if localAddr := c.pconn4.LocalAddr(); localAddr.IP.IsUnspecified() {
@ -2360,16 +2360,14 @@ func (c *Conn) logEndpointCreated(n tailcfg.NodeView) {
fmt.Fprintf(w, "derp=%v%s ", regionID, code) fmt.Fprintf(w, "derp=%v%s ", regionID, code)
} }
for i := range n.AllowedIPs().Len() { for _, a := range n.AllowedIPs().All() {
a := n.AllowedIPs().At(i)
if a.IsSingleIP() { if a.IsSingleIP() {
fmt.Fprintf(w, "aip=%v ", a.Addr()) fmt.Fprintf(w, "aip=%v ", a.Addr())
} else { } else {
fmt.Fprintf(w, "aip=%v ", a) fmt.Fprintf(w, "aip=%v ", a)
} }
} }
for i := range n.Endpoints().Len() { for _, ep := range n.Endpoints().All() {
ep := n.Endpoints().At(i)
fmt.Fprintf(w, "ep=%v ", ep) fmt.Fprintf(w, "ep=%v ", ep)
} }
})) }))

View File

@ -643,13 +643,11 @@ func (ns *Impl) UpdateNetstackIPs(nm *netmap.NetworkMap) {
newPfx := make(map[netip.Prefix]bool) newPfx := make(map[netip.Prefix]bool)
if selfNode.Valid() { if selfNode.Valid() {
for i := range selfNode.Addresses().Len() { for _, p := range selfNode.Addresses().All() {
p := selfNode.Addresses().At(i)
newPfx[p] = true newPfx[p] = true
} }
if ns.ProcessSubnets { if ns.ProcessSubnets {
for i := range selfNode.AllowedIPs().Len() { for _, p := range selfNode.AllowedIPs().All() {
p := selfNode.AllowedIPs().At(i)
newPfx[p] = true newPfx[p] = true
} }
} }

View File

@ -207,8 +207,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) {
ps, found := e.getPeerStatusLite(n.Key()) ps, found := e.getPeerStatusLite(n.Key())
if !found { if !found {
onlyZeroRoute := true // whether peerForIP returned n only because its /0 route matched onlyZeroRoute := true // whether peerForIP returned n only because its /0 route matched
for i := range n.AllowedIPs().Len() { for _, r := range n.AllowedIPs().All() {
r := n.AllowedIPs().At(i)
if r.Bits() != 0 && r.Contains(flow.DstAddr()) { if r.Bits() != 0 && r.Contains(flow.DstAddr()) {
onlyZeroRoute = false onlyZeroRoute = false
break break

View File

@ -852,8 +852,7 @@ func (e *userspaceEngine) updateActivityMapsLocked(trackNodes []key.NodePublic,
// hasOverlap checks if there is a IPPrefix which is common amongst the two // hasOverlap checks if there is a IPPrefix which is common amongst the two
// provided slices. // provided slices.
func hasOverlap(aips, rips views.Slice[netip.Prefix]) bool { func hasOverlap(aips, rips views.Slice[netip.Prefix]) bool {
for i := range aips.Len() { for _, aip := range aips.All() {
aip := aips.At(i)
if views.SliceContains(rips, aip) { if views.SliceContains(rips, aip) {
return true return true
} }
@ -1329,9 +1328,9 @@ func (e *userspaceEngine) mySelfIPMatchingFamily(dst netip.Addr) (src netip.Addr
if addrs.Len() == 0 { if addrs.Len() == 0 {
return zero, errors.New("no self address in netmap") return zero, errors.New("no self address in netmap")
} }
for i := range addrs.Len() { for _, p := range addrs.All() {
if a := addrs.At(i); a.IsSingleIP() && a.Addr().BitLen() == dst.BitLen() { if p.IsSingleIP() && p.Addr().BitLen() == dst.BitLen() {
return a.Addr(), nil return p.Addr(), nil
} }
} }
return zero, errors.New("no self address in netmap matching address family") return zero, errors.New("no self address in netmap matching address family")

View File

@ -40,8 +40,7 @@ func cidrIsSubnet(node tailcfg.NodeView, cidr netip.Prefix) bool {
if !cidr.IsSingleIP() { if !cidr.IsSingleIP() {
return true return true
} }
for i := range node.Addresses().Len() { for _, selfCIDR := range node.Addresses().All() {
selfCIDR := node.Addresses().At(i)
if cidr == selfCIDR { if cidr == selfCIDR {
return false return false
} }
@ -110,8 +109,7 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
cpeer.V4MasqAddr = peer.SelfNodeV4MasqAddrForThisPeer() cpeer.V4MasqAddr = peer.SelfNodeV4MasqAddrForThisPeer()
cpeer.V6MasqAddr = peer.SelfNodeV6MasqAddrForThisPeer() cpeer.V6MasqAddr = peer.SelfNodeV6MasqAddrForThisPeer()
cpeer.IsJailed = peer.IsJailed() cpeer.IsJailed = peer.IsJailed()
for i := range peer.AllowedIPs().Len() { for _, allowedIP := range peer.AllowedIPs().All() {
allowedIP := peer.AllowedIPs().At(i)
if allowedIP.Bits() == 0 && peer.StableID() != exitNode { if allowedIP.Bits() == 0 && peer.StableID() != exitNode {
if didExitNodeWarn { if didExitNodeWarn {
// Don't log about both the IPv4 /0 and IPv6 /0. // Don't log about both the IPv4 /0 and IPv6 /0.