good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
bor
Commits
b1908f6a
Commit
b1908f6a
authored
Feb 15, 2016
by
Péter Szilágyi
Browse files
Options
Downloads
Patches
Plain Diff
psp/discovery: NTP sanity check clock drift in case of expirations
parent
7841f0cc
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
p2p/discover/ntp.go
+99
-0
99 additions, 0 deletions
p2p/discover/ntp.go
p2p/discover/udp.go
+29
-4
29 additions, 4 deletions
p2p/discover/udp.go
with
128 additions
and
4 deletions
p2p/discover/ntp.go
0 → 100644
+
99
−
0
View file @
b1908f6a
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Contains the NTP time drift detection via the SNTP protocol:
// https://tools.ietf.org/html/rfc4330
package
discover
import
(
"net"
"sort"
"time"
)
// ntpPool is the NTP server to query for the current time
const
ntpPool
=
"pool.ntp.org"
// durationSlice attaches the methods of sort.Interface to []time.Duration,
// sorting in increasing order.
type
durationSlice
[]
time
.
Duration
func
(
s
durationSlice
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
durationSlice
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
<
s
[
j
]
}
func
(
s
durationSlice
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
// sntpDrift does a naive time resolution against an NTP server and returns the
// measured drift. This method uses the simple version of NTP. It's not precise
// but should be fine for these purposes.
//
// Note, it executes two extra measurements compared to the number of requested
// ones to be able to discard the two extremes as outliers.
func
sntpDrift
(
measurements
int
)
(
time
.
Duration
,
error
)
{
// Resolve the address of the NTP server
addr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
ntpPool
+
":123"
)
if
err
!=
nil
{
return
0
,
err
}
// Construct the time request (empty package with only 2 fields set):
// Bits 3-5: Protocol version, 3
// Bits 6-8: Mode of operation, client, 3
request
:=
make
([]
byte
,
48
)
request
[
0
]
=
3
<<
3
|
3
// Execute each of the measurements
drifts
:=
[]
time
.
Duration
{}
for
i
:=
0
;
i
<
measurements
+
2
;
i
++
{
// Dial the NTP server and send the time retrieval request
conn
,
err
:=
net
.
DialUDP
(
"udp"
,
nil
,
addr
)
if
err
!=
nil
{
return
0
,
err
}
defer
conn
.
Close
()
sent
:=
time
.
Now
()
if
_
,
err
=
conn
.
Write
(
request
);
err
!=
nil
{
return
0
,
err
}
// Retrieve the reply and calculate the elapsed time
conn
.
SetDeadline
(
time
.
Now
()
.
Add
(
5
*
time
.
Second
))
reply
:=
make
([]
byte
,
48
)
if
_
,
err
=
conn
.
Read
(
reply
);
err
!=
nil
{
return
0
,
err
}
elapsed
:=
time
.
Since
(
sent
)
// Reconstruct the time from the reply data
sec
:=
uint64
(
reply
[
43
])
|
uint64
(
reply
[
42
])
<<
8
|
uint64
(
reply
[
41
])
<<
16
|
uint64
(
reply
[
40
])
<<
24
frac
:=
uint64
(
reply
[
47
])
|
uint64
(
reply
[
46
])
<<
8
|
uint64
(
reply
[
45
])
<<
16
|
uint64
(
reply
[
44
])
<<
24
nanosec
:=
sec
*
1e9
+
(
frac
*
1e9
)
>>
32
t
:=
time
.
Date
(
1900
,
1
,
1
,
0
,
0
,
0
,
0
,
time
.
UTC
)
.
Add
(
time
.
Duration
(
nanosec
))
.
Local
()
// Calculate the drift based on an assumed answer time of RRT/2
drifts
=
append
(
drifts
,
sent
.
Sub
(
t
)
+
elapsed
/
2
)
}
// Calculate average drif (drop two extremities to avoid outliers)
sort
.
Sort
(
durationSlice
(
drifts
))
drift
:=
time
.
Duration
(
0
)
for
i
:=
1
;
i
<
len
(
drifts
)
-
1
;
i
++
{
drift
+=
drifts
[
i
]
}
return
drift
/
time
.
Duration
(
measurements
),
nil
}
This diff is collapsed.
Click to expand it.
p2p/discover/udp.go
+
29
−
4
View file @
b1908f6a
...
@@ -51,6 +51,9 @@ const (
...
@@ -51,6 +51,9 @@ const (
respTimeout
=
500
*
time
.
Millisecond
respTimeout
=
500
*
time
.
Millisecond
sendTimeout
=
500
*
time
.
Millisecond
sendTimeout
=
500
*
time
.
Millisecond
expiration
=
20
*
time
.
Second
expiration
=
20
*
time
.
Second
ntpThreshold
=
32
// Continuous timeouts after which to check NTP
driftThreshold
=
10
*
time
.
Second
// Allowed clock drift before warning user
)
)
// RPC packet types
// RPC packet types
...
@@ -316,13 +319,14 @@ func (t *udp) handleReply(from NodeID, ptype byte, req packet) bool {
...
@@ -316,13 +319,14 @@ func (t *udp) handleReply(from NodeID, ptype byte, req packet) bool {
}
}
}
}
// loop runs in its own goroutin. it keeps track of
// loop runs in its own goroutin
e
. it keeps track of
// the refresh timer and the pending reply queue.
// the refresh timer and the pending reply queue.
func
(
t
*
udp
)
loop
()
{
func
(
t
*
udp
)
loop
()
{
var
(
var
(
plist
=
list
.
New
()
plist
=
list
.
New
()
timeout
=
time
.
NewTimer
(
0
)
timeout
=
time
.
NewTimer
(
0
)
nextTimeout
*
pending
// head of plist when timeout was last reset
nextTimeout
*
pending
// head of plist when timeout was last reset
contTimeouts
=
0
// number of continuous timeouts to do NTP checks
)
)
<-
timeout
.
C
// ignore first timeout
<-
timeout
.
C
// ignore first timeout
defer
timeout
.
Stop
()
defer
timeout
.
Stop
()
...
@@ -377,19 +381,40 @@ func (t *udp) loop() {
...
@@ -377,19 +381,40 @@ func (t *udp) loop() {
p
.
errc
<-
nil
p
.
errc
<-
nil
plist
.
Remove
(
el
)
plist
.
Remove
(
el
)
}
}
// Reset the continuous timeout counter (time drift detection)
contTimeouts
=
0
}
}
}
}
r
.
matched
<-
matched
r
.
matched
<-
matched
case
now
:=
<-
timeout
.
C
:
case
now
:=
<-
timeout
.
C
:
nextTimeout
=
nil
nextTimeout
=
nil
// Notify and remove callbacks whose deadline is in the past.
// Notify and remove callbacks whose deadline is in the past.
for
el
:=
plist
.
Front
();
el
!=
nil
;
el
=
el
.
Next
()
{
for
el
:=
plist
.
Front
();
el
!=
nil
;
el
=
el
.
Next
()
{
p
:=
el
.
Value
.
(
*
pending
)
p
:=
el
.
Value
.
(
*
pending
)
if
now
.
After
(
p
.
deadline
)
||
now
.
Equal
(
p
.
deadline
)
{
if
now
.
After
(
p
.
deadline
)
||
now
.
Equal
(
p
.
deadline
)
{
p
.
errc
<-
errTimeout
p
.
errc
<-
errTimeout
plist
.
Remove
(
el
)
plist
.
Remove
(
el
)
contTimeouts
++
}
}
// If we've accumulated too many timeouts, do an NTP time sync check
if
contTimeouts
>
ntpThreshold
{
go
func
()
{
drift
,
err
:=
sntpDrift
(
3
)
switch
{
case
err
!=
nil
:
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"No UDP connectivity, maybe blocked by firewall? (%v)"
,
err
)
case
drift
<
-
driftThreshold
||
drift
>
driftThreshold
:
glog
.
V
(
logger
.
Warn
)
.
Infof
(
"System clock seems off by %v, which can prevent network connectivity"
,
drift
)
default
:
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Sanity NTP check reported %v drift, all ok"
,
drift
)
}
}
}()
contTimeouts
=
0
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment