276 lines
10 KiB
Diff
276 lines
10 KiB
Diff
commit a0fb624d9a2bb804d85f4597b1249123c7978fed
|
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
Date: Thu Jan 16 15:04:04 2025 +0100
|
|
|
|
clock: Add variables for external grandmaster.
|
|
|
|
When ptp4l is configured to run as the server part of a bridge between
|
|
different domains, or a boundary clock split into multiple instances
|
|
(using one or two clocks), it announces its own clock identity as
|
|
grandmasterIdentity and stepsRemoved of 0. The clients of the server
|
|
don't see the true identity and distance, which can impact the result of
|
|
BMCA if there are multiple bridges/paths to the grandmaster. In the
|
|
worst case it could cause synchronization loops.
|
|
|
|
Add new variables to the clock that will override the grandmaster
|
|
identity and stepsRemoved values included in announce messages to make
|
|
it possible to pass them from the source domain as if the bridge/BC was
|
|
a single PTP instance. The variables will be used only when in the
|
|
grandmaster state and when not zero.
|
|
|
|
Runtime configuration over the UDS port will follow.
|
|
|
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
|
diff --git a/clock.c b/clock.c
|
|
index 863e9d8..fb33ac0 100644
|
|
--- a/clock.c
|
|
+++ b/clock.c
|
|
@@ -148,6 +148,8 @@ struct clock {
|
|
int step_window_counter;
|
|
int step_window;
|
|
struct time_zone tz[MAX_TIME_ZONES];
|
|
+ struct ClockIdentity ext_gm_identity;
|
|
+ int ext_gm_steps_removed;
|
|
};
|
|
|
|
struct clock the_clock;
|
|
@@ -830,13 +832,22 @@ static int clock_compare_pds(struct parentDS *pds1, struct parentDS *pds2)
|
|
static void clock_update_grandmaster(struct clock *c)
|
|
{
|
|
struct parentDS *pds = &c->dad.pds, old_pds = *pds;
|
|
+ struct ClockIdentity gm_identity, nul_identity;
|
|
+
|
|
+ memset(&nul_identity, 0, sizeof(nul_identity));
|
|
memset(&c->cur, 0, sizeof(c->cur));
|
|
memset(c->ptl, 0, sizeof(c->ptl));
|
|
|
|
+ if (!cid_eq(&nul_identity, &c->ext_gm_identity))
|
|
+ gm_identity = c->ext_gm_identity;
|
|
+ else
|
|
+ gm_identity = c->dds.clockIdentity;
|
|
+
|
|
+ c->cur.stepsRemoved = c->ext_gm_steps_removed;
|
|
pds->parentPortIdentity.clockIdentity = c->dds.clockIdentity;
|
|
/* Follow IEEE 1588 Table 30: Updates for state decision code M1 and M2 */
|
|
pds->parentPortIdentity.portNumber = 0;
|
|
- pds->grandmasterIdentity = c->dds.clockIdentity;
|
|
+ pds->grandmasterIdentity = gm_identity;
|
|
pds->grandmasterClockQuality = c->dds.clockQuality;
|
|
pds->grandmasterPriority1 = c->dds.priority1;
|
|
pds->grandmasterPriority2 = c->dds.priority2;
|
|
|
|
commit d76e19e4ed4a4c1892b98124ffb66dba354f76ac
|
|
Author: Miroslav Lichvar <mlichvar@redhat.com>
|
|
Date: Thu Jan 16 15:04:05 2025 +0100
|
|
|
|
Add management message for external grandmaster properties.
|
|
|
|
Add EXTERNAL_GRANDMASTER_PROPERTIES_NP management message to get and set
|
|
the new external grandmasterIdentity and stepsRemoved variables of the
|
|
clock. Together with the GRANDMASTER_SETTINGS_NP message all
|
|
grandmaster-specific values in announce messages can be now set.
|
|
|
|
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
|
|
|
diff --git a/clock.c b/clock.c
|
|
index fb33ac0..7c30066 100644
|
|
--- a/clock.c
|
|
+++ b/clock.c
|
|
@@ -422,6 +422,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
|
|
struct ptp_message *req,
|
|
struct ptp_message *rsp, int id)
|
|
{
|
|
+ struct external_grandmaster_properties_np *egpn;
|
|
struct alternate_time_offset_properties *atop;
|
|
struct alternate_time_offset_name *aton;
|
|
struct grandmaster_settings_np *gsn;
|
|
@@ -582,6 +583,12 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
|
|
mtd->val = c->local_sync_uncertain;
|
|
datalen = sizeof(*mtd);
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ egpn = (struct external_grandmaster_properties_np *) tlv->data;
|
|
+ egpn->gmIdentity = c->ext_gm_identity;
|
|
+ egpn->stepsRemoved = c->ext_gm_steps_removed;
|
|
+ datalen = sizeof(*egpn);
|
|
+ break;
|
|
default:
|
|
/* The caller should *not* respond to this message. */
|
|
tlv_extra_recycle(extra);
|
|
@@ -620,6 +627,7 @@ static int clock_management_get_response(struct clock *c, struct port *p,
|
|
static int clock_management_set(struct clock *c, struct port *p,
|
|
int id, struct ptp_message *req, int *changed)
|
|
{
|
|
+ struct external_grandmaster_properties_np *egpn;
|
|
struct alternate_time_offset_properties *atop;
|
|
struct alternate_time_offset_name *aton;
|
|
struct grandmaster_settings_np *gsn;
|
|
@@ -710,6 +718,13 @@ static int clock_management_set(struct clock *c, struct port *p,
|
|
break;
|
|
}
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ egpn = (struct external_grandmaster_properties_np *) tlv->data;
|
|
+ c->ext_gm_identity = egpn->gmIdentity;
|
|
+ c->ext_gm_steps_removed = egpn->stepsRemoved;
|
|
+ *changed = 1;
|
|
+ respond = 1;
|
|
+ break;
|
|
}
|
|
if (respond && !clock_management_get_response(c, p, id, req))
|
|
pr_err("failed to send management set response");
|
|
diff --git a/pmc.c b/pmc.c
|
|
index 0b61da4..6a6a94e 100644
|
|
--- a/pmc.c
|
|
+++ b/pmc.c
|
|
@@ -158,6 +158,7 @@ static void pmc_show_signaling(struct ptp_message *msg, FILE *fp)
|
|
|
|
static void pmc_show(struct ptp_message *msg, FILE *fp)
|
|
{
|
|
+ struct external_grandmaster_properties_np *egpn;
|
|
struct alternate_time_offset_properties *atop;
|
|
struct alternate_time_offset_name *aton;
|
|
struct ieee_c37_238_settings_np *pwr;
|
|
@@ -475,6 +476,14 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
|
|
fprintf(fp, "SYNCHRONIZATION_UNCERTAIN_NP "
|
|
IFMT "uncertain %hhu", mtd->val);
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ egpn = (struct external_grandmaster_properties_np *) mgt->data;
|
|
+ fprintf(fp, "EXTERNAL_GRANDMASTER_PROPERTIES_NP "
|
|
+ IFMT "gmIdentity %s"
|
|
+ IFMT "stepsRemoved %hu",
|
|
+ cid2str(&egpn->gmIdentity),
|
|
+ egpn->stepsRemoved);
|
|
+ break;
|
|
case MID_PORT_DATA_SET:
|
|
p = (struct portDS *) mgt->data;
|
|
if (p->portState > PS_SLAVE) {
|
|
diff --git a/pmc_common.c b/pmc_common.c
|
|
index 7c77a10..b55e7ec 100644
|
|
--- a/pmc_common.c
|
|
+++ b/pmc_common.c
|
|
@@ -132,6 +132,7 @@ struct management_id idtab[] = {
|
|
{ "GRANDMASTER_SETTINGS_NP", MID_GRANDMASTER_SETTINGS_NP, do_set_action },
|
|
{ "SUBSCRIBE_EVENTS_NP", MID_SUBSCRIBE_EVENTS_NP, do_set_action },
|
|
{ "SYNCHRONIZATION_UNCERTAIN_NP", MID_SYNCHRONIZATION_UNCERTAIN_NP, do_set_action },
|
|
+ { "EXTERNAL_GRANDMASTER_PROPERTIES_NP", MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP, do_set_action },
|
|
/* Port management ID values */
|
|
{ "NULL_MANAGEMENT", MID_NULL_MANAGEMENT, null_management },
|
|
{ "CLOCK_DESCRIPTION", MID_CLOCK_DESCRIPTION, do_get_action },
|
|
@@ -172,6 +173,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
|
{
|
|
int cnt, code = idtab[index].code, freq_traceable, leap_59, leap_61,
|
|
ptp_timescale, time_traceable, utc_off_valid;
|
|
+ struct external_grandmaster_properties_np egpn;
|
|
struct alternate_time_offset_properties atop;
|
|
struct ieee_c37_238_settings_np pwr;
|
|
struct grandmaster_settings_np gsn;
|
|
@@ -183,6 +185,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
|
char onoff_parent_data_set[4] = "off";
|
|
char onoff_cmlds[4] = "off";
|
|
char display_name[11] = {0};
|
|
+ char identity[19];
|
|
uint64_t jump;
|
|
uint8_t key;
|
|
int enable;
|
|
@@ -400,6 +403,19 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
|
IEEE_C37_238_VERSION_2017);
|
|
}
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ cnt = sscanf(str, " %*s %*s "
|
|
+ "gmIdentity %18s "
|
|
+ "stepsRemoved %hu ",
|
|
+ identity,
|
|
+ &egpn.stepsRemoved);
|
|
+ if (cnt != 2 || str2cid(identity, &egpn.gmIdentity)) {
|
|
+ fprintf(stderr, "%s SET needs 2 values\n",
|
|
+ idtab[index].name);
|
|
+ break;
|
|
+ }
|
|
+ pmc_send_set_action(pmc, code, &egpn, sizeof(egpn));
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
@@ -704,6 +720,9 @@ static int pmc_tlv_datalen(struct pmc *pmc, int id)
|
|
case MID_POWER_PROFILE_SETTINGS_NP:
|
|
len += sizeof(struct ieee_c37_238_settings_np);
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ len += sizeof(struct external_grandmaster_properties_np);
|
|
+ break;
|
|
case MID_LOG_ANNOUNCE_INTERVAL:
|
|
case MID_ANNOUNCE_RECEIPT_TIMEOUT:
|
|
case MID_LOG_SYNC_INTERVAL:
|
|
diff --git a/tlv.c b/tlv.c
|
|
index b22277c..0639a71 100644
|
|
--- a/tlv.c
|
|
+++ b/tlv.c
|
|
@@ -164,6 +164,7 @@ static void alttime_offset_pre_send(struct tlv_extra *extra)
|
|
static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
|
struct tlv_extra *extra)
|
|
{
|
|
+ struct external_grandmaster_properties_np *egpn;
|
|
struct alternate_time_offset_properties *atop;
|
|
struct alternate_time_offset_name *aton;
|
|
struct ieee_c37_238_settings_np *pwr;
|
|
@@ -490,6 +491,12 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len,
|
|
NTOHL(cmlds->scaledNeighborRateRatio);
|
|
NTOHL(cmlds->as_capable);
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ if (data_len != sizeof(struct external_grandmaster_properties_np))
|
|
+ goto bad_length;
|
|
+ egpn = (struct external_grandmaster_properties_np *) m->data;
|
|
+ NTOHS(egpn->stepsRemoved);
|
|
+ break;
|
|
case MID_SAVE_IN_NON_VOLATILE_STORAGE:
|
|
case MID_RESET_NON_VOLATILE_STORAGE:
|
|
case MID_INITIALIZE:
|
|
@@ -513,6 +520,7 @@ bad_length:
|
|
|
|
static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
|
|
{
|
|
+ struct external_grandmaster_properties_np *egpn;
|
|
struct alternate_time_offset_properties *atop;
|
|
struct ieee_c37_238_settings_np *pwr;
|
|
struct unicast_master_table_np *umtn;
|
|
@@ -688,6 +696,10 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra)
|
|
HTONL(cmlds->scaledNeighborRateRatio);
|
|
HTONL(cmlds->as_capable);
|
|
break;
|
|
+ case MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP:
|
|
+ egpn = (struct external_grandmaster_properties_np *)m->data;
|
|
+ HTONS(egpn->stepsRemoved);
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
diff --git a/tlv.h b/tlv.h
|
|
index 1b464f3..f0c47ce 100644
|
|
--- a/tlv.h
|
|
+++ b/tlv.h
|
|
@@ -100,6 +100,7 @@ enum management_action {
|
|
#define MID_GRANDMASTER_SETTINGS_NP 0xC001
|
|
#define MID_SUBSCRIBE_EVENTS_NP 0xC003
|
|
#define MID_SYNCHRONIZATION_UNCERTAIN_NP 0xC006
|
|
+#define MID_EXTERNAL_GRANDMASTER_PROPERTIES_NP 0xC00D
|
|
|
|
/* Port management ID values */
|
|
#define MID_NULL_MANAGEMENT 0x0000
|
|
@@ -489,6 +490,11 @@ struct msg_interface_rate_tlv {
|
|
UInteger16 numberOfBitsAfterTimestamp;
|
|
} PACKED;
|
|
|
|
+struct external_grandmaster_properties_np {
|
|
+ struct ClockIdentity gmIdentity;
|
|
+ UInteger16 stepsRemoved;
|
|
+} PACKED;
|
|
+
|
|
/**
|
|
* Allocates a new tlv_extra structure.
|
|
* @return Pointer to a new structure on success or NULL otherwise.
|