In no particular order, they are manual preempt, scored  
auto-expiry, and start/stop-pump.

Manual preempt basically adds the preempt as a depressible button  
for external helper scripts.

Scored auto expiry adds a score a bit like the one used by the  
NTP pool, and kicks the worst of the lot off the island 6 times a
week and the eldest once. I also, think it needs controls and
documentation, but I didn't see how at the time.

start/stop pump has a couple of values for the number of pool
association children to ask for more when the number drops, and
more importantly to stop asking when the population burgeons. I
forgot to add a way to adjust it off.
From 07e651a521f26bcad95a927d6cd1fac9ec8bd586 Mon Sep 17 00:00:00 2001
From: James Browning <jamesb.f...@gmail.com>
Date: Wed, 9 Jun 2021 16:15:03 -0700
Subject: [PATCH] ntpd: add 'preempt' as under documented server option ...

It is intended for external tools that emulate the pool option.
---
 docs/includes/assoc-options.adoc | 6 ++++++
 ntpd/keyword-gen.c               | 1 +
 ntpd/ntp_config.c                | 4 ++++
 ntpd/ntp_parser.y                | 2 ++
 4 files changed, 13 insertions(+)

diff --git a/docs/includes/assoc-options.adoc b/docs/includes/assoc-options.adoc
index 3028c0b89..aace11a53 100644
--- a/docs/includes/assoc-options.adoc
+++ b/docs/includes/assoc-options.adoc
@@ -53,6 +53,12 @@
   Marks the server as unused, except for display purposes. The server is
   discarded by the selection algorithm.
 
++preempt+::
+  Marks the server as preemptable. If the server is not performing well,
+  it can be automatically dissociated. Intended for use by external tools
+  and not in config files or manual entry via +ntp+. It is automatically
+  added to servers from the +pool+ option.
+
 +prefer+::
   Marks the server as preferred. All other things being equal, this host
   will be chosen for synchronization among a set of correctly operating
