health: track whether we have a functional udp4 bind

Suggested-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Signed-off-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Josh Bleecher Snyder 2021-04-28 10:36:54 -07:00
parent 7dc7078d96
commit fe50ded95c
2 changed files with 19 additions and 1 deletions

View File

@ -37,6 +37,7 @@
ipnState string ipnState string
ipnWantRunning bool ipnWantRunning bool
anyInterfaceUp = true // until told otherwise anyInterfaceUp = true // until told otherwise
udp4Unbound bool
) )
// Subsystem is the name of a subsystem whose health can be monitored. // Subsystem is the name of a subsystem whose health can be monitored.
@ -47,7 +48,7 @@
// the system, rather than one particular subsystem. // the system, rather than one particular subsystem.
SysOverall = Subsystem("overall") SysOverall = Subsystem("overall")
// SysRouter is the name the wgengine/router subsystem. // SysRouter is the name of the wgengine/router subsystem.
SysRouter = Subsystem("router") SysRouter = Subsystem("router")
// SysDNS is the name of the net/dns subsystem. // SysDNS is the name of the net/dns subsystem.
@ -214,6 +215,14 @@ func SetAnyInterfaceUp(up bool) {
selfCheckLocked() selfCheckLocked()
} }
// SetUDP4Unbound sets whether the udp4 bind failed completely.
func SetUDP4Unbound(unbound bool) {
mu.Lock()
defer mu.Unlock()
udp4Unbound = unbound
selfCheckLocked()
}
func timerSelfCheck() { func timerSelfCheck() {
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
@ -257,6 +266,9 @@ func overallErrorLocked() error {
if d := now.Sub(derpRegionLastFrame[rid]).Round(time.Second); d > tooIdle { if d := now.Sub(derpRegionLastFrame[rid]).Round(time.Second); d > tooIdle {
return fmt.Errorf("haven't heard from home DERP region %v in %v", rid, d) return fmt.Errorf("haven't heard from home DERP region %v in %v", rid, d)
} }
if udp4Unbound {
return errors.New("no udp4 bind")
}
// TODO: use // TODO: use
_ = inMapPollSince _ = inMapPollSince

View File

@ -2671,6 +2671,9 @@ func (c *Conn) bindSocket(rucPtr **RebindingUDPConn, network string) error {
} }
// Success. // Success.
ruc.pconn = pconn ruc.pconn = pconn
if network == "udp4" {
health.SetUDP4Unbound(false)
}
return nil return nil
} }
@ -2679,6 +2682,9 @@ func (c *Conn) bindSocket(rucPtr **RebindingUDPConn, network string) error {
// This keeps the receive funcs alive for a future in which // This keeps the receive funcs alive for a future in which
// we get a link change and we can try binding again. // we get a link change and we can try binding again.
ruc.pconn = newBlockForeverConn() ruc.pconn = newBlockForeverConn()
if network == "udp4" {
health.SetUDP4Unbound(true)
}
return fmt.Errorf("failed to bind any ports (tried %v)", ports) return fmt.Errorf("failed to bind any ports (tried %v)", ports)
} }