Let's Talk About SNTP (Simple

In the next posts I will tell about my explorations with the Raspberry Pi Pico W using the C/C++ SDK. As a first project, I decided to adapt a piece of code I wrote using the Arduino libraries for an ESP8266 board. This code (that you can see here, with comments in Portuguese) get the current time and date from an NTP server. In this post I will give a brief explanation of the Simple Network Time Protocol that is used for that.


The NTP (Network Time Protocol) is a clock synchronization protocol, implemented over UDP. Its been updated through the years, its current version is 4 and its formal documentation is RFC 5905. A full implementation can achieve millisecond precision synchronization.

SNTP (Simple Network Time Protocol) is a subset of NTP, using the same packet format but ignoring some fields and sophisticated sync algorithms. Its is currently also defined in RFC 5905, but I found the previous version (RFC 4330) more readble.

From now on I will talk about client NTP, according to RFC 4330. The packets exchanged with the server have the following format:

All timestamps have 64 bits.  The first 32 bits are the integer part of the number of seconds since 00:00:00 of 1/1/1900 (UTC), the next 32 bits are the fractional part. This counters will run over in 2036, the most recent version of NTP supports also 128 bits timestamps.

To request the current timestamp from the server, we send this packet with all fiels zero, except for:
  • Mode: 3 (client)
  • VN: 4 (the version we support)
  • Transmit Timestamp: while this field can be zero, it is suggested to put the local timestamp so we can validate the response.
The server will respond (or not, the UDP protocol does not guarantee deliver, only integrity) with a packet will all fields filled. "Transmit Timerstamp" is the server timestamp when it filled the packet, for simplicity we will use this value as our new local timestamp (NTP describes algorithms for accounting for delays and getting better precision).

Some checks can be done to discard invalid packets (very unlikely) or packets received out of order (UDP does not guarantee the order of delivery):
  • Mode should be 4 (server)
  • VN should be 4 (the version we requested)
  • LI must be between 0 and 2
  • Stratum and Transmit Timestamp should be non-zero
  • Originate Timestamp should be the value we sent as Transmit Timestamp
RFC 4330 details these checks (and others).

To maintain synchronization this exchange should be repeated periodically. RFC 4330 recommends a minimum time of 60 seconds between requests and "forbids" intervals bellow 14 seconds.

There are many libraries available that implement SNTP (even though they say they implement the full NTP). A popular Arduino library is NTPClient. The lwIP library (used by the Pico C/C++ SDK) includes support for SNTP. There is also a example in pico-examples that implements SNTP, that is what we are going to look at in a future post (before writing my own code).

Comments

Popular posts from this blog

Using the PIO to Interface a PS/2 Keyboard