diff --git a/ntpd/keyword-gen.c b/ntpd/keyword-gen.c
index 1b7de71ae..5482a95f4 100644
--- a/ntpd/keyword-gen.c
+++ b/ntpd/keyword-gen.c
@@ -87,6 +87,7 @@ struct key_tok ntp_keywords[] = {
 { "mode",		T_Mode,			FOLLBY_TOKEN },
 { "noselect",		T_Noselect,		FOLLBY_TOKEN },
 { "true",		T_True,			FOLLBY_TOKEN },
+{ "preempt",		T_Preempt,		FOLLBY_TOKEN },
 { "prefer",		T_Prefer,		FOLLBY_TOKEN },
 { "subtype",		T_Subtype,		FOLLBY_TOKEN },
 { "version",		T_Version,		FOLLBY_TOKEN },
diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c
index b5638d7e6..3735e1b16 100644
--- a/ntpd/ntp_config.c
+++ b/ntpd/ntp_config.c
@@ -617,6 +617,10 @@ create_peer_node(
 				break;
 #endif
 
+			case T_Preempt:
+				my_node->ctl.flags |= FLAG_PREEMPT;
+				break;
+
 			case T_Prefer:
 				my_node->ctl.flags |= FLAG_PREFER;
 				break;
diff --git a/ntpd/ntp_parser.y b/ntpd/ntp_parser.y
index 91a15ce2c..0ab3fe4c5 100644
--- a/ntpd/ntp_parser.y
+++ b/ntpd/ntp_parser.y
@@ -177,6 +177,7 @@
 %token	<Integer>	T_Pidfile
 %token	<Integer>	T_Pool
 %token	<Integer>	T_Ppspath
+%token	<Integer>	T_Preempt
 %token	<Integer>	T_Prefer
 %token	<Integer>	T_Protostats
 %token	<Integer>	T_Rawstats
@@ -421,6 +422,7 @@ option_flag_keyword
 	|	T_Noselect
 	|	T_Noval
 	|	T_Nts
+	|	T_Preempt
 	|	T_Prefer
 	|	T_True
 	;
-- 
2.25.1

From 63c0cd2258ae692e95e81ea5b72ee2a2fbf3de24 Mon Sep 17 00:00:00 2001
From: James Browning <jamesb.f...@gmail.com>
Date: Mon, 14 Jun 2021 07:33:18 -0700
Subject: [PATCH] ntpd: Purge worst ephemeral peer daily and the oldest weekly
 ...

Also add an undocumented variable for 'ntpq -c "rv ${peer}" to
show number used to make the worst determination.
---
 include/ntp.h      |  1 +
 include/ntpd.h     |  2 ++
 ntpd/ntp_control.c |  4 ++++
 ntpd/ntp_proto.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 ntpd/ntp_timer.c   |  2 ++
 5 files changed, 53 insertions(+)

diff --git a/include/ntp.h b/include/ntp.h
index 729e482ee..bedcd9043 100644
--- a/include/ntp.h
+++ b/include/ntp.h
@@ -244,6 +244,7 @@ struct peer_ctl {
  * It used to be called ttl which was used by multicast which we dropped.
  */
 struct peer {
+	double goodness;	/* how worthy the server is to survive the day */
 	struct peer *p_link;	/* link pointer in free & peer lists */
 	struct peer *adr_link;	/* link pointer in address hash */
 	struct peer *aid_link;	/* link pointer in associd hash */
diff --git a/include/ntpd.h b/include/ntpd.h
index a15ac00ff..89b4ac268 100644
--- a/include/ntpd.h
+++ b/include/ntpd.h
@@ -196,6 +196,8 @@ extern	void	set_sys_tick_precision(double);
 extern	void	proto_config	(int, unsigned long, double);
 extern	void	proto_clr_stats (void);
 
+extern	void	purge_day	(bool);
+
 /* ntp_restrict.c */
 extern	void	init_restrict	(void);
 extern	unsigned short	restrictions	(sockaddr_u *);
diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c
index 4b66ecd71..108811191 100644
--- a/ntpd/ntp_control.c
+++ b/ntpd/ntp_control.c
@@ -522,6 +522,8 @@ static const struct ctl_var peer_var[] = {
 	/* new in NTPsec */
 #define	CP_NTSCOOKIES		49
 	{ CP_NTSCOOKIES, RO|DEF, "ntscookies" },
+#define	CP_GOODNESS		50
+	{ CP_GOODNESS, RO|DEF, "goodness" },
 #define	CP_MAXCODE		((sizeof(peer_var)/sizeof(peer_var[0])) - 1)
 	{ 0,		EOV, "" }
 };
@@ -2054,6 +2056,8 @@ ctl_putpeer(
 
 	CASE_INT(CP_NTSCOOKIES, p->nts_state.count);
 
+	CASE_DBL6(CP_GOODNESS, p->goodness);
+
 	default:
 		break;
 	}
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c
index 895567c83..3733303b6 100644
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -625,6 +625,21 @@ handle_procpkt(
 	}
 	peer->reach |= 1;
 
+	// Nudge the peer survivability score --  badly ripped from
+	// lines 140-158,165 of the pools Control/Monitor.pm /
+	// credit is for ABH, blame for JamesB192
+	if ((peer->stratum == 0)||(peer->stratum > 15)) {
+		// already dropped the 5 which factors below as well
+	} else if ((peer->stratum >= 8)||(delta > 3)) {
+		peer->goodness += 1;
+	} else if (delta > 0.75) {
+		peer->goodness += 3;
+	} else if (delta > 0.075) {
+		peer->goodness += 6 - (4 * theta);
+	} else {
+		peer->goodness += 6;
+	};
+
 	/* Hooray! Pass our new sample off to the clock filter. */
 	clock_filter(peer, theta + peer->cfg.bias, delta, epsilon);
 }
@@ -856,6 +871,8 @@ transmit(
 		peer->outdate = current_time;
 		peer->unreach++;
 		peer->reach <<= 1;
+		peer->goodness *= 0.95;
+		peer->goodness -= 5;
 		if (!peer->reach) {
 
 			/*
@@ -2951,3 +2968,30 @@ void maybe_log_junk(const char *tag, struct recvbuf *rbufp) {
 	"%s: %s", tag, buf);
 }
 
+void purge_day(bool eldest) {
+    double worstscore = 20;
+//    uint6_t ties = 0;
+    struct peer *loop, *purgable = NULL;
+    if (eldest) {
+	for (loop = peer_list; loop->p_link != NULL; loop = loop->p_link) {
+	    if (loop->cfg.flags & FLAG_PREEMPT) {
+		unpeer(loop);
+		return;
+	    }
+	}
+	return;
+    }
+    for (loop = peer_list; loop->p_link != NULL; loop = loop->p_link) {
+	if ((loop->cfg.flags & FLAG_PREEMPT)&&(loop->goodness < worstscore)) {
+	    worstscore = loop->goodness;
+	    purgable = loop;
+//	    ties = 1;
+//	} else if (loop->goodness == worstscore) {
+//	    ties++;
+	}
+    }
+    if (purgable != NULL) {
+	unpeer(purgable);
+	purgable = NULL;
+    }
+}
diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c
index 3dd44e859..cf4e8d53f 100644
--- a/ntpd/ntp_timer.c
+++ b/ntpd/ntp_timer.c
@@ -288,6 +288,8 @@ timer(void)
 		if (leapf_timer <= current_time) {
 			leapf_timer += SECSPERDAY;
 			check_leap_file(true, now);
+			bool eldest = (6 == (current_time / SECSPERDAY) % 7);
+			purge_day(eldest);
 		} else {
 			check_leap_file(false, now);
 		}
-- 
2.25.1

From 82f367b4db2d3780314b3a2bad577c73279a247e Mon Sep 17 00:00:00 2001
From: James Browning <jamesb.f...@gmail.com>
Date: Wed, 16 Jun 2021 08:17:35 -0700
Subject: [PATCH] ntpd: Add startpump and stoppump options intended for pool
 use ...

If children of a pool association have been disassociated
decrement count and remove them from the array. If the number
of children above is greater than or equal to stoppump
(default 5 constrained 1..12) stop making requests, otherwise
if the number of children above is less than or equal to
startpump (default 3 constrained 0..11) start making requests.

Start not making requests, and document nothing.
---
 docs/includes/assoc-options.adoc | 10 +++++++++
 include/ntp.h                    |  4 ++++
 ntpd/keyword-gen.c               |  2 ++
 ntpd/ntp_config.c                | 26 ++++++++++++++++++++++
 ntpd/ntp_dns.c                   | 38 ++++++++++++++++++++++++++++++--
 ntpd/ntp_parser.y                |  4 ++++
 6 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/docs/includes/assoc-options.adoc b/docs/includes/assoc-options.adoc
index 3028c0b89..49d0e9a7a 100644
--- a/docs/includes/assoc-options.adoc
+++ b/docs/includes/assoc-options.adoc
@@ -59,6 +59,16 @@
   hosts. See the "Mitigation Rules and the prefer Keyword" page
   for further information.
 
++starpump+ 'on_at'::
++stoppump+ 'off_at'::
+  When the number of associated children for a pool directive drops below
+ _on_at_, begin associating new pools of ntp servers until the number rises
+ to _off_at_. When the number of associated children from the same pool
+ association is above _off_at_, stop asking for new server pools until their
+ number goes down to _on_at_. _on_at_ can be set between 0 and 11 inclusive,
+ defaulting to 3, and must be below _off_at_, while _off_at_ may be between 1
+ and 12 incluse, defaulting to 5, and must be greater than _on_at_.
+
 +true+::
   Mark the association to assume truechimer status; that is, always
   survive the selection and clustering algorithms. This option can be
diff --git a/include/ntp.h b/include/ntp.h
index 729e482ee..ecca2e087 100644
--- a/include/ntp.h
+++ b/include/ntp.h
@@ -188,6 +188,8 @@ struct peer_ctl {
 	double		bias;
 	struct ntscfg_t nts_cfg;
 	uint32_t	mode;	/* only used by refclocks */
+	uint32_t	startpump;	/* only used by pool */
+	uint32_t	stoppump;	/* only used by pool */
 #ifdef REFCLOCK
 	uint32_t	baud;
 	char		*path;
@@ -260,6 +262,8 @@ struct peer {
 	uint8_t	num_events;	/* number of error events */
 	struct ntsclient_t nts_state;	/* per-peer NTS state */
 
+	uint16_t *children;	/* count and addocids of pool children  */
+
 	/*
 	 * Variables used by reference clock support
 	 */
diff --git a/ntpd/keyword-gen.c b/ntpd/keyword-gen.c
index 1b7de71ae..d1b3e1286 100644
--- a/ntpd/keyword-gen.c
+++ b/ntpd/keyword-gen.c
@@ -88,6 +88,8 @@ struct key_tok ntp_keywords[] = {
 { "noselect",		T_Noselect,		FOLLBY_TOKEN },
 { "true",		T_True,			FOLLBY_TOKEN },
 { "prefer",		T_Prefer,		FOLLBY_TOKEN },
+{ "startpump",		T_Startpump,		FOLLBY_TOKEN },
+{ "stoppump",		T_Stoppump,		FOLLBY_TOKEN },
 { "subtype",		T_Subtype,		FOLLBY_TOKEN },
 { "version",		T_Version,		FOLLBY_TOKEN },
 /*** MONITORING COMMANDS ***/
diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c
index b5638d7e6..9e00bd014 100644
--- a/ntpd/ntp_config.c
+++ b/ntpd/ntp_config.c
@@ -565,6 +565,8 @@ create_peer_node(
 
 	my_node->ctl.version = NTP_VERSION;
 	my_node->ctl.minpoll = NTP_MINDPOLL;
+	my_node->ctl.startpump = 3;
+	my_node->ctl.stoppump = 5;
         /* can not set maxpoll default yet, it may be NTP_MAXDPOLL or minpoll */
 	my_node->ctl.maxpoll = NTP_MAXPOLL_UNK;
 	my_node->ctl.bias = 0;
@@ -678,6 +680,30 @@ create_peer_node(
 			my_node->ctl.mode = option->value.u;
 			break;
 
+		case T_Startpump:
+			if ((option->value.u >= 12)) {
+				msyslog(LOG_ERR, "CONFIG: startpump: not in range 0..11");
+				errflag = true;
+			} else if (option->value.u <= my_node->ctl.stoppump) {
+				msyslog(LOG_ERR, "CONFIG: startpump: not less than stoppump value.");
+				errflag = true;
+			} else {
+				my_node->ctl.startpump = option->value.u;
+			}
+			break;
+
+		case T_Stoppump:
+			if ((option->value.u = 0)||(option->value.u > 12)) {
+				msyslog(LOG_ERR, "CONFIG: stoppump: not in range 1..12");
+				errflag = true;
+			} else if (option->value.u >= my_node->ctl.stoppump) {
+				msyslog(LOG_ERR, "CONFIG: stoppump: not greater than startpump value.");
+				errflag = true;
+			} else {
+				my_node->ctl.stoppump = option->value.u;
+			}
+			break;
+
 		case T_Key:
 			if (option->value.u >= NTP_MAXKEY) {
 				msyslog(LOG_ERR, "CONFIG: key: invalid argument");
diff --git a/ntpd/ntp_dns.c b/ntpd/ntp_dns.c
index e87e20b99..993ee7fa0 100644
--- a/ntpd/ntp_dns.c
+++ b/ntpd/ntp_dns.c
@@ -66,6 +66,39 @@ bool dns_probe(struct peer* pp)
 		hostname = socktoa(&pp->srcadr);
 	}
 
+	if (pp->cast_flags & MDF_POOL) {
+		if (NULL == pp->children) {
+			pp->children = calloc(sizeof(uint16_t), NTP_HASH_SIZE);
+			if (NULL == pp->children) {
+				_Exit(1);
+			}
+		}
+		uint16_t *kids = pp->children;
+		uint16_t old = kids[0] & ~(1 << 15), new, iterator;
+		bool pull = (kids[0] & (1 << 15));
+		new = iterator = 1;
+		while(iterator < old) {
+			if (findpeerbyassoc(kids[iterator])) {
+				new++;
+			}
+			kids[iterator] = kids[new];
+			iterator++;
+		}
+		for (iterator = new + 1; iterator <= old; iterator++) {
+			kids[iterator] = 0;
+		}
+		if (pull && (new >= pp->cfg.stoppump)) {
+			kids[0] = new & ~(1 << 15);
+			pull = false;
+		} else if (!pull && (new <= pp->cfg.startpump)) {
+			kids[0] = (1 << 15) | new;
+			pull = true;
+		}
+		if (!pull) {
+		    return true;
+		}
+	}
+
 	msyslog(LOG_INFO, "DNS: dns_probe: %s, cast_flags:%x, flags:%x%s",
 		hostname, pp->cast_flags, pp->cfg.flags, busy);
         if (NULL != active)	/* normally redundant */
@@ -128,10 +161,11 @@ void dns_check(void)
 		/* Both dns_take_pool and dns_take_server log something. */
 		// msyslog(LOG_INFO, "DNS: Take %s=>%s",
 		//		socktoa(ai->ai_addr), socktoa(&sockaddr));
-		if (active->cast_flags & MDF_POOL)
+		if (active->cast_flags & MDF_POOL) {
 			dns_take_pool(active, &sockaddr);
-		else
+		} else {
 			dns_take_server(active, &sockaddr);
+		}
 	}
 
 	switch (gai_rc) {
diff --git a/ntpd/ntp_parser.y b/ntpd/ntp_parser.y
index 91a15ce2c..b1f159f13 100644
--- a/ntpd/ntp_parser.y
+++ b/ntpd/ntp_parser.y
@@ -192,6 +192,7 @@
 %token	<Integer>	T_Setvar
 %token	<Integer>	T_Source
 %token	<Integer>	T_Stacksize
+%token	<Integer>	T_Startpump
 %token	<Integer>	T_Statistics
 %token	<Integer>	T_Stats
 %token	<Integer>	T_Statsdir
@@ -199,6 +200,7 @@
 %token	<Integer>	T_Stepback
 %token	<Integer>	T_Stepfwd
 %token	<Integer>	T_Stepout
+%token	<Integer>	T_Stoppump
 %token	<Integer>	T_Stratum
 %token	<Integer>	T_Subtype
 %token	<String>	T_String		/* Not a token */
@@ -451,6 +453,8 @@ option_int_keyword
 	|	T_Version
 	|	T_Baud
 	|	T_Holdover
+	|	T_Startpump
+	|	T_Stoppump
 	;
 
 option_double
-- 
2.25.1

_______________________________________________
devel mailing list
devel@ntpsec.org
https://lists.ntpsec.org/mailman/listinfo/devel

Reply via email to