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