fed1e1
Backported commit f774703cb1eee058a346aec3341fee0be329bd6d
fed1e1
Author: Karthikkumar V <kvaloor@altiostar.com>
fed1e1
Date:   Fri Feb 26 06:54:07 2021 +0000
fed1e1
fed1e1
    Clock Class Threshold Feature addition for PTP4L
fed1e1
    
fed1e1
    This code changes brings in the ability to program the acceptable
fed1e1
    clockClass threshold beyond which device will move to holdover/free-run.
fed1e1
    Default clockClass threshold is 248.
fed1e1
    Example Use-Case:
fed1e1
    This is needed in the cases where T-SC/T-BC Slave might want to listen
fed1e1
    only on PRC clockCLass and anything beyond that might not be acceptible
fed1e1
    and would want to go to holdover (with SyncE backup or internal oscillator).
fed1e1
    
fed1e1
    Signed-off-by: Karthikkumar V <kvaloor@altiostar.com>
fed1e1
    Signed-off-by: Ramana Reddy <rreddy@altiostar.com>
fed1e1
fed1e1
diff --git a/clock.c b/clock.c
fed1e1
index c1fcff6..d584748 100644
fed1e1
--- a/clock.c
fed1e1
+++ b/clock.c
fed1e1
@@ -114,6 +114,7 @@ struct clock {
fed1e1
 	int utc_offset;
fed1e1
 	int time_flags;  /* grand master role */
fed1e1
 	int time_source; /* grand master role */
fed1e1
+	UInteger8 clock_class_threshold;
fed1e1
 	UInteger8 max_steps_removed;
fed1e1
 	enum servo_state servo_state;
fed1e1
 	enum timestamp_type timestamping;
fed1e1
@@ -978,6 +979,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
fed1e1
 	c->default_dataset.localPriority =
fed1e1
 		config_get_int(config, NULL, "G.8275.defaultDS.localPriority");
fed1e1
 	c->max_steps_removed = config_get_int(config, NULL,"maxStepsRemoved");
fed1e1
+	c->clock_class_threshold = config_get_int(config, NULL, "clock_class_threshold");
fed1e1
 
fed1e1
 	/* Harmonize the twoStepFlag with the time_stamping option. */
fed1e1
 	if (config_harmonize_onestep(config)) {
fed1e1
@@ -1711,6 +1713,11 @@ UInteger8 clock_max_steps_removed(struct clock *c)
fed1e1
 	return c->max_steps_removed;
fed1e1
 }
fed1e1
 
fed1e1
+UInteger8 clock_get_clock_class_threshold(struct clock *c)
fed1e1
+{
fed1e1
+	return c->clock_class_threshold;
fed1e1
+}
fed1e1
+
fed1e1
 UInteger16 clock_steps_removed(struct clock *c)
fed1e1
 {
fed1e1
 	return c->cur.stepsRemoved;
fed1e1
diff --git a/clock.h b/clock.h
fed1e1
index e7daf97..845d54f 100644
fed1e1
--- a/clock.h
fed1e1
+++ b/clock.h
fed1e1
@@ -289,6 +289,13 @@ int clock_slave_only(struct clock *c);
fed1e1
  */
fed1e1
 UInteger8 clock_max_steps_removed(struct clock *c);
fed1e1
 
fed1e1
+/**
fed1e1
+ * Obtain the clock class threshold field from a clock's default data set.
fed1e1
+ * @param c  The clock instance.
fed1e1
+ * @return   Configured clock class threshold value.
fed1e1
+ */
fed1e1
+UInteger8 clock_get_clock_class_threshold(struct clock *c);
fed1e1
+
fed1e1
 /**
fed1e1
  * Obtain the steps removed field from a clock's current data set.
fed1e1
  * @param c  The clock instance.
fed1e1
diff --git a/config.c b/config.c
fed1e1
index c3deddb..bf1049f 100644
fed1e1
--- a/config.c
fed1e1
+++ b/config.c
fed1e1
@@ -231,6 +231,7 @@ struct config_item config_tab[] = {
fed1e1
 	GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX),
fed1e1
 	GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX),
fed1e1
 	GLOB_ITEM_STR("clockIdentity", "000000.0000.000000"),
fed1e1
+	GLOB_ITEM_INT("clock_class_threshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 6, CLOCK_CLASS_THRESHOLD_DEFAULT),
fed1e1
 	GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu),
fed1e1
 	GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu),
fed1e1
 	GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu),
fed1e1
diff --git a/configs/default.cfg b/configs/default.cfg
fed1e1
index 9604219..b2ffa94 100644
fed1e1
--- a/configs/default.cfg
fed1e1
+++ b/configs/default.cfg
fed1e1
@@ -60,6 +60,7 @@ verbose			0
fed1e1
 summary_interval	0
fed1e1
 kernel_leap		1
fed1e1
 check_fup_sync		0
fed1e1
+clock_class_threshold	248
fed1e1
 #
fed1e1
 # Servo Options
fed1e1
 #
fed1e1
diff --git a/ds.h b/ds.h
fed1e1
index 9d9c417..dff6d5e 100644
fed1e1
--- a/ds.h
fed1e1
+++ b/ds.h
fed1e1
@@ -87,6 +87,7 @@ struct parent_ds {
fed1e1
 
fed1e1
 #define CURRENT_UTC_OFFSET  37 /* 1 Jan 2017 */
fed1e1
 #define INTERNAL_OSCILLATOR 0xA0
fed1e1
+#define CLOCK_CLASS_THRESHOLD_DEFAULT 248
fed1e1
 
fed1e1
 struct timePropertiesDS {
fed1e1
 	Integer16    currentUtcOffset;
fed1e1
diff --git a/port.c b/port.c
fed1e1
index 2bb974c..eb3b319 100644
fed1e1
--- a/port.c
fed1e1
+++ b/port.c
fed1e1
@@ -1870,6 +1870,14 @@ int process_announce(struct port *p, struct ptp_message *m)
fed1e1
 		return result;
fed1e1
 	}
fed1e1
 
fed1e1
+	if (m->announce.grandmasterClockQuality.clockClass >
fed1e1
+		clock_get_clock_class_threshold(p->clock)) {
fed1e1
+		pl_err(60, "port %hu: Master clock quality received is "
fed1e1
+			"greater than configured, ignoring master!",
fed1e1
+			portnum(p));
fed1e1
+		return result;
fed1e1
+	}
fed1e1
+
fed1e1
 	switch (p->state) {
fed1e1
 	case PS_INITIALIZING:
fed1e1
 	case PS_FAULTY:
fed1e1
diff --git a/ptp4l.8 b/ptp4l.8
fed1e1
index b04936a..ca76175 100644
fed1e1
--- a/ptp4l.8
fed1e1
+++ b/ptp4l.8
fed1e1
@@ -455,6 +455,11 @@ message is greater than or equal to the value of maxStepsRemoved the
fed1e1
 Announce message is not considered in the operation of the BMCA.
fed1e1
 The default value is 255.
fed1e1
 .TP
fed1e1
+.B clock_class_threshold
fed1e1
+The maximum clock class value from master, acceptible to sub-ordinate
fed1e1
+clock beyond which it moves out of lock state.
fed1e1
+The default value is 248.
fed1e1
+.TP
fed1e1
 
fed1e1
 .B domainNumber
fed1e1
 The domain attribute of the local clock.