8000 feat/DHCP NTP Servers - Enhances time sync with DHCP NTP and custom servers by IDisposable · Pull Request #625 · jetkvm/kvm · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat/DHCP NTP Servers - Enhances time sync with DHCP NTP and custom servers #625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

IDisposable
Copy link
Contributor

Extends time synchronization capabilities by:

  • Adding sup 10000 port for obtaining NTP server addresses from DHCP leases.
  • Enabling the use of user-defined NTP and HTTP servers for time synchronization.
  • Introduces a configurable time sync ordering, allowing users to specify the preferred order of time sources.

Since the ordering may have been previously defaulted and saved as "ntp,http", but that was being ignored and fallback-defaults were being used, in Ordering, `ntp` means use the fallback NTP servers, and `http` means use the fallback HTTP URLs. Thus `ntp_user_provided` and `http_user_provided` are the user specified static lists.
@IDisposable
Copy link
Contributor Author
IDisposable commented Jun 19, 2025

Fleshing out the device-side support for the configuration options added in #361

Still need the configuration UI to be finished, but this respects all the settings allowed in the config file https://github.com/jetkvm/kvm/pull/361/files#diff-5850db209b26ffd9fd3630b5255df6e30442d6cdfd7bcb6174c60924608dcc45R47-R50

chunkSize := 4
httpUrls := t.httpUrls
func (t *TimeSync) queryAllHttpTime(httpUrls []string) (now *time.Time) {
chunkSize := int(t.networkConfig.TimeSyncParallel.ValueOr(4))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honors the setting of the number of parallel time-sync requests (defaults to 4)

@@ -89,7 +91,7 @@ func NewNetworkInterfaceState(opts *NetworkInterfaceOptions) (*NetworkInterfaceS
opts.Logger.Error().Err(err).Msg("failed to update network state")
return
}

_ = s.updateNtpServersFromLease(lease)
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time we get a new DHCP lease, we need to copy over the NTP servers (if any) to the NetworkInterfaceState for access inside the time-sync logic.

@IDisposable IDisposable force-pushed the feat/dhcp-ntp-servers branch from 873fc91 to bdd8281 Compare June 19, 2025 01:49
@@ -43,9 +43,11 @@ type testNetworkConfig struct {
LLDPTxTLVs []string `json:"lldp_tx_tlvs,omitempty" one_of:"chassis,port,system,vlan" default:"chassis,port,system,vlan"`
MDNSMode null.String `json:"mdns_mode,omitempty" one_of:"disabled,auto,ipv4_only,ipv6_only" default:"auto"`
TimeSyncMode null.String `json:"time_sync_mode,omitempty" one_of:"ntp_only,ntp_and_http,http_only,custom" default:"ntp_and_http"`
TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,ntp_fallback" default:"ntp,http"`
TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,http_user_provided" default:"ntp,http"`
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since anyone who ran a version that included the previous code would have gotten the defaults written to their device's config file, we should behave the same way as before until they change the setting (there's still no UI for that, but that's a different PR).

So, the old behavior was to try NTP on the default servers, then HTTP on the default servers. This means that we should interpret the saved config line for ntp,http as if they requested the default servers.

Thus ntp means the prior default NTP servers and we need ntp_user_provided to specify user-supplied values.
The same logic applies to the HTTP URLs, so http refers to the prior default list of HTTP URLs.

Ideally, we probably would like the default ordering to be ntp_dhcp. then ntp, then http but that ship has sailed for anyone running 0.4.x. We might want to change the defaults here for future users.

Thus we added the http_user_provided option and deleted the redundant ntp_fallback option here to match

TimeSyncDisableFallback null.Bool `json:"time_sync_disable_fallback,omitempty" default:"false"`
TimeSyncParallel null.Int `json:"time_sync_parallel,omitempty" default:"4"`
TimeSyncNTPServers []string `json:"time_sync_ntp_servers,omitempty" validate_type:"ipv4_or_ipv6" required_if:"TimeSyncOrdering=ntp_user_provided"`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are where the user's user-provided NTP Server and HTTP URL values can be store. The required_if is likely not completely correct but changing the confparser seems way out of scope here. It will do the right thing iff the user selected only ntp_user_provided in the TimeSyncOrdering but not if they have it included in the string somewhere. I think @ym might know how to express that (includes not equals), but not there now.

@IDisposable IDisposable force-pushed the feat/dhcp-ntp-servers branch from bdd8281 to 57e9a65 Compare June 19, 2025 01:57
@@ -46,6 +47,10 @@ type ntpResult struct {

func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (now *time.Time, offset *time.Duration) {
results := make(chan *ntpResult, len(servers))

_, cancel := context.WithTimeout(context.Background(), timeout)
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add logic to cancel all outstanding NTP queries when we process a valid reply or end this chunk. This parallels logic in the HTTP path, and might not be desired.

@@ -66,15 +71,25 @@ func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (no
return
}

if response.IsKissOfDeath() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really need to make sure the NTP server we were talking to didn't tell us to go away. https://support.ntp.org/Dev/KoDResponses

rtcDevicePath: rtcDevice,
rtcLock: &sync.Mutex{},
preCheckFunc: opts.PreCheckFunc,
ntpServers: defaultNTPServers,
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need these two ntpServers and httpUrls in the TimeSync struct as they're available to the time-sync code.

@IDisposable IDisposable force-pushed the feat/dhcp-ntp-servers branch from 57e9a65 to 926fcf2 Compare June 19, 2025 02:10
func (t *TimeSync) getSyncMode() SyncMode {
syncMode := SyncMode{
Ntp: true,
Http: true,
Ordering: []string{"ntp_dhcp", "ntp", "http"},
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default ordering is a lie, unless there was no stored config, because that will overwrite this defaulting... but just in case, use the DHCP provided NTP servers, then the NTP default servers, then the default HTTP URLs

if syncMode.Http && now == nil {
now = t.queryAllHttpTime()
Orders:
for _, mode := range syncMode.Ordering {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the options in the order they specified.

case "ntp_user_provided":
if syncMode.Ntp {
t.l.Info().Msg("using NTP custom servers")
now, offset = t.queryNetworkTime(t.networkConfig.TimeSyncNTPServers)
Copy link
Contributor Author
@IDisposable IDisposable Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTP servers from the config (will be empty until the UI is coded)

case "ntp_dhcp":
if syncMode.Ntp {
t.l.Info().Msg("using NTP servers from DHCP")
now, offset = t.queryNetworkTime(t.dhcpNtpAddresses)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTP servers from the DHCP lease

case "ntp":
if syncMode.Ntp && syncMode.NtpUseFallback {
t.l.Info().Msg("using NTP fallback")
now, offset = t.queryNetworkTime(defaultNTPServers)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTP servers from the code-defined defaults (fallbacks)

case "http":
if syncMode.Http && syncMode.HttpUseFallback {
t.l.Info().Msg("using HTTP fallback")
now = t.queryAllHttpTime(defaultHTTPUrls)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP URLs from the code-defined defaults (fallbacks)

case "http_user_provided":
if syncMode.Http {
t.l.Info().Msg("using HTTP custom URLs")
now = t.queryAllHttpTime(t.networkConfig.TimeSyncHTTPUrls)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP URLs from the config (will be empty until the UI is coded)

}
}
case "http_user_provided":
if syncMode.Http {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, that http means the prior HTTP URL default list.

break Orders
}
}
case "ntp":
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that ntp means the prior default NTP server list.

@@ -19,8 +19,17 @@ func networkStateChanged() {
// do not block the main thread
go waitCtrlAndRequestDisplayUpdate(true)

if timeSync != nil {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These nil checks are necessary because we can hit networkStateChanged before we've even finished setting up.

@IDisposable
Copy link
Contributor Author

This is step one of two to enable all the rest of the NTP configurable behavior that was started in #361. Hopefully this is helpful.

@IDisposable
Copy link
Contributor Author

If this is merged first, PR #609 will need to be adjusted (or just closed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
0