From 65bd26dacb662f20aef5ee108c0f04f84df54ad2 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 1 Jul 2024 10:39:54 +0000 Subject: [PATCH 1/3] chore: add missing netcheck report fields to netinfo --- tailcfg/tailcfg.go | 46 ++++++++++++++++++++++++++++++--- wgengine/magicsock/magicsock.go | 10 +++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index eb1b4e9876790..918bd78289f20 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -733,7 +733,38 @@ type NetInfo struct { // This should only be updated rarely, or when there's a // material change, as any change here also gets uploaded to // the control plane. - DERPLatency map[string]float64 `json:",omitempty"` + // Deprecated; use DERPLatencyV4 and DERPLatencyV6 instead. + DERPLatency map[string]float64 `json:",omitempty"` + DERPLatencyV4 map[int]float64 `json:",omitempty"` + DERPLatencyV6 map[int]float64 `json:",omitempty"` + + // a UDP STUN round trip completed + UDP bool `json:",omitempty"` + + // an IPv6 STUN round trip completed + IPv6 bool `json:",omitempty"` + + // an IPv4 STUN round trip completed + IPv4 bool `json:",omitempty"` + + // an IPv6 packet was able to be sent + IPv6CanSend bool `json:",omitempty"` + + // an IPv4 packet was able to be sent + IPv4CanSend bool `json:",omitempty"` + + // an ICMPv4 round trip completed + ICMPv4 bool + + // ip:port of global IPv4 + GlobalV4 string + + // [ip]:port of global IPv6 + GlobalV6 string + + // CaptivePortal is set when we think there's a captive portal that is + // intercepting HTTP traffic. + CaptivePortal opt.Bool // Update BasicallyEqual when adding fields. } @@ -774,7 +805,7 @@ func conciseOptBool(b opt.Bool, trueVal string) string { } // BasicallyEqual reports whether ni and ni2 are basically equal, ignoring -// changes in DERP ServerLatency & RegionLatency. +// changes in DERP ServerLatency & RegionLatency func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool { if (ni == nil) != (ni2 == nil) { return false @@ -793,7 +824,16 @@ func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool { ni.PMP == ni2.PMP && ni.PCP == ni2.PCP && ni.PreferredDERP == ni2.PreferredDERP && - ni.LinkType == ni2.LinkType + ni.LinkType == ni2.LinkType && + ni.UDP == ni2.UDP && + ni.IPv6 == ni2.IPv6 && + ni.IPv4 == ni2.IPv4 && + ni.IPv6CanSend == ni2.IPv6CanSend && + ni.IPv4CanSend == ni2.IPv4CanSend && + ni.ICMPv4 == ni2.ICMPv4 && + ni.GlobalV4 == ni2.GlobalV4 && + ni.GlobalV6 == ni2.GlobalV6 && + ni.CaptivePortal == ni2.CaptivePortal } // Equal reports whether h and h2 are equal. diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index c4bb2e5858ff2..7c41059c14c9d 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -674,11 +674,20 @@ func (c *Conn) updateNetInfo(ctx context.Context) (*netcheck.Report, error) { PMP: report.PMP, PCP: report.PCP, HavePortMap: c.portMapper.HaveMapping(), + UDP: report.UDP, + IPv6: report.IPv6, + IPv4: report.IPv4, + IPv4CanSend: report.IPv4CanSend, + ICMPv4: report.ICMPv4, + GlobalV4: report.GlobalV4, + GlobalV6: report.GlobalV6, } for rid, d := range report.RegionV4Latency { + ni.DERPLatencyV4[rid] = d.Seconds() ni.DERPLatency[fmt.Sprintf("%d-v4", rid)] = d.Seconds() } for rid, d := range report.RegionV6Latency { + ni.DERPLatencyV6[rid] = d.Seconds() ni.DERPLatency[fmt.Sprintf("%d-v6", rid)] = d.Seconds() } @@ -687,6 +696,7 @@ func (c *Conn) updateNetInfo(ctx context.Context) (*netcheck.Report, error) { ni.WorkingUDP.Set(report.UDP) ni.WorkingICMPv4.Set(report.ICMPv4) ni.PreferredDERP = report.PreferredDERP + ni.CaptivePortal = report.CaptivePortal if ni.PreferredDERP == 0 { // Perhaps UDP is blocked. Pick a deterministic but arbitrary From e1878abab2ba70c0e6646e894b373862dd0ee830 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 1 Jul 2024 10:41:18 +0000 Subject: [PATCH 2/3] fix --- tailcfg/tailcfg.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 918bd78289f20..6e154e214b446 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -805,7 +805,7 @@ func conciseOptBool(b opt.Bool, trueVal string) string { } // BasicallyEqual reports whether ni and ni2 are basically equal, ignoring -// changes in DERP ServerLatency & RegionLatency +// changes in DERP ServerLatency & RegionLatency. func (ni *NetInfo) BasicallyEqual(ni2 *NetInfo) bool { if (ni == nil) != (ni2 == nil) { return false From 274cda7733f5c7201b6ab1c29576bcb236898cc9 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Mon, 1 Jul 2024 11:00:45 +0000 Subject: [PATCH 3/3] clone gen --- tailcfg/tailcfg_clone.go | 23 +++++++++++++++++++++++ tailcfg/tailcfg_view.go | 26 +++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index e33f2dc1eaaa5..a0b1da6294c4d 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -178,6 +178,18 @@ func (src *NetInfo) Clone() *NetInfo { dst.DERPLatency[k] = v } } + if dst.DERPLatencyV4 != nil { + dst.DERPLatencyV4 = map[int]float64{} + for k, v := range src.DERPLatencyV4 { + dst.DERPLatencyV4[k] = v + } + } + if dst.DERPLatencyV6 != nil { + dst.DERPLatencyV6 = map[int]float64{} + for k, v := range src.DERPLatencyV6 { + dst.DERPLatencyV6[k] = v + } + } return dst } @@ -196,6 +208,17 @@ var _NetInfoCloneNeedsRegeneration = NetInfo(struct { PreferredDERP int LinkType string DERPLatency map[string]float64 + DERPLatencyV4 map[int]float64 + DERPLatencyV6 map[int]float64 + UDP bool + IPv6 bool + IPv4 bool + IPv6CanSend bool + IPv4CanSend bool + ICMPv4 bool + GlobalV4 string + GlobalV6 string + CaptivePortal opt.Bool }{}) // Clone makes a deep copy of Login. diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 4dc536ce5c7d0..d5646c82c41f6 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -410,7 +410,20 @@ func (v NetInfoView) PreferredDERP() int { return v.ж.PreferredDER func (v NetInfoView) LinkType() string { return v.ж.LinkType } func (v NetInfoView) DERPLatency() views.Map[string, float64] { return views.MapOf(v.ж.DERPLatency) } -func (v NetInfoView) String() string { return v.ж.String() } + +func (v NetInfoView) DERPLatencyV4() views.Map[int, float64] { return views.MapOf(v.ж.DERPLatencyV4) } + +func (v NetInfoView) DERPLatencyV6() views.Map[int, float64] { return views.MapOf(v.ж.DERPLatencyV6) } +func (v NetInfoView) UDP() bool { return v.ж.UDP } +func (v NetInfoView) IPv6() bool { return v.ж.IPv6 } +func (v NetInfoView) IPv4() bool { return v.ж.IPv4 } +func (v NetInfoView) IPv6CanSend() bool { return v.ж.IPv6CanSend } +func (v NetInfoView) IPv4CanSend() bool { return v.ж.IPv4CanSend } +func (v NetInfoView) ICMPv4() bool { return v.ж.ICMPv4 } +func (v NetInfoView) GlobalV4() string { return v.ж.GlobalV4 } +func (v NetInfoView) GlobalV6() string { return v.ж.GlobalV6 } +func (v NetInfoView) CaptivePortal() opt.Bool { return v.ж.CaptivePortal } +func (v NetInfoView) String() string { return v.ж.String() } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _NetInfoViewNeedsRegeneration = NetInfo(struct { @@ -427,6 +440,17 @@ var _NetInfoViewNeedsRegeneration = NetInfo(struct { PreferredDERP int LinkType string DERPLatency map[string]float64 + DERPLatencyV4 map[int]float64 + DERPLatencyV6 map[int]float64 + UDP bool + IPv6 bool + IPv4 bool + IPv6CanSend bool + IPv4CanSend bool + ICMPv4 bool + GlobalV4 string + GlobalV6 string + CaptivePortal opt.Bool }{}) // View returns a readonly view of Login.