Skip to content

Conversation

@IDisposable
Copy link
Contributor

Extends time synchronization capabilities by:

  • Adding support 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)

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
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

TimeSyncOrdering []string `json:"time_sync_ordering,omitempty" one_of:"http,ntp,ntp_dhcp,ntp_user_provided,http_user_provided" default:"ntp,http"`
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
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.

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
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.

// 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)

@ym ym merged commit 11a095c into jetkvm:dev Jul 11, 2025
11 of 13 checks passed
@IDisposable IDisposable deleted the feat/dhcp-ntp-servers branch July 11, 2025 08:15
adammkelly pushed a commit to adammkelly/kvm that referenced this pull request Jul 15, 2025
…m#625)

* Ensure the mDNS mode is set every time network state changes

Eliminates (mostly) duplicate code

* Add custom NTP and HTTP time sync servers

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.

* Add support for using DHCP-provided NTP server
adammkelly pushed a commit to adammkelly/kvm that referenced this pull request Jul 15, 2025
…m#625)

* Ensure the mDNS mode is set every time network state changes

Eliminates (mostly) duplicate code

* Add custom NTP and HTTP time sync servers

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.

* Add support for using DHCP-provided NTP server
@adamshiervani adamshiervani added this to the 0.5.0 milestone Aug 4, 2025
@adamshiervani adamshiervani moved this to Done in JetKVM Aug 4, 2025
@adamshiervani adamshiervani modified the milestones: 0.5.0, 0.4.7 Sep 11, 2025
ym pushed a commit to ym/jetkvm-kvm that referenced this pull request Sep 26, 2025
…m#625)

* Ensure the mDNS mode is set every time network state changes

Eliminates (mostly) duplicate code

* Add custom NTP and HTTP time sync servers

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.

* Add support for using DHCP-provided NTP server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants