Explorar el Código

apply `go fix` for Go 1.26 (#1867)

* apply `go fix` for Go 1.26

This applies the `go fix` recommendations for go1.26

* for all of ./...
Wade Simmons hace 1 mes
padre
commit
0dc8a28d1f
Se han modificado 76 ficheros con 80 adiciones y 161 borrados
  1. 2 11
      bits.go
  2. 1 1
      cert/sign_test.go
  3. 4 4
      cmd/nebula-cert/ca.go
  4. 0 1
      cmd/nebula-cert/ca_test.go
  5. 4 4
      cmd/nebula-cert/sign.go
  6. 0 1
      cmd/nebula-cert/sign_test.go
  7. 0 1
      cmd/nebula-service/logs_generic.go
  8. 0 1
      cmd/nebula/notify_notlinux.go
  9. 6 9
      config/config.go
  10. 1 1
      connection_state_test.go
  11. 1 1
      control_lifecycle_test.go
  12. 0 1
      e2e/echo_test.go
  13. 0 1
      e2e/handshake_manager_test.go
  14. 0 1
      e2e/handshakes_test.go
  15. 0 1
      e2e/helpers_test.go
  16. 0 1
      e2e/leak_test.go
  17. 0 1
      e2e/rebind_test.go
  18. 0 1
      e2e/recovery_timing_test.go
  19. 0 1
      e2e/router/hostmap.go
  20. 0 1
      e2e/router/router.go
  21. 0 1
      e2e/sshd_test.go
  22. 0 1
      e2e/tunnels_test.go
  23. 1 1
      firewall/cache_test.go
  24. 0 1
      noiseutil/boring.go
  25. 0 1
      noiseutil/boring_test.go
  26. 2 2
      overlay/batch/checksum_seed_test.go
  27. 1 1
      overlay/batch/tcp_coalesce_test.go
  28. 2 2
      overlay/batch/tx_batch_test.go
  29. 3 3
      overlay/batch/udp_coalesce_test.go
  30. 1 1
      overlay/checksum/checksum_test.go
  31. 0 1
      overlay/network_category_windows.go
  32. 0 1
      overlay/network_category_windows_test.go
  33. 0 1
      overlay/tio/blockon_linux.go
  34. 0 1
      overlay/tio/queueset_gso_linux.go
  35. 0 1
      overlay/tio/queueset_poll_linux.go
  36. 0 1
      overlay/tio/tio_gso_linux.go
  37. 0 1
      overlay/tio/tio_poll_linux.go
  38. 4 7
      overlay/tio/tun_file_linux_test.go
  39. 0 1
      overlay/tio/tun_linux_offload.go
  40. 5 6
      overlay/tio/tun_linux_offload_test.go
  41. 0 1
      overlay/tio/virtio/header_linux.go
  42. 4 11
      overlay/tio/virtio/segment_linux.go
  43. 7 8
      overlay/tio/virtio/segment_linux_test.go
  44. 2 2
      overlay/tun.go
  45. 0 1
      overlay/tun_android.go
  46. 0 1
      overlay/tun_bypass_windows_386.go
  47. 0 1
      overlay/tun_darwin.go
  48. 0 1
      overlay/tun_freebsd.go
  49. 0 1
      overlay/tun_ios.go
  50. 1 2
      overlay/tun_linux.go
  51. 0 1
      overlay/tun_linux_test.go
  52. 0 1
      overlay/tun_netbsd.go
  53. 0 1
      overlay/tun_notwin.go
  54. 0 1
      overlay/tun_openbsd.go
  55. 0 1
      overlay/tun_tester.go
  56. 0 1
      overlay/tun_windows.go
  57. 2 2
      overlay/user_test.go
  58. 3 3
      routing/balance_test.go
  59. 5 4
      routing/gateway.go
  60. 4 8
      scheduler_test.go
  61. 2 2
      test/assert.go
  62. 0 1
      udp/netchange_darwin.go
  63. 0 1
      udp/netchange_darwin_test.go
  64. 0 1
      udp/netchange_generic.go
  65. 0 1
      udp/udp_android.go
  66. 0 1
      udp/udp_bypass_windows_386.go
  67. 0 1
      udp/udp_darwin.go
  68. 2 5
      udp/udp_linux.go
  69. 4 4
      udp/udp_linux_fixes_test.go
  70. 3 6
      udp/udp_linux_writebatch.go
  71. 2 2
      udp/udp_linux_writebatch_alloc_test.go
  72. 0 1
      udp/udp_netbsd.go
  73. 0 1
      udp/udp_rio_windows.go
  74. 0 1
      udp/udp_tester.go
  75. 0 1
      udp/udp_windows.go
  76. 1 1
      util/cpupin_linux.go

+ 2 - 11
bits.go

@@ -79,13 +79,7 @@ func (b *Bits) clearRange(startPos, count uint64) uint64 {
 	// handle the potential partial word before pos becomes u64 aligned
 	word := pos >> 6
 	bit := pos & 63
-	take := uint64(64) - bit
-	if take > remaining {
-		take = remaining
-	}
-	if take > b.length-pos {
-		take = b.length - pos
-	}
+	take := min(min(uint64(64)-bit, remaining), b.length-pos)
 	var mask uint64
 	if take == 64 {
 		mask = math.MaxUint64
@@ -189,10 +183,7 @@ func (b *Bits) Update(l *slog.Logger, i uint64) bool {
 func (b *Bits) updateSlow(l *slog.Logger, i uint64) bool {
 	// If i is a jump, adjust the window, record lost, update current, and return true
 	if i > b.current {
-		end := i
-		if end > b.current+b.length {
-			end = b.current + b.length
-		}
+		end := min(i, b.current+b.length)
 		count := end - b.current
 		startPos := (b.current + 1) & b.lengthMask
 

+ 1 - 1
cert/sign_test.go

@@ -120,7 +120,7 @@ func TestCertificate_SignP256_AlwaysNormalized(t *testing.T) {
 	pub := elliptic.Marshal(elliptic.P256(), priv.PublicKey.X, priv.PublicKey.Y)
 	rawPriv := priv.D.FillBytes(make([]byte, 32))
 
-	for i := 0; i < 1000; i++ {
+	for i := range 1000 {
 		if i&1 == 1 {
 			tbs.Version = Version1
 		} else {

+ 4 - 4
cmd/nebula-cert/ca.go

@@ -151,7 +151,7 @@ func ca(args []string, out io.Writer, errOut io.Writer, pr PasswordReader) error
 
 	var groups []string
 	if *cf.groups != "" {
-		for _, rg := range strings.Split(*cf.groups, ",") {
+		for rg := range strings.SplitSeq(*cf.groups, ",") {
 			g := strings.TrimSpace(rg)
 			if g != "" {
 				groups = append(groups, g)
@@ -171,7 +171,7 @@ func ca(args []string, out io.Writer, errOut io.Writer, pr PasswordReader) error
 	}
 
 	if *cf.networks != "" {
-		for _, rs := range strings.Split(*cf.networks, ",") {
+		for rs := range strings.SplitSeq(*cf.networks, ",") {
 			rs := strings.Trim(rs, " ")
 			if rs != "" {
 				n, err := netip.ParsePrefix(rs)
@@ -193,7 +193,7 @@ func ca(args []string, out io.Writer, errOut io.Writer, pr PasswordReader) error
 	}
 
 	if *cf.unsafeNetworks != "" {
-		for _, rs := range strings.Split(*cf.unsafeNetworks, ",") {
+		for rs := range strings.SplitSeq(*cf.unsafeNetworks, ",") {
 			rs := strings.Trim(rs, " ")
 			if rs != "" {
 				n, err := netip.ParsePrefix(rs)
@@ -221,7 +221,7 @@ func ca(args []string, out io.Writer, errOut io.Writer, pr PasswordReader) error
 	if !isP11 && *cf.encryption {
 		passphrase = []byte(os.Getenv("NEBULA_CA_PASSPHRASE"))
 		if len(passphrase) == 0 {
-			for i := 0; i < 5; i++ {
+			for range 5 {
 				errOut.Write([]byte("Enter passphrase: "))
 				passphrase, err = pr.ReadPassword()
 

+ 0 - 1
cmd/nebula-cert/ca_test.go

@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package main
 

+ 4 - 4
cmd/nebula-cert/sign.go

@@ -146,7 +146,7 @@ func signCert(args []string, out io.Writer, errOut io.Writer, pr PasswordReader)
 			passphrase = []byte(os.Getenv("NEBULA_CA_PASSPHRASE"))
 			if len(passphrase) == 0 {
 				// ask for a passphrase until we get one
-				for i := 0; i < 5; i++ {
+				for range 5 {
 					errOut.Write([]byte("Enter passphrase: "))
 					passphrase, err = pr.ReadPassword()
 
@@ -203,7 +203,7 @@ func signCert(args []string, out io.Writer, errOut io.Writer, pr PasswordReader)
 	}
 
 	if *sf.networks != "" {
-		for _, rs := range strings.Split(*sf.networks, ",") {
+		for rs := range strings.SplitSeq(*sf.networks, ",") {
 			rs := strings.Trim(rs, " ")
 			if rs != "" {
 				n, err := netip.ParsePrefix(rs)
@@ -228,7 +228,7 @@ func signCert(args []string, out io.Writer, errOut io.Writer, pr PasswordReader)
 	}
 
 	if *sf.unsafeNetworks != "" {
-		for _, rs := range strings.Split(*sf.unsafeNetworks, ",") {
+		for rs := range strings.SplitSeq(*sf.unsafeNetworks, ",") {
 			rs := strings.Trim(rs, " ")
 			if rs != "" {
 				n, err := netip.ParsePrefix(rs)
@@ -247,7 +247,7 @@ func signCert(args []string, out io.Writer, errOut io.Writer, pr PasswordReader)
 
 	var groups []string
 	if *sf.groups != "" {
-		for _, rg := range strings.Split(*sf.groups, ",") {
+		for rg := range strings.SplitSeq(*sf.groups, ",") {
 			g := strings.TrimSpace(rg)
 			if g != "" {
 				groups = append(groups, g)

+ 0 - 1
cmd/nebula-cert/sign_test.go

@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package main
 

+ 0 - 1
cmd/nebula-service/logs_generic.go

@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package main
 

+ 0 - 1
cmd/nebula/notify_notlinux.go

@@ -1,5 +1,4 @@
 //go:build !linux
-// +build !linux
 
 package main
 

+ 6 - 9
config/config.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"log/slog"
+	"maps"
 	"math"
 	"os"
 	"os/signal"
@@ -154,9 +155,7 @@ func (c *C) ReloadConfig() {
 	defer c.reloadLock.Unlock()
 
 	c.oldSettings = make(map[string]any)
-	for k, v := range c.Settings {
-		c.oldSettings[k] = v
-	}
+	maps.Copy(c.oldSettings, c.Settings)
 
 	err := c.Load(c.path)
 	if err != nil {
@@ -177,9 +176,7 @@ func (c *C) ReloadConfigString(raw string) error {
 	defer c.reloadLock.Unlock()
 
 	c.oldSettings = make(map[string]any)
-	for k, v := range c.Settings {
-		c.oldSettings[k] = v
-	}
+	maps.Copy(c.oldSettings, c.Settings)
 
 	err := c.LoadString(raw)
 	if err != nil {
@@ -216,7 +213,7 @@ func (c *C) GetStringSlice(k string, d []string) []string {
 	}
 
 	v := make([]string, len(rv))
-	for i := 0; i < len(v); i++ {
+	for i := range v {
 		v[i] = fmt.Sprintf("%v", rv[i])
 	}
 
@@ -310,8 +307,8 @@ func (c *C) IsSet(k string) bool {
 }
 
 func (c *C) get(k string, v any) any {
-	parts := strings.Split(k, ".")
-	for _, p := range parts {
+	parts := strings.SplitSeq(k, ".")
+	for p := range parts {
 		m, ok := v.(map[string]any)
 		if !ok {
 			return nil

+ 1 - 1
connection_state_test.go

@@ -97,7 +97,7 @@ func TestConnectionState_NextMessageCounter(t *testing.T) {
 	assert.Equal(t, RejectAfterMessages, cs.messageCounter.Load())
 
 	// Continued send attempts stay refused and the counter never wraps
-	for i := 0; i < 10; i++ {
+	for range 10 {
 		_, ok = cs.NextMessageCounter()
 		assert.False(t, ok)
 	}

+ 1 - 1
control_lifecycle_test.go

@@ -247,7 +247,7 @@ func TestControl_ConcurrentStopAndStart(t *testing.T) {
 	c, _, _ := newReadyControl(t)
 
 	var wg sync.WaitGroup
-	for i := 0; i < 2; i++ {
+	for range 2 {
 		wg.Go(func() { c.Stop() })
 	}
 	wg.Go(func() { _ = c.Start() })

+ 0 - 1
e2e/echo_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/handshake_manager_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/handshakes_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/helpers_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/leak_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/rebind_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/recovery_timing_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/router/hostmap.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package router
 

+ 0 - 1
e2e/router/router.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package router
 

+ 0 - 1
e2e/sshd_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 0 - 1
e2e/tunnels_test.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package e2e
 

+ 1 - 1
firewall/cache_test.go

@@ -22,7 +22,7 @@ func newFixedTicker(t *testing.T, l *slog.Logger, cacheLen int) *ConntrackCacheT
 		l:     l,
 		cache: make(ConntrackCache, cacheLen),
 	}
-	for i := 0; i < cacheLen; i++ {
+	for i := range cacheLen {
 		c.cache[Packet{LocalPort: uint16(i) + 1}] = struct{}{}
 	}
 	c.cacheTick.Store(1) // cacheV starts at 0, so Get() takes the reset path

+ 0 - 1
noiseutil/boring.go

@@ -1,5 +1,4 @@
 //go:build boringcrypto
-// +build boringcrypto
 
 package noiseutil
 

+ 0 - 1
noiseutil/boring_test.go

@@ -1,5 +1,4 @@
 //go:build boringcrypto
-// +build boringcrypto
 
 package noiseutil
 

+ 2 - 2
overlay/batch/checksum_seed_test.go

@@ -127,7 +127,7 @@ func TestPseudoSumIPv6MatchesReference(t *testing.T) {
 func TestIPv4HdrChecksumMatchesReference(t *testing.T) {
 	rng := rand.New(rand.NewSource(0x1791))
 	for _, hdrLen := range []int{20, 24, 40, 60} {
-		for trial := 0; trial < 200; trial++ {
+		for trial := range 200 {
 			hdr := make([]byte, hdrLen)
 			rng.Read(hdr)
 			hdr[0] = 0x40 | byte(hdrLen/4)
@@ -156,7 +156,7 @@ func TestIPv4HdrChecksumMatchesReference(t *testing.T) {
 // the way a receiver does (pseudo-header + L4 must sum to all-ones).
 func TestChecksumSeedReceiverAcceptance(t *testing.T) {
 	rng := rand.New(rand.NewSource(0x1826))
-	for trial := 0; trial < 200; trial++ {
+	for trial := range 200 {
 		src := [4]byte{byte(rng.Intn(256)), byte(rng.Intn(256)), byte(rng.Intn(256)), byte(rng.Intn(256))}
 		dst := [4]byte{byte(rng.Intn(256)), byte(rng.Intn(256)), byte(rng.Intn(256)), byte(rng.Intn(256))}
 		payLen := rng.Intn(1500)

+ 1 - 1
overlay/batch/tcp_coalesce_test.go

@@ -540,7 +540,7 @@ func TestCoalescerCapBySegments(t *testing.T) {
 	c := newTestTCPCoalescer(t, w)
 	pay := make([]byte, 512)
 	seq := uint32(1000)
-	for i := 0; i < tcpCoalesceMaxSegs+5; i++ {
+	for range tcpCoalesceMaxSegs + 5 {
 		if err := c.Commit(buildTCPv4(seq, tcpAck, pay)); err != nil {
 			t.Fatal(err)
 		}

+ 2 - 2
overlay/batch/tx_batch_test.go

@@ -28,7 +28,7 @@ func TestSendBatchReserveCommitFlush(t *testing.T) {
 	b := NewSendBatch(fw, 4, 32)
 
 	ap := netip.MustParseAddrPort("10.0.0.1:4242")
-	for i := 0; i < 4; i++ {
+	for i := range 4 {
 		slot := b.Reserve(32)
 		if cap(slot) != 32 {
 			t.Fatalf("slot %d: cap=%d want 32", i, cap(slot))
@@ -72,7 +72,7 @@ func TestSendBatchSlotsDoNotOverlap(t *testing.T) {
 	b := NewSendBatch(fw, 3, 8)
 	ap := netip.MustParseAddrPort("10.0.0.1:80")
 
-	for i := 0; i < 3; i++ {
+	for i := range 3 {
 		s := b.Reserve(8)
 		pkt := append(s[:0], byte(0xA0+i), byte(0xB0+i))
 		b.Commit(pkt, ap)

+ 3 - 3
overlay/batch/udp_coalesce_test.go

@@ -129,7 +129,7 @@ func TestUDPCoalescerCoalescesEqualSized(t *testing.T) {
 	w := &fakeTunWriter{gsoEnabled: true}
 	c := newTestUDPCoalescer(t, w)
 	pay := make([]byte, 1200)
-	for i := 0; i < 3; i++ {
+	for range 3 {
 		if err := c.Commit(buildUDPv4(1000, 53, pay)); err != nil {
 			t.Fatal(err)
 		}
@@ -259,7 +259,7 @@ func TestUDPCoalescerCapsAtMaxSegs(t *testing.T) {
 	w := &fakeTunWriter{gsoEnabled: true}
 	c := newTestUDPCoalescer(t, w)
 	pay := make([]byte, 100)
-	for i := 0; i < udpCoalesceMaxSegs+5; i++ {
+	for range udpCoalesceMaxSegs + 5 {
 		if err := c.Commit(buildUDPv4(1000, 53, pay)); err != nil {
 			t.Fatal(err)
 		}
@@ -317,7 +317,7 @@ func TestUDPCoalescerIPv6Coalesces(t *testing.T) {
 	w := &fakeTunWriter{gsoEnabled: true}
 	c := newTestUDPCoalescer(t, w)
 	pay := make([]byte, 1200)
-	for i := 0; i < 3; i++ {
+	for range 3 {
 		if err := c.Commit(buildUDPv6(1000, 53, pay)); err != nil {
 			t.Fatal(err)
 		}

+ 1 - 1
overlay/checksum/checksum_test.go

@@ -151,7 +151,7 @@ func TestChecksumTailPaths(t *testing.T) {
 			offsets := []int{0, 1, 3, 7, 15} // mix of aligned and odd starts
 
 			for k := 0; k <= maxK; k++ {
-				for tail := 0; tail < 64; tail++ {
+				for tail := range 64 {
 					length := 64*k + tail
 					for _, seed := range seeds {
 						for _, off := range offsets {

+ 0 - 1
overlay/network_category_windows.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/network_category_windows_test.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tio/blockon_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 0 - 1
overlay/tio/queueset_gso_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 0 - 1
overlay/tio/queueset_poll_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 0 - 1
overlay/tio/tio_gso_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 0 - 1
overlay/tio/tio_poll_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 4 - 7
overlay/tio/tun_file_linux_test.go

@@ -1,5 +1,4 @@
 //go:build linux && !android && !e2e_testing
-// +build linux,!android,!e2e_testing
 
 package tio
 
@@ -117,17 +116,15 @@ func TestPoll_ConcurrentWrite_NoRace(t *testing.T) {
 	}()
 
 	var wg sync.WaitGroup
-	for w := 0; w < writers; w++ {
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
-			for i := 0; i < perWriter; i++ {
+	for range writers {
+		wg.Go(func() {
+			for range perWriter {
 				if _, werr := p.Write(payload); werr != nil {
 					t.Errorf("write: %v", werr)
 					return
 				}
 			}
-		}()
+		})
 	}
 	wg.Wait()
 

+ 0 - 1
overlay/tio/tun_linux_offload.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package tio
 

+ 5 - 6
overlay/tio/tun_linux_offload_test.go

@@ -1,5 +1,4 @@
 //go:build linux && !android && !e2e_testing
-// +build linux,!android,!e2e_testing
 
 package tio
 
@@ -137,7 +136,7 @@ func buildTSOv4(t *testing.T, payLen, mss int) ([]byte, virtio.Hdr) {
 	binary.BigEndian.PutUint16(pkt[34:36], 65535) // window
 
 	// payload
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+tcpLen+i] = byte(i & 0xff)
 	}
 	return pkt, virtio.NewHeader(
@@ -257,7 +256,7 @@ func TestSegmentTCPv6(t *testing.T) {
 	pkt[53] = 0x19 // FIN | ACK | PSH — exercise FIN clearing too
 	binary.BigEndian.PutUint16(pkt[54:56], 65535)
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+tcpLen+i] = byte(i)
 	}
 
@@ -361,7 +360,7 @@ func buildUSOv4(t *testing.T, payLen, gsoSize int) ([]byte, virtio.Hdr) {
 	binary.BigEndian.PutUint16(pkt[22:24], 53)                    // dport
 	binary.BigEndian.PutUint16(pkt[24:26], uint16(udpLen+payLen)) // superpacket length
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+udpLen+i] = byte(i & 0xff)
 	}
 
@@ -473,7 +472,7 @@ func TestSegmentUDPv6(t *testing.T) {
 	// Superpacket-wide length, as the kernel supplies it; see buildUSOv4.
 	binary.BigEndian.PutUint16(pkt[44:46], uint16(udpLen+payLen))
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+udpLen+i] = byte(i)
 	}
 
@@ -772,7 +771,7 @@ func buildTSOv6(payLen, gso int) []byte {
 	pkt[53] = 0x10 // ACK only
 	binary.BigEndian.PutUint16(pkt[54:56], 65535)
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+tcpLen+i] = byte(i)
 	}
 	return pkt

+ 0 - 1
overlay/tio/virtio/header_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package virtio
 

+ 4 - 11
overlay/tio/virtio/segment_linux.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 // Package virtio implements the pure validation, header-correction, and
 // per-segment slicing logic for kernel-supplied TSO/USO superpackets on
@@ -254,12 +253,9 @@ func SegmentTCP(pkt []byte, hdrLenU, csumStartU, gsoSizeU uint16, yield func(seg
 	var savedHdr [maxSegHdrLen]byte
 	copy(savedHdr[:headerLen], pkt[:headerLen])
 
-	for i := 0; i < numSeg; i++ {
+	for i := range numSeg {
 		segStart := i * gsoSize
-		segEnd := segStart + gsoSize
-		if segEnd > payLen {
-			segEnd = payLen
-		}
+		segEnd := min(segStart+gsoSize, payLen)
 		segPayLen := segEnd - segStart
 		segLen := headerLen + segPayLen
 		headerOff := i * gsoSize
@@ -359,12 +355,9 @@ func SegmentUDP(pkt []byte, hdrLenU, csumStartU, gsoSizeU uint16, yield func(seg
 	var savedHdr [maxSegHdrLen]byte
 	copy(savedHdr[:headerLen], pkt[:headerLen])
 
-	for i := 0; i < numSeg; i++ {
+	for i := range numSeg {
 		segStart := i * gsoSize
-		segEnd := segStart + gsoSize
-		if segEnd > payLen {
-			segEnd = payLen
-		}
+		segEnd := min(segStart+gsoSize, payLen)
 		segPayLen := segEnd - segStart
 		segLen := headerLen + segPayLen
 		headerOff := i * gsoSize

+ 7 - 8
overlay/tio/virtio/segment_linux_test.go

@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package virtio
 
@@ -58,7 +57,7 @@ func buildTCPv4Super(payLen int) (pkt []byte, hdrLen, csumStart uint16) {
 	pkt[33] = 0x18                                // ACK | PSH
 	binary.BigEndian.PutUint16(pkt[34:36], 65535) // window
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+tcpLen+i] = byte(i & 0xff)
 	}
 	return pkt, ipLen + tcpLen, ipLen
@@ -82,7 +81,7 @@ func buildUDPv4Super(payLen int) (pkt []byte, hdrLen, csumStart uint16) {
 	binary.BigEndian.PutUint16(pkt[20:22], 12345) // sport
 	binary.BigEndian.PutUint16(pkt[22:24], 53)    // dport
 
-	for i := 0; i < payLen; i++ {
+	for i := range payLen {
 		pkt[ipLen+udpLen+i] = byte(i & 0xff)
 	}
 	return pkt, ipLen + udpLen, ipLen
@@ -188,7 +187,7 @@ func TestSegmentTCPHeaderNotCorrupted(t *testing.T) {
 				// Payload bytes must be the original contiguous slice.
 				segPayLen := len(seg) - int(hdrLen)
 				wantPay := make([]byte, segPayLen)
-				for k := 0; k < segPayLen; k++ {
+				for k := range segPayLen {
 					wantPay[k] = byte((off + k) & 0xff)
 				}
 				if !bytes.Equal(seg[hdrLen:], wantPay) {
@@ -317,7 +316,7 @@ func TestSegmentUDPHeaderNotCorrupted(t *testing.T) {
 				}
 
 				wantPay := make([]byte, segPayLen)
-				for k := 0; k < segPayLen; k++ {
+				for k := range segPayLen {
 					wantPay[k] = byte((off + k) & 0xff)
 				}
 				if !bytes.Equal(seg[hdrLen:], wantPay) {
@@ -365,7 +364,7 @@ func buildUDPv4Single(payload []byte) (pkt []byte, hdr Hdr) {
 // 0xffff, because all-zero is the reserved "no checksum" encoding that IPv6 rejects outright.
 func TestFinishChecksumUDPZeroStoresAllOnes(t *testing.T) {
 	var payload []byte
-	for i := 0; i < 0x10000; i++ {
+	for i := range 0x10000 {
 		p := []byte{byte(i >> 8), byte(i)}
 		pkt, hdr := buildUDPv4Single(p)
 		cs, co := int(hdr.CsumStart), int(hdr.CsumOffset)
@@ -544,7 +543,7 @@ func TestBaseSumsMatchZeroingReference(t *testing.T) {
 
 	t.Run("ipv4", func(t *testing.T) {
 		for ihl := ipv4HeaderMinLen; ihl <= ipv4HeaderMaxLen; ihl += 4 {
-			for iter := 0; iter < 5000; iter++ {
+			for range 5000 {
 				pkt := make([]byte, ihl)
 				for i := range pkt {
 					pkt[i] = randByte(&state)
@@ -574,7 +573,7 @@ func TestBaseSumsMatchZeroingReference(t *testing.T) {
 		for dataOff := 5; dataOff <= 15; dataOff++ {
 			tcpLen := dataOff * 4
 			headerLen := csumStart + tcpLen
-			for iter := 0; iter < 5000; iter++ {
+			for range 5000 {
 				pkt := make([]byte, headerLen+64)
 				for i := range pkt {
 					pkt[i] = randByte(&state)

+ 2 - 2
overlay/tun.go

@@ -93,14 +93,14 @@ func prefixToMask(prefix netip.Prefix) netip.Addr {
 }
 
 func flipBytes(b []byte) []byte {
-	for i := 0; i < len(b); i++ {
+	for i := range b {
 		b[i] ^= 0xFF
 	}
 	return b
 }
 func orBytes(a []byte, b []byte) []byte {
 	ret := make([]byte, len(a))
-	for i := 0; i < len(a); i++ {
+	for i := range a {
 		ret[i] = a[i] | b[i]
 	}
 	return ret

+ 0 - 1
overlay/tun_android.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_bypass_windows_386.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_darwin.go

@@ -1,5 +1,4 @@
 //go:build !ios && !e2e_testing
-// +build !ios,!e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_freebsd.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_ios.go

@@ -1,5 +1,4 @@
 //go:build ios && !e2e_testing
-// +build ios,!e2e_testing
 
 package overlay
 

+ 1 - 2
overlay/tun_linux.go

@@ -1,5 +1,4 @@
 //go:build !android && !e2e_testing
-// +build !android,!e2e_testing
 
 package overlay
 
@@ -548,7 +547,7 @@ func (t *tun) setDefaultRoute(cidr netip.Prefix) error {
 	if err != nil {
 		t.l.Warn("Failed to set default route MTU, retrying", "error", err, "cidr", cidr)
 		//retry twice more -- on some systems there appears to be a race condition where if we set routes too soon, netlink says `invalid argument`
-		for i := 0; i < 2; i++ {
+		for range 2 {
 			time.Sleep(100 * time.Millisecond)
 			err = netlink.RouteReplace(&nr)
 			if err == nil {

+ 0 - 1
overlay/tun_linux_test.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_netbsd.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_notwin.go

@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package overlay
 

+ 0 - 1
overlay/tun_openbsd.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_tester.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package overlay
 

+ 0 - 1
overlay/tun_windows.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package overlay
 

+ 2 - 2
overlay/user_test.go

@@ -108,7 +108,7 @@ func TestUserDeviceReadersConcurrentRace(t *testing.T) {
 	var wg sync.WaitGroup
 	run := func(idx int) {
 		defer wg.Done()
-		for i := 0; i < iterations; i++ {
+		for range iterations {
 			pkts, err := readers[idx].Read()
 			if err != nil {
 				errs <- err
@@ -136,7 +136,7 @@ func TestUserDeviceReadersConcurrentRace(t *testing.T) {
 	// waiting reader's private buffer, so reusing buf between writes is safe.
 	go func() {
 		buf := make([]byte, 32)
-		for i := 0; i < 2*iterations; i++ {
+		for i := range 2 * iterations {
 			for j := range buf {
 				buf[j] = byte(i + j)
 			}

+ 3 - 3
routing/balance_test.go

@@ -27,7 +27,7 @@ func TestPacketsAreBalancedEqually(t *testing.T) {
 	gw3count := 0
 
 	iterationCount := uint16(65535)
-	for i := uint16(0); i < iterationCount; i++ {
+	for i := range iterationCount {
 		packet := firewall.Packet{
 			LocalAddr:  netip.MustParseAddr("192.168.1.1"),
 			RemoteAddr: netip.MustParseAddr("10.0.0.1"),
@@ -74,7 +74,7 @@ func TestPacketsAreBalancedByPriority(t *testing.T) {
 	gw2count := 0
 
 	iterationCount := uint16(65535)
-	for i := uint16(0); i < iterationCount; i++ {
+	for i := range iterationCount {
 		packet := firewall.Packet{
 			LocalAddr:  netip.MustParseAddr("192.168.1.1"),
 			RemoteAddr: netip.MustParseAddr("10.0.0.1"),
@@ -115,7 +115,7 @@ func TestBalancePacketDistributsRandomlyAndReturnsFalseIfBucketsNotCalculated(t
 	gw1count := 0
 	gw2count := 0
 
-	for i := uint16(0); i < iterationCount; i++ {
+	for i := range iterationCount {
 		packet := firewall.Packet{
 			LocalAddr:  netip.MustParseAddr("192.168.1.1"),
 			RemoteAddr: netip.MustParseAddr("10.0.0.1"),

+ 5 - 4
routing/gateway.go

@@ -3,6 +3,7 @@ package routing
 import (
 	"fmt"
 	"net/netip"
+	"strings"
 )
 
 const (
@@ -13,14 +14,14 @@ const (
 type Gateways []Gateway
 
 func (g Gateways) String() string {
-	str := ""
+	var str strings.Builder
 	for i, gw := range g {
-		str += gw.String()
+		str.WriteString(gw.String())
 		if i < len(g)-1 {
-			str += ", "
+			str.WriteString(", ")
 		}
 	}
-	return str
+	return str.String()
 }
 
 type Gateway struct {

+ 4 - 8
scheduler_test.go

@@ -1,21 +1,19 @@
 package nebula
 
 import (
-	"context"
 	"testing"
 	"time"
 )
 
 func TestScheduler_PooledReuse(t *testing.T) {
-	ctx, cancel := context.WithCancel(context.Background())
-	defer cancel()
+	ctx := t.Context()
 
 	s := NewScheduler[int](16)
 	delivered := make(chan int, 256)
 	go s.Run(ctx, func(item int) { delivered <- item })
 
 	const N = 100
-	for i := 0; i < N; i++ {
+	for i := range N {
 		s.Schedule(ctx, i, time.Millisecond)
 	}
 
@@ -34,8 +32,7 @@ func TestScheduler_PooledReuse(t *testing.T) {
 // BenchmarkScheduler_Schedule reports allocations per Schedule call.
 // In steady state the Scheduler's sync.Pool means we should see zero allocs per op once the pool warms up.
 func BenchmarkScheduler_Schedule(b *testing.B) {
-	ctx, cancel := context.WithCancel(context.Background())
-	defer cancel()
+	ctx := b.Context()
 
 	s := NewScheduler[int](b.N)
 	go s.Run(ctx, func(int) {})
@@ -51,8 +48,7 @@ func BenchmarkScheduler_Schedule(b *testing.B) {
 // What we'd pay per Schedule if Punchy called time.AfterFunc directly without the pooled Scheduler.
 // Allocates a *time.Timer plus a closure each call.
 func BenchmarkBareAfterFunc(b *testing.B) {
-	ctx, cancel := context.WithCancel(context.Background())
-	defer cancel()
+	ctx := b.Context()
 
 	queue := make(chan int, b.N)
 	go func() {

+ 2 - 2
test/assert.go

@@ -25,7 +25,7 @@ func AssertDeepCopyEqual(t *testing.T, a any, b any) {
 }
 
 func traverseDeepCopy(t *testing.T, v1 reflect.Value, v2 reflect.Value, name string) bool {
-	if v1.Type() == v2.Type() && v1.Type() == reflect.TypeOf(netip.Addr{}) {
+	if v1.Type() == v2.Type() && v1.Type() == reflect.TypeFor[netip.Addr]() {
 		// Ignore netip.Addr types since they reuse an interned global value
 		return false
 	}
@@ -72,7 +72,7 @@ func traverseDeepCopy(t *testing.T, v1 reflect.Value, v2 reflect.Value, name str
 		}
 		return traverseDeepCopy(t, v1.Elem(), v2.Elem(), name)
 
-	case reflect.Ptr:
+	case reflect.Pointer:
 		local := reflect.ValueOf(time.Local).Pointer()
 		if local == v1.Pointer() && local == v2.Pointer() {
 			return true

+ 0 - 1
udp/netchange_darwin.go

@@ -1,5 +1,4 @@
 //go:build darwin && !ios && !e2e_testing
-// +build darwin,!ios,!e2e_testing
 
 package udp
 

+ 0 - 1
udp/netchange_darwin_test.go

@@ -1,5 +1,4 @@
 //go:build darwin && !ios && !e2e_testing
-// +build darwin,!ios,!e2e_testing
 
 package udp
 

+ 0 - 1
udp/netchange_generic.go

@@ -1,5 +1,4 @@
 //go:build !darwin || ios || e2e_testing
-// +build !darwin ios e2e_testing
 
 package udp
 

+ 0 - 1
udp/udp_android.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package udp
 

+ 0 - 1
udp/udp_bypass_windows_386.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package udp
 

+ 0 - 1
udp/udp_darwin.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package udp
 

+ 2 - 5
udp/udp_linux.go

@@ -294,10 +294,7 @@ func deliverSegments(r EncReader, from netip.AddrPort, payload []byte, segSize i
 		return
 	}
 	for off := 0; off < len(payload); off += segSize {
-		end := off + segSize
-		if end > len(payload) {
-			end = len(payload)
-		}
+		end := min(off+segSize, len(payload))
 		r(from, payload[off:end:end])
 	}
 }
@@ -479,7 +476,7 @@ func NewUDPStatsEmitter(udpConns []Conn) func() {
 	return func() {
 		for i, gauges := range udpGauges {
 			if err := udpConns[i].(*StdConn).getMemInfo(&meminfo); err == nil {
-				for j := 0; j < unix.SK_MEMINFO_VARS; j++ {
+				for j := range unix.SK_MEMINFO_VARS {
 					gauges[j].Update(int64(meminfo[j]))
 				}
 			}

+ 4 - 4
udp/udp_linux_fixes_test.go

@@ -107,7 +107,7 @@ func TestWriteBatchBadFamilyDeliversOthers(t *testing.T) {
 	got := map[string]bool{}
 	rx.SetReadDeadline(time.Now().Add(2 * time.Second))
 	buf := make([]byte, 64)
-	for i := 0; i < 2; i++ {
+	for i := range 2 {
 		n, _, rerr := rx.ReadFromUDPAddrPort(buf)
 		if rerr != nil {
 			t.Fatalf("expected 2 delivered packets, read #%d failed: %v", i+1, rerr)
@@ -161,7 +161,7 @@ func TestWriteBatchUnreachableDestDeliversOthers(t *testing.T) {
 	got := map[string]bool{}
 	rx.SetReadDeadline(time.Now().Add(2 * time.Second))
 	buf := make([]byte, 64)
-	for i := 0; i < 4; i++ {
+	for i := range 4 {
 		n, _, rerr := rx.ReadFromUDPAddrPort(buf)
 		if rerr != nil {
 			t.Fatalf("expected 4 delivered packets, read #%d failed: %v (got so far: %v)", i+1, rerr, got)
@@ -691,7 +691,7 @@ func TestGSOEngagesOnLoopback(t *testing.T) {
 	// The kernel must deliver the original datagram boundaries and bytes.
 	_ = rx.SetReadDeadline(time.Now().Add(5 * time.Second))
 	got := make([]byte, pktLen+1)
-	for i := 0; i < numPkts; i++ {
+	for i := range numPkts {
 		n, _, err := rx.ReadFromUDP(got)
 		if err != nil {
 			t.Fatalf("rx read %d: %v", i, err)
@@ -699,7 +699,7 @@ func TestGSOEngagesOnLoopback(t *testing.T) {
 		if n != pktLen {
 			t.Fatalf("rx read %d: len=%d want %d (kernel segmented at wrong boundary)", i, n, pktLen)
 		}
-		for j := 0; j < n; j++ {
+		for j := range n {
 			if got[j] != byte(i) {
 				t.Fatalf("rx read %d: byte %d = %#x, want %#x", i, j, got[j], byte(i))
 			}

+ 3 - 6
udp/udp_linux_writebatch.go

@@ -112,7 +112,7 @@ func (w *batchWriter) prepareWriteMessages(n int, offloadsEnabled bool) {
 
 	w.cmsg = make([]byte, n*w.cmsgSpace)
 
-	for k := 0; k < n; k++ {
+	for k := range n {
 		base := k * w.cmsgSpace
 		seg := (*unix.Cmsghdr)(unsafe.Pointer(&w.cmsg[base]))
 		seg.Level = unix.SOL_UDP
@@ -214,7 +214,7 @@ func (w *batchWriter) WriteBatch(bufs [][]byte, addrs []netip.AddrPort) (int, er
 				break
 			}
 
-			for k := 0; k < runLen; k++ {
+			for k := range runLen {
 				b := bufs[i+k]
 				if len(b) == 0 {
 					w.iovs[iovIdx+k].Base = nil
@@ -318,10 +318,7 @@ func (w *batchWriter) planRun(bufs [][]byte, addrs []netip.AddrPort, start, iovB
 		return 1, segSize
 	}
 	dst := addrs[start]
-	maxLen := w.maxGSOSegments
-	if iovBudget < maxLen {
-		maxLen = iovBudget
-	}
+	maxLen := min(iovBudget, w.maxGSOSegments)
 	runLen := 1
 	total := segSize
 	for runLen < maxLen && start+runLen < len(bufs) {

+ 2 - 2
udp/udp_linux_writebatch_alloc_test.go

@@ -64,13 +64,13 @@ func TestWriteBatchNoAllocs(t *testing.T) {
 				addrs = append(addrs, dst)
 			}
 			// GSO-eligible run with a short tail.
-			for k := 0; k < 8; k++ {
+			for range 8 {
 				add(payload, dstA)
 			}
 			add(short, dstA)
 			add(payload, dstA)
 			// Alternating destinations defeat coalescing entirely.
-			for k := 0; k < 4; k++ {
+			for k := range 4 {
 				dst := dstA
 				if k%2 == 0 {
 					dst = dstB

+ 0 - 1
udp/udp_netbsd.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package udp
 

+ 0 - 1
udp/udp_rio_windows.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 // Inspired by https://git.zx2c4.com/wireguard-go/tree/conn/bind_windows.go
 

+ 0 - 1
udp/udp_tester.go

@@ -1,5 +1,4 @@
 //go:build e2e_testing
-// +build e2e_testing
 
 package udp
 

+ 0 - 1
udp/udp_windows.go

@@ -1,5 +1,4 @@
 //go:build !e2e_testing
-// +build !e2e_testing
 
 package udp
 

+ 1 - 1
util/cpupin_linux.go

@@ -40,7 +40,7 @@ func AllowedCPUs() ([]int, error) {
 		return nil, err
 	}
 	cpus := make([]int, 0, set.Count())
-	for cpu := 0; cpu < len(set)*64; cpu++ {
+	for cpu := range len(set) * 64 {
 		if set.IsSet(cpu) {
 			cpus = append(cpus, cpu)
 		}