checkAlignment(t, "Peer.stats", unsafe.Offsetof(p.stats))
checkAlignment(t, "Peer.isRunning", unsafe.Offsetof(p.isRunning))
}
+
+
+// TestDeviceAlignment checks that atomically-accessed fields are
+// aligned to 64-bit boundaries, as required by the atomic package.
+//
+// Unfortunately, violating this rule on 32-bit platforms results in a
+// hard segfault at runtime.
+func TestDeviceAlignment(t *testing.T) {
+ var d Device
+
+ typ := reflect.TypeOf(&d).Elem()
+ t.Logf("Device type size: %d, with fields:", typ.Size())
+ for i := 0; i < typ.NumField(); i++ {
+ field := typ.Field(i)
+ t.Logf("\t%30s\toffset=%3v\t(type size=%3d, align=%d)",
+ field.Name,
+ field.Offset,
+ field.Type.Size(),
+ field.Type.Align(),
+ )
+ }
+
+ checkAlignment(t, "Device.rate.underLoadUntil", unsafe.Offsetof(d.rate.underLoadUntil))
+}
cookieChecker CookieChecker
rate struct {
- underLoadUntil atomic.Value
+ underLoadUntil int64
limiter ratelimiter.Ratelimiter
}
}
func (device *Device) IsUnderLoad() bool {
-
// check if currently under load
-
now := time.Now()
underLoad := len(device.queue.handshake.c) >= UnderLoadQueueSize
if underLoad {
- device.rate.underLoadUntil.Store(now.Add(UnderLoadAfterTime))
+ atomic.StoreInt64(&device.rate.underLoadUntil, now.Add(UnderLoadAfterTime).UnixNano())
return true
}
-
// check if recently under load
-
- until := device.rate.underLoadUntil.Load().(time.Time)
- return until.After(now)
+ return atomic.LoadInt64(&device.rate.underLoadUntil) > now.UnixNano()
}
func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
mtu = DefaultMTU
}
device.tun.mtu = int32(mtu)
-
device.peers.keyMap = make(map[NoisePublicKey]*Peer)
-
device.rate.limiter.Init()
- device.rate.underLoadUntil.Store(time.Time{})
-
device.indexTable.Init()
-
device.PopulatePools()
// create queues