Skip to content

Conversation

@troglobit
Copy link
Contributor

@troglobit troglobit commented Dec 3, 2025

Description

This PR adds NTP server support using the ietf-ntp (RFC 9249) YANG model. The implementation supports three operational modes aligned with the documentation:

  • Standalone mode: Uses only a local reference clock to serve time
  • Server mode: Syncs from upstream NTP servers while serving clients
  • Peer mode: Bidirectional synchronization between two NTP servers

Features Implemented

  • Unicast server and peer configurations with composite key (address, type)
  • Configurable poll intervals (minpoll/maxpoll), NTP version, per-source port
  • Preference settings (prefer, iburst, burst with peer mode restrictions)
  • makestep: Fast initial synchronization (1.0s threshold, 3 update limit by default)
  • rtcsync: Hardware RTC synchronization enabled by default for time persistence across reboots
  • Comprehensive operational state:
    • Server statistics (packets received/sent/dropped)
    • Associations (address, mode, stratum)
    • Clock state (stratum, offsets, delays, frequencies, sync state)
  • Mutual exclusion with ietf-system NTP client enforced via YANG

Deviations & Limitations

Several advanced features from ietf-ntp have been deviated as not-supported:

  • Authentication (keys and per-source auth)
  • Access rules (currently allows all clients)
  • Interface-specific configurations (broadcast/multicast modes)
  • Source interface binding (chronyd limitation)

Testing

  • server_mode_standalone: Standalone operation with local reference clock
  • server_mode_server: Upstream sync while serving clients
  • server_mode_peer: Bidirectional peer synchronization
  • server_makestep: Configuration and operational state verification
  • server_client: Verifies ietf-ntp (server) and ietf-system (client)

Checklist

Tick relevant boxes, this PR is-a or has-a:

  • Bugfix
    • Regression tests
    • ChangeLog updates (for next release)
  • Feature
    • YANG model change => revision updated?
    • Regression tests added?
    • ChangeLog updates (for next release)
    • Documentation added?
  • Test changes
    • Checked in changed Readme.adoc (make test-spec)
    • Added new test to group Readme.adoc and yaml file
  • Code style update (formatting, renaming)
  • Refactoring (please detail in commit messages)
  • Build related changes
  • Documentation content changes
    • ChangeLog updated (for major changes)
  • Other (please describe):

Fixes #904

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
@troglobit troglobit marked this pull request as ready for review December 4, 2025 15:48
@troglobit troglobit requested a review from mattiaswal December 4, 2025 15:48
@troglobit troglobit linked an issue Dec 5, 2025 that may be closed by this pull request
Copy link
Contributor

@mattiaswal mattiaswal left a comment

Choose a reason for hiding this comment

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

Great work, will be a great addition to Infix 💪

NTP uses a hierarchical system called **stratum** to indicate distance from
authoritative time sources:

- **Stratum 0**: Reference clocks (atomic clocks, GPS receivers)
Copy link
Contributor

Choose a reason for hiding this comment

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

stratum 0 is atom clocks, GPS receivers will have 1 (derectly connected to stratum 0 as you say below)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for catching that!

}

/* Upstream server/peer configuration (unicast-configuration) */
rc = sr_get_items(session, XPATH_NTP_"/unicast-configuration", 0, 0, &val, &cnt);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a better API to get the xpath from the config struct ly_set *lydx_find_xpathf(struct lyd_node *ctx, const char *xpfmt, ...) no neet do allocate more memory.

fprintf(fp, "# Upstream NTP servers and peers\n");

for (size_t i = 0; i < cnt; i++) {
char *address = srx_get_str(session, "%s/address", val[i].xpath);
Copy link
Contributor

Choose a reason for hiding this comment

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

all srx_get_get_str can also be changed to use lydx_ API to reduce memory allocation


/* Reference clock (local stratum) - fallback time source */
if (lydx_get_xpathf(config, XPATH_NTP_"/refclock-master")) {
SRX_GET_UINT8(session, stratum, XPATH_NTP_"/refclock-master/master-stratum");
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, store the result of lydx_get_xpath and use lydx api.


/* Infer refclock-master with stratum 10 (safe fallback) */
DEBUG("Inferring NTP refclock-master with stratum 10");
inferred_uint8.data.uint8_val = 10;
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be default in the YANG model instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, of course! I see now that the YANG model does have a default value (16):

    container refclock-master {
      presence "NTP master clock is enabled.";
      description
        "Configures the local clock of this device as NTP server.";
      leaf master-stratum {
        type ntp-stratum;
        default "16";
        description
          "Stratum level from which NTP clients get their time
           synchronized.";
      }
    }

I'll make sure to just infer the container.

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.

Add support for NTP server

3 participants