
Fix clock selection algorithm behavior where a clock source starts to match requirements but is not selected because it has the same ha_priority than active. In a HA configuration with two or more clocks configured with equal ha_priority if no clock source matches the requirements the first one in the configuration file is selected active. This is a standard behavior to always have a clock source, even when they are not synchronized. When one of the clock sources starts to match the requirements it must be selected active, regardless of the priority. But when a second clock source starts to match the requirements and has the same ha_priority as the active, the active remains the clock source. There is no need to switch active when they have equal ha_priority. Test plan: two sources with the same priority PASS: Verify a clock source is selected active when it starts to match the requirements and the current active doesn't match them, even if they have equal ha_priority. PASS: Verify a clock source isn't selected active when it starts to match the requirements and the current active also matches them. Regression: two sources with different priority PASS: Verify a clock source is selected active when it starts to match the requirements and the current active doesn't match them, even if their ha_priority is lower than the actives. PASS: Verify a clock source is selected active when it starts to match the requirements and the current active also matches them but has lower ha_priority configured. PASS: Verify a clock source isn't selected active when it starts to match the requirements and the current active also matches them and has higher ha_priority configured. Story: 2010723 Task: 48699 Change-Id: If80532b7b8febcc164f7c748a8d4122b4f10fd3b Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
184 lines
5.6 KiB
Diff
184 lines
5.6 KiB
Diff
From 3e6dd047083625ca03df9b4bbdc781e7dd079ff2 Mon Sep 17 00:00:00 2001
|
|
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
|
Date: Mon, 12 Jun 2023 17:29:30 -0300
|
|
Subject: [PATCH 29/50] pmc_agent: Generalize the method that queries the local
|
|
clock identity.
|
|
|
|
When started in automatic mode, the phc2sys program first queries the
|
|
local clock identification and then the number of ports immediately
|
|
afterwords. However, both of those values come from the default data
|
|
set. Make code both simpler and more efficient by caching the entire
|
|
data set inside of the agent.
|
|
|
|
A subsequent patch will fix the run_pmc_get_number_ports() method to
|
|
return the cached result.
|
|
|
|
The active word in the function's name is "query" rather that "get" in
|
|
order to distinguish methods that send and receive over the network
|
|
from those that merely return a cached value.
|
|
|
|
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
|
|
|
[commit 919703eb06b7ee9679308597e01e1da0162736d7 upstream]
|
|
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
|
---
|
|
phc2sys.c | 20 +++++++++++---------
|
|
pmc_agent.c | 46 +++++++++++++++++++++++-----------------------
|
|
pmc_agent.h | 15 ++++++++++++++-
|
|
3 files changed, 48 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/phc2sys.c b/phc2sys.c
|
|
index 32e6e13..0f33630 100644
|
|
--- a/phc2sys.c
|
|
+++ b/phc2sys.c
|
|
@@ -854,23 +854,25 @@ static int phc2sys_recv_subscribed(void *context, struct ptp_message *msg,
|
|
|
|
static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
|
{
|
|
- int err, number_ports, res;
|
|
- int state, timestamping;
|
|
+ int err, number_ports, state, timestamping;
|
|
char iface[IFNAMSIZ];
|
|
struct clock *clock;
|
|
struct port *port;
|
|
unsigned int i;
|
|
|
|
while (1) {
|
|
- if (!is_running())
|
|
+ if (!is_running()) {
|
|
return -1;
|
|
- res = run_pmc_clock_identity(priv->node, 1000);
|
|
- if (res < 0)
|
|
- return -1;
|
|
- if (res > 0)
|
|
+ }
|
|
+ err = pmc_agent_query_dds(priv->node, 1000);
|
|
+ if (!err) {
|
|
break;
|
|
- /* res == 0, timeout */
|
|
- pr_notice("Waiting for ptp4l...");
|
|
+ }
|
|
+ if (err == -ETIMEDOUT) {
|
|
+ pr_notice("Waiting for ptp4l...");
|
|
+ } else {
|
|
+ return -1;
|
|
+ }
|
|
}
|
|
|
|
number_ports = run_pmc_get_number_ports(priv->node, 1000);
|
|
diff --git a/pmc_agent.c b/pmc_agent.c
|
|
index cc729ab..51023d1 100644
|
|
--- a/pmc_agent.c
|
|
+++ b/pmc_agent.c
|
|
@@ -38,8 +38,8 @@ struct pmc_agent {
|
|
struct pmc *pmc;
|
|
uint64_t pmc_last_update;
|
|
|
|
- struct ClockIdentity clock_identity;
|
|
- int clock_identity_set;
|
|
+ struct defaultDS dds;
|
|
+ bool dds_valid;
|
|
int leap;
|
|
int pmc_ds_requested;
|
|
bool stay_subscribed;
|
|
@@ -63,10 +63,11 @@ static void send_subscription(struct pmc_agent *node)
|
|
|
|
static int check_clock_identity(struct pmc_agent *node, struct ptp_message *msg)
|
|
{
|
|
- if (!node->clock_identity_set)
|
|
+ if (!node->dds_valid) {
|
|
return 1;
|
|
- return cid_eq(&node->clock_identity,
|
|
- &msg->header.sourcePortIdentity.clockIdentity);
|
|
+ }
|
|
+ return cid_eq(&node->dds.clockIdentity,
|
|
+ &msg->header.sourcePortIdentity.clockIdentity);
|
|
}
|
|
|
|
static int is_msg_mgt(struct ptp_message *msg)
|
|
@@ -251,24 +252,6 @@ void run_pmc_events(struct pmc_agent *node)
|
|
run_pmc(node, 0, -1, &msg);
|
|
}
|
|
|
|
-int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
|
-{
|
|
- struct ptp_message *msg;
|
|
- struct defaultDS *dds;
|
|
- int res;
|
|
-
|
|
- res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
|
- if (res <= 0)
|
|
- return res;
|
|
-
|
|
- dds = (struct defaultDS *) management_tlv_data(msg);
|
|
- memcpy(&node->clock_identity, &dds->clockIdentity,
|
|
- sizeof(struct ClockIdentity));
|
|
- node->clock_identity_set = 1;
|
|
- msg_put(msg);
|
|
- return 1;
|
|
-}
|
|
-
|
|
int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
|
|
pmc_node_recv_subscribed_t *recv_subscribed, void *context)
|
|
{
|
|
@@ -317,6 +300,23 @@ int pmc_agent_get_sync_offset(struct pmc_agent *agent)
|
|
return agent->sync_offset;
|
|
}
|
|
|
|
+int pmc_agent_query_dds(struct pmc_agent *node, int timeout)
|
|
+{
|
|
+ struct ptp_message *msg;
|
|
+ struct defaultDS *dds;
|
|
+ int res;
|
|
+
|
|
+ res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
|
+ if (is_run_pmc_error(res)) {
|
|
+ return run_pmc_err2errno(res);
|
|
+ }
|
|
+ dds = (struct defaultDS *) management_tlv_data(msg);
|
|
+ memcpy(&node->dds, dds, sizeof(node->dds));
|
|
+ node->dds_valid = true;
|
|
+ msg_put(msg);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int pmc_agent_query_port_properties(struct pmc_agent *node, int timeout,
|
|
unsigned int port, int *state,
|
|
int *tstamping, char *iface)
|
|
diff --git a/pmc_agent.h b/pmc_agent.h
|
|
index ea37bf9..9d8bd1c 100644
|
|
--- a/pmc_agent.h
|
|
+++ b/pmc_agent.h
|
|
@@ -33,7 +33,6 @@ typedef int pmc_node_recv_subscribed_t(void *context, struct ptp_message *msg,
|
|
|
|
int init_pmc_node(struct config *cfg, struct pmc_agent *agent, const char *uds,
|
|
pmc_node_recv_subscribed_t *recv_subscribed, void *context);
|
|
-int run_pmc_clock_identity(struct pmc_agent *agent, int timeout);
|
|
int run_pmc_wait_sync(struct pmc_agent *agent, int timeout);
|
|
int run_pmc_get_number_ports(struct pmc_agent *agent, int timeout);
|
|
void run_pmc_events(struct pmc_agent *agent);
|
|
@@ -70,6 +69,20 @@ int pmc_agent_get_leap(struct pmc_agent *agent);
|
|
*/
|
|
int pmc_agent_get_sync_offset(struct pmc_agent *agent);
|
|
|
|
+/**
|
|
+ * Queries the local clock's default data set from the ptp4l service.
|
|
+ * The result of the query will be cached inside of the agent.
|
|
+ *
|
|
+ * In addition:
|
|
+ *
|
|
+ * - The port state notification callback might be invoked.
|
|
+ *
|
|
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
|
+ * @param timeout Transmit and receive timeout in milliseconds.
|
|
+ * @return Zero on success, negative error code otherwise.
|
|
+ */
|
|
+int pmc_agent_query_dds(struct pmc_agent *agent, int timeout);
|
|
+
|
|
/**
|
|
* Queries the port properties of a given port from the ptp4l service.
|
|
*
|
|
--
|
|
2.25.1
|
|
|