[ntp:hackers] Simplifying NTPD

Poul-Henning Kamp phk at phk.freebsd.dk
Fri Jun 27 13:31:05 UTC 2014


I've been roped in to help improve ntpd and I have spent some time
getting to know the NTP project sourcecode again, and thinking about
what should happen to it.

The first thing which surprised me is how much source code we have
accumulated over the years.

I get it to 360.000 lines of C code, which really surprised me,
because my own Varnish project is only 72.000 lines of C code and
I perceive that as doing a lot more complex task.

The refclocks themselves amount to almost 50.000 lines of code,
and I have not yet determined how much supporting code is only
there for the refclocks, but it's probably a fair bit.

Writing a refclock to NTPD has never been very much fun, it is
a very constrained programming environment with some very peculiar
rules and regulations.

That was necessary when NTPD ran on FUZZBALLs and 68k CPUs, but
today we can afford to spend a little bit of CPU and memory to
make lives easier for programmers.

Refclocks are also troublesome in some other respects.

There are only so many Austron 2201 receivers in the world, and
testing that the refclock code or modifications to it actually work
is not an option for very many people.  This is not a new problem,
even when they were current 2201's were still scarce.

For that and other reasons, the code quality of the refclocks has
always been "divergent" from the rest of NTPD.

For these and other reasons, I want to divorce refclocks from the
rest of NTPD.

My proposal is to "evict" them to separate processes, so they don't
have to touch the rest of ntpd in any other way, than through a
simple well defined ASCII/text based protocol.

Refclocks will be configured with:

	refclock [arguments]

    arguments can be one or more of:
		stratum NUMBER
		uid	NAME|NUMBER
		gid	NAME|NUMBER
		exec	COMMAND_STRING

The COMMAND_STRING gets executed in a sub-process and emits ascii
messages on its standard-output, which goes by some (NTPD-chosen,
maybe platform-dependent) channel (pipe/socket) back to NTPD.

A typical refclock would send back something like:

	refclock	1.0
	id		GPS
	timeout		20
	precision	6
	delta	1403875215.067136  +0.0035
	delta	1403875216.067246  +0.0030
	delta	1403875217.068831  +0.0021
	...

And that means that you can implement a refclock in any programming
language or environment you want to: C, C++, Python, APL, Haskell,
INTERCAL, COBOL -- whatever.

It also means that refclocks becomes version-independent of NTPD
and can be packaged and distributed separately from NTPD.

If the refclock goes silent ($timeout) or misbehaves, NTPD will
kill the child process, wait a $timeout, and try to restart it.
If you kill the refclock process, the same thing happens.

That means that developing or tuning a refclock-implementation
will not need to start/stop NTPD all the time, and this not wait
for the "swing-in" of NTPD to see if it works.

On the NTPD side this will be the last refclock we ever add.

Once it is in place, we can start to port the subset of the existing
refclocks we can test (or get tested) into separate programs and
then finally clean all the refclock related stuff out of the NTPD
process.

I'm going to be working on other things in NTPD as well, but this
will be my "big goal project" for now.

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.


More information about the hackers mailing list