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