Merge "Redundant HA PTP timing clock sources support"
This commit is contained in:
commit
2c20b741c8
@ -1,7 +1,7 @@
|
||||
From 63b43924294da6cb177d0509120b2e957580441c Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon, 31 May 2021 11:07:52 +0200
|
||||
Subject: [PATCH 1/10] clock: Reset state when switching port with same best clock.
|
||||
Subject: [PATCH 1/47] clock: Reset state when switching port with same best clock.
|
||||
|
||||
When the best port is changed, but the ID of the best clock doesn't
|
||||
change (e.g. a passive port is activated on link failure), reset the
|
||||
|
@ -4,7 +4,7 @@ In-Reply-To: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerv
|
||||
References: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerville@windriver.com>
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon, 31 May 2021 11:07:53 +0200
|
||||
Subject: [PATCH 2/10] clock: Reset clock check on best clock/port change.
|
||||
Subject: [PATCH 2/47] clock: Reset clock check on best clock/port change.
|
||||
|
||||
Reset the clock check when the best clock or port changes, together with
|
||||
the other state like current estimated delay and frequency. This avoids
|
||||
|
@ -4,7 +4,7 @@ In-Reply-To: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerv
|
||||
References: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerville@windriver.com>
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon, 31 May 2021 11:07:54 +0200
|
||||
Subject: [PATCH 3/10] port: Don't check timestamps from non-slave ports.
|
||||
Subject: [PATCH 3/47] port: Don't check timestamps from non-slave ports.
|
||||
|
||||
Don't perform the sanity check on receive timestamps from ports in
|
||||
non-slave states to avoid false positives in the jbod mode, where
|
||||
|
@ -4,7 +4,7 @@ In-Reply-To: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerv
|
||||
References: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerville@windriver.com>
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon, 31 May 2021 11:07:55 +0200
|
||||
Subject: [PATCH 4/10] port: Don't renew raw transport.
|
||||
Subject: [PATCH 4/47] port: Don't renew raw transport.
|
||||
|
||||
Renewing of the transport on announce/sync timeout is needed in the
|
||||
client-only mode to avoid getting stuck with a broken multicast socket
|
||||
|
@ -4,7 +4,7 @@ In-Reply-To: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630611367.git.Jim.Somerv
|
||||
References: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630611367.git.Jim.Somerville@windriver.com>
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Mon, 31 May 2021 11:07:56 +0200
|
||||
Subject: [PATCH 5/10] clockcheck: Increase minimum interval.
|
||||
Subject: [PATCH 5/47] clockcheck: Increase minimum interval.
|
||||
|
||||
Increase the minimum check interval to 1 second to measure the frequency
|
||||
offset more accurately and with default configuration make false
|
||||
|
@ -4,7 +4,7 @@ In-Reply-To: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerv
|
||||
References: <0389752e3aecf8d2b2743f16ce1408a58088bea9.1630418391.git.Jim.Somerville@windriver.com>
|
||||
From: Cole Walker <cole.walker@windriver.com>
|
||||
Date: Wed, 23 Jun 2021 11:14:41 -0400
|
||||
Subject: [PATCH 6/10] Add option to disable default port selection in phc2sys
|
||||
Subject: [PATCH 6/47] Add option to disable default port selection in phc2sys
|
||||
|
||||
This change serves to address an issue in phc2sys
|
||||
where the local ptp clocks are not synced together properly if the local
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 6428c2628c013c408ec09355ad37eb12fa6bb20f Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Wed, 18 May 2022 11:33:35 +0200
|
||||
Subject: [PATCH 7/10] sysoff: Change sysoff_measure() to return errno.
|
||||
Subject: [PATCH 7/47] sysoff: Change sysoff_measure() to return errno.
|
||||
|
||||
Return -errno from failed ioctl instead of the SYSOFF_* enum from the
|
||||
measurement functions to allow the callers to check for specific errors.
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 38a530d94fc5aa73bde424d05e2e38348e64d7e5 Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Wed, 18 May 2022 11:33:36 +0200
|
||||
Subject: [PATCH 8/10] sysoff: Change log level of ioctl error messages.
|
||||
Subject: [PATCH 8/47] sysoff: Change log level of ioctl error messages.
|
||||
|
||||
Change the log level of ioctl error messages to the error level to make
|
||||
them visible in default configuration, with the exception of EOPNOTSUPP
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 11ae077e31d9957df01aacfa17eea5b5d548b249 Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Wed, 18 May 2022 11:33:37 +0200
|
||||
Subject: [PATCH 9/10] sysoff: Retry on EBUSY when probing supported ioctls.
|
||||
Subject: [PATCH 9/47] sysoff: Retry on EBUSY when probing supported ioctls.
|
||||
|
||||
Handle EBUSY when probing support for a PTP_SYS_OFFSET ioctl. Try each
|
||||
ioctl up to three times before giving up on it to make the detection
|
||||
|
@ -1,7 +1,7 @@
|
||||
From e4fd6a930213e6f0f009eb070d51b1e14db60d1b Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
Date: Wed, 18 May 2022 11:33:38 +0200
|
||||
Subject: [PATCH 10/10] phc2sys: Don't exit when reading of PHC fails with EBUSY.
|
||||
Subject: [PATCH 10/47] phc2sys: Don't exit when reading of PHC fails with EBUSY.
|
||||
|
||||
Reading of the PHC can occasionally fail with some drivers, e.g. the ice
|
||||
driver returns EBUSY when it fails to get a lock. Continue in the loop
|
||||
|
@ -0,0 +1,641 @@
|
||||
From 0c5c39a8cd3675d91e872a75d75854907950957d Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 13:47:47 -0300
|
||||
Subject: [PATCH 11/47] phc2sys: extract PMC functionality into a smaller
|
||||
struct pmc_node
|
||||
|
||||
This creates a smaller structure within phc2sys_private, which embeds
|
||||
all properties related to the PMC. This structure is called "pmc_node",
|
||||
which is somewhat reminiscent of the old name of phc2sys_private (struct
|
||||
node). But the advantage is that struct pmc_node can be reused by other
|
||||
modules.
|
||||
|
||||
The phc2sys code that is executed upon a subscription update,
|
||||
recv_subscribed, is now refactored into a function pointer callback. It
|
||||
is imaginable that other programs might to do other things in it.
|
||||
Note that putting this function pointer in struct pmc_node is, long
|
||||
term, maybe not the best of choices. It is only needed from the
|
||||
run_pmc_events() code path, and could be therefore passed as a more
|
||||
local callback to that function only. However, for that, further
|
||||
refactoring is needed inside the common run_pmc() function, so that is
|
||||
being left for another time.
|
||||
|
||||
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 1ca1419ad7e6cc04cf893f5a9ca449a90f39f4e0 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 228 ++++++++++++++++++++++++++++++------------------------
|
||||
1 file changed, 125 insertions(+), 103 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 7959015..86b9822 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "clockadj.h"
|
||||
#include "clockcheck.h"
|
||||
+#include "contain.h"
|
||||
#include "ds.h"
|
||||
#include "fsm.h"
|
||||
#include "missing.h"
|
||||
@@ -99,23 +100,34 @@ struct port {
|
||||
struct clock *clock;
|
||||
};
|
||||
|
||||
+struct pmc_node;
|
||||
+
|
||||
+typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
+ struct ptp_message *msg,
|
||||
+ int excluded);
|
||||
+
|
||||
+struct pmc_node {
|
||||
+ struct pmc *pmc;
|
||||
+ int pmc_ds_requested;
|
||||
+ uint64_t pmc_last_update;
|
||||
+ int sync_offset;
|
||||
+ int leap;
|
||||
+ int utc_offset_traceable;
|
||||
+ int clock_identity_set;
|
||||
+ struct ClockIdentity clock_identity;
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
+};
|
||||
+
|
||||
struct phc2sys_private {
|
||||
unsigned int stats_max_count;
|
||||
int sanity_freq_limit;
|
||||
enum servo_type servo_type;
|
||||
int phc_readings;
|
||||
double phc_interval;
|
||||
- int sync_offset;
|
||||
int forced_sync_offset;
|
||||
- int utc_offset_traceable;
|
||||
- int leap;
|
||||
int kernel_leap;
|
||||
- struct pmc *pmc;
|
||||
- int pmc_ds_requested;
|
||||
- uint64_t pmc_last_update;
|
||||
int state_changed;
|
||||
- int clock_identity_set;
|
||||
- struct ClockIdentity clock_identity;
|
||||
+ struct pmc_node node;
|
||||
LIST_HEAD(port_head, port) ports;
|
||||
LIST_HEAD(clock_head, clock) clocks;
|
||||
LIST_HEAD(dst_clock_head, clock) dst_clocks;
|
||||
@@ -125,16 +137,16 @@ struct phc2sys_private {
|
||||
|
||||
static struct config *phc2sys_config;
|
||||
|
||||
-static int update_pmc(struct phc2sys_private *priv, int subscribe);
|
||||
+static int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
static int clock_handle_leap(struct phc2sys_private *priv,
|
||||
struct clock *clock,
|
||||
int64_t offset, uint64_t ts);
|
||||
-static int run_pmc_get_utc_offset(struct phc2sys_private *priv,
|
||||
+static int run_pmc_get_utc_offset(struct pmc_node *node,
|
||||
int timeout);
|
||||
-static void run_pmc_events(struct phc2sys_private *priv);
|
||||
+static void run_pmc_events(struct pmc_node *node);
|
||||
|
||||
static int normalize_state(int state);
|
||||
-static int run_pmc_port_properties(struct phc2sys_private *priv,
|
||||
+static int run_pmc_port_properties(struct pmc_node *node,
|
||||
int timeout, unsigned int port,
|
||||
int *state, int *tstamping, char *iface);
|
||||
|
||||
@@ -325,7 +337,7 @@ static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
|
||||
LIST_FOREACH(p, &priv->ports, list) {
|
||||
if (p->clock == clock) {
|
||||
- ret = run_pmc_port_properties(priv, 1000, p->number,
|
||||
+ ret = run_pmc_port_properties(&priv->node, 1000, p->number,
|
||||
&state, ×tamping,
|
||||
iface);
|
||||
if (ret > 0)
|
||||
@@ -660,7 +672,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
|
||||
if (src == CLOCK_INVALID) {
|
||||
/* The sync offset can't be applied with PPS alone. */
|
||||
- priv->sync_offset = 0;
|
||||
+ priv->node.sync_offset = 0;
|
||||
} else {
|
||||
enable_pps_output(priv->master->clkid);
|
||||
}
|
||||
@@ -691,7 +703,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
- if (update_pmc(priv, 0) < 0)
|
||||
+ if (update_pmc_node(&priv->node, 0) < 0)
|
||||
continue;
|
||||
update_clock(priv, clock, pps_offset, pps_ts, -1);
|
||||
}
|
||||
@@ -729,15 +741,15 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
|
||||
while (is_running()) {
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
|
||||
- if (update_pmc(priv, subscriptions) < 0)
|
||||
+ if (update_pmc_node(&priv->node, subscriptions) < 0)
|
||||
continue;
|
||||
|
||||
if (subscriptions) {
|
||||
- run_pmc_events(priv);
|
||||
+ run_pmc_events(&priv->node);
|
||||
if (priv->state_changed) {
|
||||
/* force getting offset, as it may have
|
||||
* changed after the port state change */
|
||||
- if (run_pmc_get_utc_offset(priv, 1000) <= 0) {
|
||||
+ if (run_pmc_get_utc_offset(&priv->node, 1000) <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
continue;
|
||||
}
|
||||
@@ -800,13 +812,12 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int check_clock_identity(struct phc2sys_private *priv,
|
||||
- struct ptp_message *msg)
|
||||
+static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
{
|
||||
- if (!priv->clock_identity_set)
|
||||
+ if (!node->clock_identity_set)
|
||||
return 1;
|
||||
- return cid_eq(&priv->clock_identity,
|
||||
- &msg->header.sourcePortIdentity.clockIdentity);
|
||||
+ return cid_eq(&node->clock_identity,
|
||||
+ &msg->header.sourcePortIdentity.clockIdentity);
|
||||
}
|
||||
|
||||
static int is_msg_mgt(struct ptp_message *msg)
|
||||
@@ -876,9 +887,13 @@ static int clock_compute_state(struct phc2sys_private *priv,
|
||||
return state;
|
||||
}
|
||||
|
||||
-static int recv_subscribed(struct phc2sys_private *priv,
|
||||
- struct ptp_message *msg, int excluded)
|
||||
+#define node_to_phc2sys(node) \
|
||||
+ container_of(node, struct phc2sys_private, node)
|
||||
+
|
||||
+static int phc2sys_recv_subscribed(struct pmc_node *node,
|
||||
+ struct ptp_message *msg, int excluded)
|
||||
{
|
||||
+ struct phc2sys_private *priv = node_to_phc2sys(node);
|
||||
int mgt_id, state;
|
||||
struct portDS *pds;
|
||||
struct port *port;
|
||||
@@ -913,29 +928,28 @@ static int recv_subscribed(struct phc2sys_private *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void send_subscription(struct phc2sys_private *priv)
|
||||
+static void send_subscription(struct pmc_node *node)
|
||||
{
|
||||
struct subscribe_events_np sen;
|
||||
|
||||
memset(&sen, 0, sizeof(sen));
|
||||
sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
- pmc_send_set_action(priv->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
+ pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
}
|
||||
|
||||
-static int init_pmc(struct config *cfg, struct phc2sys_private *priv)
|
||||
+static int init_pmc_node(struct config *cfg, struct pmc_node *node,
|
||||
+ const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
{
|
||||
- char uds_local[MAX_IFNAME_SIZE + 1];
|
||||
-
|
||||
- snprintf(uds_local, sizeof(uds_local), "/var/run/phc2sys.%d",
|
||||
- getpid());
|
||||
- priv->pmc = pmc_create(cfg, TRANS_UDS, uds_local, 0,
|
||||
+ node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
config_get_int(cfg, NULL, "domainNumber"),
|
||||
config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
|
||||
- if (!priv->pmc) {
|
||||
+ if (!node->pmc) {
|
||||
pr_err("failed to create pmc");
|
||||
return -1;
|
||||
}
|
||||
+ node->recv_subscribed = recv_subscribed;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -946,7 +960,7 @@ static int init_pmc(struct config *cfg, struct phc2sys_private *priv)
|
||||
* -1: error reported by the other side
|
||||
* -2: local error, fatal
|
||||
*/
|
||||
-static int run_pmc(struct phc2sys_private *priv, int timeout, int ds_id,
|
||||
+static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
struct ptp_message **msg)
|
||||
{
|
||||
#define N_FD 1
|
||||
@@ -954,9 +968,9 @@ static int run_pmc(struct phc2sys_private *priv, int timeout, int ds_id,
|
||||
int cnt, res;
|
||||
|
||||
while (1) {
|
||||
- pollfd[0].fd = pmc_get_transport_fd(priv->pmc);
|
||||
+ pollfd[0].fd = pmc_get_transport_fd(node->pmc);
|
||||
pollfd[0].events = POLLIN|POLLPRI;
|
||||
- if (!priv->pmc_ds_requested && ds_id >= 0)
|
||||
+ if (!node->pmc_ds_requested && ds_id >= 0)
|
||||
pollfd[0].events |= POLLOUT;
|
||||
|
||||
cnt = poll(pollfd, N_FD, timeout);
|
||||
@@ -966,7 +980,7 @@ static int run_pmc(struct phc2sys_private *priv, int timeout, int ds_id,
|
||||
}
|
||||
if (!cnt) {
|
||||
/* Request the data set again in the next run. */
|
||||
- priv->pmc_ds_requested = 0;
|
||||
+ node->pmc_ds_requested = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -975,24 +989,24 @@ static int run_pmc(struct phc2sys_private *priv, int timeout, int ds_id,
|
||||
!(pollfd[0].revents & (POLLIN|POLLPRI))) {
|
||||
switch (ds_id) {
|
||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
- send_subscription(priv);
|
||||
+ send_subscription(node);
|
||||
break;
|
||||
default:
|
||||
- pmc_send_get_action(priv->pmc, ds_id);
|
||||
+ pmc_send_get_action(node->pmc, ds_id);
|
||||
break;
|
||||
}
|
||||
- priv->pmc_ds_requested = 1;
|
||||
+ node->pmc_ds_requested = 1;
|
||||
}
|
||||
|
||||
if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
continue;
|
||||
|
||||
- *msg = pmc_recv(priv->pmc);
|
||||
+ *msg = pmc_recv(node->pmc);
|
||||
|
||||
if (!*msg)
|
||||
continue;
|
||||
|
||||
- if (!check_clock_identity(priv, *msg)) {
|
||||
+ if (!check_clock_identity(node, *msg)) {
|
||||
msg_put(*msg);
|
||||
*msg = NULL;
|
||||
continue;
|
||||
@@ -1000,29 +1014,29 @@ static int run_pmc(struct phc2sys_private *priv, int timeout, int ds_id,
|
||||
|
||||
res = is_msg_mgt(*msg);
|
||||
if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
- priv->pmc_ds_requested = 0;
|
||||
+ node->pmc_ds_requested = 0;
|
||||
return -1;
|
||||
}
|
||||
- if (res <= 0 || recv_subscribed(priv, *msg, ds_id) ||
|
||||
+ if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
get_mgt_id(*msg) != ds_id) {
|
||||
msg_put(*msg);
|
||||
*msg = NULL;
|
||||
continue;
|
||||
}
|
||||
- priv->pmc_ds_requested = 0;
|
||||
+ node->pmc_ds_requested = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
-static int run_pmc_wait_sync(struct phc2sys_private *priv, int timeout)
|
||||
+static int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
- int res;
|
||||
- void *data;
|
||||
Enumeration8 portState;
|
||||
+ void *data;
|
||||
+ int res;
|
||||
|
||||
while (1) {
|
||||
- res = run_pmc(priv, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
@@ -1036,47 +1050,47 @@ static int run_pmc_wait_sync(struct phc2sys_private *priv, int timeout)
|
||||
return 1;
|
||||
}
|
||||
/* try to get more data sets (for other ports) */
|
||||
- priv->pmc_ds_requested = 1;
|
||||
+ node->pmc_ds_requested = 1;
|
||||
}
|
||||
}
|
||||
|
||||
-static int run_pmc_get_utc_offset(struct phc2sys_private *priv, int timeout)
|
||||
+static int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
struct timePropertiesDS *tds;
|
||||
|
||||
- res = run_pmc(priv, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
if (tds->flags & PTP_TIMESCALE) {
|
||||
- priv->sync_offset = tds->currentUtcOffset;
|
||||
+ node->sync_offset = tds->currentUtcOffset;
|
||||
if (tds->flags & LEAP_61)
|
||||
- priv->leap = 1;
|
||||
+ node->leap = 1;
|
||||
else if (tds->flags & LEAP_59)
|
||||
- priv->leap = -1;
|
||||
+ node->leap = -1;
|
||||
else
|
||||
- priv->leap = 0;
|
||||
- priv->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
tds->flags & TIME_TRACEABLE;
|
||||
} else {
|
||||
- priv->sync_offset = 0;
|
||||
- priv->leap = 0;
|
||||
- priv->utc_offset_traceable = 0;
|
||||
+ node->sync_offset = 0;
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = 0;
|
||||
}
|
||||
msg_put(msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int run_pmc_get_number_ports(struct phc2sys_private *priv, int timeout)
|
||||
+static int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
struct defaultDS *dds;
|
||||
|
||||
- res = run_pmc(priv, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
@@ -1086,36 +1100,36 @@ static int run_pmc_get_number_ports(struct phc2sys_private *priv, int timeout)
|
||||
return res;
|
||||
}
|
||||
|
||||
-static int run_pmc_subscribe(struct phc2sys_private *priv, int timeout)
|
||||
+static int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
|
||||
- res = run_pmc(priv, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
msg_put(msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void run_pmc_events(struct phc2sys_private *priv)
|
||||
+static void run_pmc_events(struct pmc_node *node)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
|
||||
- run_pmc(priv, 0, -1, &msg);
|
||||
+ run_pmc(node, 0, -1, &msg);
|
||||
}
|
||||
|
||||
-static int run_pmc_port_properties(struct phc2sys_private *priv, int timeout,
|
||||
- unsigned int port,
|
||||
- int *state, int *tstamping, char *iface)
|
||||
+static int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res, len;
|
||||
struct port_properties_np *ppn;
|
||||
|
||||
- pmc_target_port(priv->pmc, port);
|
||||
+ pmc_target_port(node->pmc, port);
|
||||
while (1) {
|
||||
- res = run_pmc(priv, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
if (res <= 0)
|
||||
goto out;
|
||||
|
||||
@@ -1138,32 +1152,35 @@ static int run_pmc_port_properties(struct phc2sys_private *priv, int timeout,
|
||||
break;
|
||||
}
|
||||
out:
|
||||
- pmc_target_all(priv->pmc);
|
||||
+ pmc_target_all(node->pmc);
|
||||
return res;
|
||||
}
|
||||
|
||||
-static int run_pmc_clock_identity(struct phc2sys_private *priv, int timeout)
|
||||
+static int run_pmc_clock_identity(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
struct defaultDS *dds;
|
||||
int res;
|
||||
|
||||
- res = run_pmc(priv, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
+ res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
- memcpy(&priv->clock_identity, &dds->clockIdentity,
|
||||
+ memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
sizeof(struct ClockIdentity));
|
||||
- priv->clock_identity_set = 1;
|
||||
+ node->clock_identity_set = 1;
|
||||
msg_put(msg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void close_pmc(struct phc2sys_private *priv)
|
||||
+static void close_pmc_node(struct pmc_node *node)
|
||||
{
|
||||
- pmc_destroy(priv->pmc);
|
||||
- priv->pmc = NULL;
|
||||
+ if (!node->pmc)
|
||||
+ return;
|
||||
+
|
||||
+ pmc_destroy(node->pmc);
|
||||
+ node->pmc = NULL;
|
||||
}
|
||||
|
||||
static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
@@ -1178,7 +1195,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
while (1) {
|
||||
if (!is_running())
|
||||
return -1;
|
||||
- res = run_pmc_clock_identity(priv, 1000);
|
||||
+ res = run_pmc_clock_identity(&priv->node, 1000);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (res > 0)
|
||||
@@ -1187,20 +1204,20 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
pr_notice("Waiting for ptp4l...");
|
||||
}
|
||||
|
||||
- number_ports = run_pmc_get_number_ports(priv, 1000);
|
||||
+ number_ports = run_pmc_get_number_ports(&priv->node, 1000);
|
||||
if (number_ports <= 0) {
|
||||
pr_err("failed to get number of ports");
|
||||
return -1;
|
||||
}
|
||||
|
||||
- res = run_pmc_subscribe(priv, 1000);
|
||||
+ res = run_pmc_subscribe(&priv->node, 1000);
|
||||
if (res <= 0) {
|
||||
pr_err("failed to subscribe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i <= number_ports; i++) {
|
||||
- res = run_pmc_port_properties(priv, 1000, i, &state,
|
||||
+ res = run_pmc_port_properties(&priv->node, 1000, i, &state,
|
||||
×tamping, iface);
|
||||
if (res == -1) {
|
||||
/* port does not exist, ignore the port */
|
||||
@@ -1237,7 +1254,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* get initial offset */
|
||||
- if (run_pmc_get_utc_offset(priv, 1000) <= 0) {
|
||||
+ if (run_pmc_get_utc_offset(&priv->node, 1000) <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
return -1;
|
||||
}
|
||||
@@ -1245,7 +1262,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* Returns: -1 in case of error, 0 otherwise */
|
||||
-static int update_pmc(struct phc2sys_private *priv, int subscribe)
|
||||
+static int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
@@ -1256,13 +1273,13 @@ static int update_pmc(struct phc2sys_private *priv, int subscribe)
|
||||
}
|
||||
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
|
||||
- if (priv->pmc &&
|
||||
- !(ts > priv->pmc_last_update &&
|
||||
- ts - priv->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
+ if (node->pmc &&
|
||||
+ !(ts > node->pmc_last_update &&
|
||||
+ ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
if (subscribe)
|
||||
- run_pmc_subscribe(priv, 0);
|
||||
- if (run_pmc_get_utc_offset(priv, 0) > 0)
|
||||
- priv->pmc_last_update = ts;
|
||||
+ run_pmc_subscribe(node, 0);
|
||||
+ if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
+ node->pmc_last_update = ts;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1272,9 +1289,9 @@ static int update_pmc(struct phc2sys_private *priv, int subscribe)
|
||||
static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
int64_t offset, uint64_t ts)
|
||||
{
|
||||
- int clock_leap, node_leap = priv->leap;
|
||||
+ int clock_leap, node_leap = priv->node.leap;
|
||||
|
||||
- clock->sync_offset = priv->sync_offset;
|
||||
+ clock->sync_offset = priv->node.sync_offset;
|
||||
|
||||
if ((node_leap || clock->leap_set) &&
|
||||
clock->is_utc != priv->master->is_utc) {
|
||||
@@ -1315,7 +1332,7 @@ static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
}
|
||||
}
|
||||
|
||||
- if (priv->utc_offset_traceable &&
|
||||
+ if (priv->node.utc_offset_traceable &&
|
||||
clock->utc_offset_set != clock->sync_offset) {
|
||||
if (clock->clkid == CLOCK_REALTIME)
|
||||
sysclk_set_tai_offset(clock->sync_offset);
|
||||
@@ -1370,6 +1387,7 @@ static void usage(char *progname)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *config = NULL, *dst_name = NULL, *progname, *src_name = NULL;
|
||||
+ char uds_local[MAX_IFNAME_SIZE + 1];
|
||||
struct clock *src, *dst;
|
||||
struct config *cfg;
|
||||
struct option *opts;
|
||||
@@ -1478,7 +1496,7 @@ int main(int argc, char *argv[])
|
||||
goto end;
|
||||
break;
|
||||
case 'O':
|
||||
- if (get_arg_val_i(c, optarg, &priv.sync_offset,
|
||||
+ if (get_arg_val_i(c, optarg, &priv.node.sync_offset,
|
||||
INT_MIN, INT_MAX))
|
||||
goto end;
|
||||
priv.forced_sync_offset = -1;
|
||||
@@ -1605,8 +1623,12 @@ int main(int argc, char *argv[])
|
||||
priv.sanity_freq_limit = config_get_int(cfg, NULL, "sanity_freq_limit");
|
||||
priv.default_sync = config_get_int(cfg, NULL, "default_sync");
|
||||
|
||||
+ snprintf(uds_local, sizeof(uds_local), "/var/run/phc2sys.%d",
|
||||
+ getpid());
|
||||
+
|
||||
if (autocfg) {
|
||||
- if (init_pmc(cfg, &priv))
|
||||
+ if (init_pmc_node(cfg, &priv.node, uds_local,
|
||||
+ phc2sys_recv_subscribed))
|
||||
goto end;
|
||||
if (auto_init_ports(&priv, rt) < 0)
|
||||
goto end;
|
||||
@@ -1643,11 +1665,12 @@ int main(int argc, char *argv[])
|
||||
r = -1;
|
||||
|
||||
if (wait_sync) {
|
||||
- if (init_pmc(cfg, &priv))
|
||||
+ if (init_pmc_node(cfg, &priv.node, uds_local,
|
||||
+ phc2sys_recv_subscribed))
|
||||
goto end;
|
||||
|
||||
while (is_running()) {
|
||||
- r = run_pmc_wait_sync(&priv, 1000);
|
||||
+ r = run_pmc_wait_sync(&priv.node, 1000);
|
||||
if (r < 0)
|
||||
goto end;
|
||||
if (r > 0)
|
||||
@@ -1657,7 +1680,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!priv.forced_sync_offset) {
|
||||
- r = run_pmc_get_utc_offset(&priv, 1000);
|
||||
+ r = run_pmc_get_utc_offset(&priv.node, 1000);
|
||||
if (r <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
goto end;
|
||||
@@ -1667,7 +1690,7 @@ int main(int argc, char *argv[])
|
||||
if (priv.forced_sync_offset ||
|
||||
(src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
src->clkid == CLOCK_INVALID)
|
||||
- close_pmc(&priv);
|
||||
+ close_pmc_node(&priv.node);
|
||||
}
|
||||
|
||||
if (pps_fd >= 0) {
|
||||
@@ -1680,8 +1703,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
end:
|
||||
- if (priv.pmc)
|
||||
- close_pmc(&priv);
|
||||
+ close_pmc_node(&priv.node);
|
||||
clock_cleanup(&priv);
|
||||
port_cleanup(&priv);
|
||||
config_destroy(cfg);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,143 @@
|
||||
From 87d8e7281e3e66813d0c669bea0b5335a8cbb6b6 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 13:59:48 -0300
|
||||
Subject: [PATCH 12/47] phc2sys: make PMC functions non-static
|
||||
|
||||
In preparation of a trivial movement of code to pmc_common.c, remove the
|
||||
"static" keyword from the functions that will end up there, since they
|
||||
will be still called from phc2sys.c for now.
|
||||
|
||||
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 2ccbb14450e1e96168a2604c0e8c96ae5a6a5bf0 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 40 +++++++++++++++++++---------------------
|
||||
1 file changed, 19 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 86b9822..d5b8e71 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -137,18 +137,17 @@ struct phc2sys_private {
|
||||
|
||||
static struct config *phc2sys_config;
|
||||
|
||||
-static int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
static int clock_handle_leap(struct phc2sys_private *priv,
|
||||
struct clock *clock,
|
||||
int64_t offset, uint64_t ts);
|
||||
-static int run_pmc_get_utc_offset(struct pmc_node *node,
|
||||
- int timeout);
|
||||
-static void run_pmc_events(struct pmc_node *node);
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
+void run_pmc_events(struct pmc_node *node);
|
||||
|
||||
static int normalize_state(int state);
|
||||
-static int run_pmc_port_properties(struct pmc_node *node,
|
||||
- int timeout, unsigned int port,
|
||||
- int *state, int *tstamping, char *iface);
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface);
|
||||
|
||||
static struct servo *servo_add(struct phc2sys_private *priv,
|
||||
struct clock *clock)
|
||||
@@ -838,13 +837,13 @@ static int is_msg_mgt(struct ptp_message *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int get_mgt_id(struct ptp_message *msg)
|
||||
+int get_mgt_id(struct ptp_message *msg)
|
||||
{
|
||||
struct management_tlv *mgt = (struct management_tlv *) msg->management.suffix;
|
||||
return mgt->id;
|
||||
}
|
||||
|
||||
-static void *get_mgt_data(struct ptp_message *msg)
|
||||
+void *get_mgt_data(struct ptp_message *msg)
|
||||
{
|
||||
struct management_tlv *mgt = (struct management_tlv *) msg->management.suffix;
|
||||
return mgt->data;
|
||||
@@ -938,9 +937,8 @@ static void send_subscription(struct pmc_node *node)
|
||||
pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
}
|
||||
|
||||
-static int init_pmc_node(struct config *cfg, struct pmc_node *node,
|
||||
- const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
{
|
||||
node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
config_get_int(cfg, NULL, "domainNumber"),
|
||||
@@ -1054,7 +1052,7 @@ static int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
}
|
||||
}
|
||||
|
||||
-static int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -1084,7 +1082,7 @@ static int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -1100,7 +1098,7 @@ static int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
return res;
|
||||
}
|
||||
|
||||
-static int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -1112,16 +1110,16 @@ static int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void run_pmc_events(struct pmc_node *node)
|
||||
+void run_pmc_events(struct pmc_node *node)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
|
||||
run_pmc(node, 0, -1, &msg);
|
||||
}
|
||||
|
||||
-static int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface)
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res, len;
|
||||
@@ -1174,7 +1172,7 @@ static int run_pmc_clock_identity(struct pmc_node *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void close_pmc_node(struct pmc_node *node)
|
||||
+void close_pmc_node(struct pmc_node *node)
|
||||
{
|
||||
if (!node->pmc)
|
||||
return;
|
||||
@@ -1262,7 +1260,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* Returns: -1 in case of error, 0 otherwise */
|
||||
-static int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,841 @@
|
||||
From ba9c2ea0e1f7a96093bca1147d4745a7d0ce17b6 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:34:19 -0300
|
||||
Subject: [PATCH 13/47] phc2sys: break out pmc code into pmc_common.c
|
||||
|
||||
The code through which phc2sys sends various PTP management messages to
|
||||
ptp4l via pmc can be reused.
|
||||
|
||||
This patch is a trivial movement of that code to a separate translation
|
||||
module, outside of phc2sys. This makes it available to other programs
|
||||
that want to subscribe to port state change events too, such as ts2phc.
|
||||
|
||||
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
[commit abc75482332752b630b023178ccdf636f5fe7de7 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 354 ---------------------------------------------------
|
||||
pmc_common.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
pmc_common.h | 35 +++++
|
||||
3 files changed, 372 insertions(+), 354 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index d5b8e71..9184db6 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -63,12 +63,6 @@
|
||||
#define NS_PER_SEC 1000000000LL
|
||||
|
||||
#define PHC_PPS_OFFSET_LIMIT 10000000
|
||||
-#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
|
||||
-#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
|
||||
-/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
|
||||
- * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
|
||||
- * renewed.
|
||||
- */
|
||||
|
||||
struct clock {
|
||||
LIST_ENTRY(clock) list;
|
||||
@@ -100,24 +94,6 @@ struct port {
|
||||
struct clock *clock;
|
||||
};
|
||||
|
||||
-struct pmc_node;
|
||||
-
|
||||
-typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
- struct ptp_message *msg,
|
||||
- int excluded);
|
||||
-
|
||||
-struct pmc_node {
|
||||
- struct pmc *pmc;
|
||||
- int pmc_ds_requested;
|
||||
- uint64_t pmc_last_update;
|
||||
- int sync_offset;
|
||||
- int leap;
|
||||
- int utc_offset_traceable;
|
||||
- int clock_identity_set;
|
||||
- struct ClockIdentity clock_identity;
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
-};
|
||||
-
|
||||
struct phc2sys_private {
|
||||
unsigned int stats_max_count;
|
||||
int sanity_freq_limit;
|
||||
@@ -137,17 +113,11 @@ struct phc2sys_private {
|
||||
|
||||
static struct config *phc2sys_config;
|
||||
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
static int clock_handle_leap(struct phc2sys_private *priv,
|
||||
struct clock *clock,
|
||||
int64_t offset, uint64_t ts);
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
-void run_pmc_events(struct pmc_node *node);
|
||||
|
||||
static int normalize_state(int state);
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface);
|
||||
|
||||
static struct servo *servo_add(struct phc2sys_private *priv,
|
||||
struct clock *clock)
|
||||
@@ -811,52 +781,6 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
-{
|
||||
- if (!node->clock_identity_set)
|
||||
- return 1;
|
||||
- return cid_eq(&node->clock_identity,
|
||||
- &msg->header.sourcePortIdentity.clockIdentity);
|
||||
-}
|
||||
-
|
||||
-static int is_msg_mgt(struct ptp_message *msg)
|
||||
-{
|
||||
- struct TLV *tlv;
|
||||
-
|
||||
- if (msg_type(msg) != MANAGEMENT)
|
||||
- return 0;
|
||||
- if (management_action(msg) != RESPONSE)
|
||||
- return 0;
|
||||
- if (msg_tlv_count(msg) != 1)
|
||||
- return 0;
|
||||
- tlv = (struct TLV *) msg->management.suffix;
|
||||
- if (tlv->type == TLV_MANAGEMENT)
|
||||
- return 1;
|
||||
- if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
|
||||
- return -1;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int get_mgt_id(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->id;
|
||||
-}
|
||||
-
|
||||
-void *get_mgt_data(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->data;
|
||||
-}
|
||||
-
|
||||
-static int get_mgt_err_id(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_error_status *mgt;
|
||||
-
|
||||
- mgt = (struct management_error_status *)msg->management.suffix;
|
||||
- return mgt->id;
|
||||
-}
|
||||
-
|
||||
static int normalize_state(int state)
|
||||
{
|
||||
if (state != PS_MASTER && state != PS_SLAVE &&
|
||||
@@ -927,260 +851,6 @@ static int phc2sys_recv_subscribed(struct pmc_node *node,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void send_subscription(struct pmc_node *node)
|
||||
-{
|
||||
- struct subscribe_events_np sen;
|
||||
-
|
||||
- memset(&sen, 0, sizeof(sen));
|
||||
- sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
- sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
- pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
-}
|
||||
-
|
||||
-int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
-{
|
||||
- node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
- config_get_int(cfg, NULL, "domainNumber"),
|
||||
- config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
|
||||
- if (!node->pmc) {
|
||||
- pr_err("failed to create pmc");
|
||||
- return -1;
|
||||
- }
|
||||
- node->recv_subscribed = recv_subscribed;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-/* Return values:
|
||||
- * 1: success
|
||||
- * 0: timeout
|
||||
- * -1: error reported by the other side
|
||||
- * -2: local error, fatal
|
||||
- */
|
||||
-static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
- struct ptp_message **msg)
|
||||
-{
|
||||
-#define N_FD 1
|
||||
- struct pollfd pollfd[N_FD];
|
||||
- int cnt, res;
|
||||
-
|
||||
- while (1) {
|
||||
- pollfd[0].fd = pmc_get_transport_fd(node->pmc);
|
||||
- pollfd[0].events = POLLIN|POLLPRI;
|
||||
- if (!node->pmc_ds_requested && ds_id >= 0)
|
||||
- pollfd[0].events |= POLLOUT;
|
||||
-
|
||||
- cnt = poll(pollfd, N_FD, timeout);
|
||||
- if (cnt < 0) {
|
||||
- pr_err("poll failed");
|
||||
- return -2;
|
||||
- }
|
||||
- if (!cnt) {
|
||||
- /* Request the data set again in the next run. */
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- /* Send a new request if there are no pending messages. */
|
||||
- if ((pollfd[0].revents & POLLOUT) &&
|
||||
- !(pollfd[0].revents & (POLLIN|POLLPRI))) {
|
||||
- switch (ds_id) {
|
||||
- case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
- send_subscription(node);
|
||||
- break;
|
||||
- default:
|
||||
- pmc_send_get_action(node->pmc, ds_id);
|
||||
- break;
|
||||
- }
|
||||
- node->pmc_ds_requested = 1;
|
||||
- }
|
||||
-
|
||||
- if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
- continue;
|
||||
-
|
||||
- *msg = pmc_recv(node->pmc);
|
||||
-
|
||||
- if (!*msg)
|
||||
- continue;
|
||||
-
|
||||
- if (!check_clock_identity(node, *msg)) {
|
||||
- msg_put(*msg);
|
||||
- *msg = NULL;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- res = is_msg_mgt(*msg);
|
||||
- if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return -1;
|
||||
- }
|
||||
- if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
- get_mgt_id(*msg) != ds_id) {
|
||||
- msg_put(*msg);
|
||||
- *msg = NULL;
|
||||
- continue;
|
||||
- }
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return 1;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- Enumeration8 portState;
|
||||
- void *data;
|
||||
- int res;
|
||||
-
|
||||
- while (1) {
|
||||
- res = run_pmc(node, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- data = get_mgt_data(msg);
|
||||
- portState = ((struct portDS *)data)->portState;
|
||||
- msg_put(msg);
|
||||
-
|
||||
- switch (portState) {
|
||||
- case PS_MASTER:
|
||||
- case PS_SLAVE:
|
||||
- return 1;
|
||||
- }
|
||||
- /* try to get more data sets (for other ports) */
|
||||
- node->pmc_ds_requested = 1;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct timePropertiesDS *tds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
- if (tds->flags & PTP_TIMESCALE) {
|
||||
- node->sync_offset = tds->currentUtcOffset;
|
||||
- if (tds->flags & LEAP_61)
|
||||
- node->leap = 1;
|
||||
- else if (tds->flags & LEAP_59)
|
||||
- node->leap = -1;
|
||||
- else
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
- tds->flags & TIME_TRACEABLE;
|
||||
- } else {
|
||||
- node->sync_offset = 0;
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = 0;
|
||||
- }
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct defaultDS *dds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
- res = dds->numberPorts;
|
||||
- msg_put(msg);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
-int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-void run_pmc_events(struct pmc_node *node)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
-
|
||||
- run_pmc(node, 0, -1, &msg);
|
||||
-}
|
||||
-
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res, len;
|
||||
- struct port_properties_np *ppn;
|
||||
-
|
||||
- pmc_target_port(node->pmc, port);
|
||||
- while (1) {
|
||||
- res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- goto out;
|
||||
-
|
||||
- ppn = get_mgt_data(msg);
|
||||
- if (ppn->portIdentity.portNumber != port) {
|
||||
- msg_put(msg);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- *state = ppn->port_state;
|
||||
- *tstamping = ppn->timestamping;
|
||||
- len = ppn->interface.length;
|
||||
- if (len > IFNAMSIZ - 1)
|
||||
- len = IFNAMSIZ - 1;
|
||||
- memcpy(iface, ppn->interface.text, len);
|
||||
- iface[len] = '\0';
|
||||
-
|
||||
- msg_put(msg);
|
||||
- res = 1;
|
||||
- break;
|
||||
- }
|
||||
-out:
|
||||
- pmc_target_all(node->pmc);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
-static int run_pmc_clock_identity(struct pmc_node *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 *)get_mgt_data(msg);
|
||||
- memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
- sizeof(struct ClockIdentity));
|
||||
- node->clock_identity_set = 1;
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-void close_pmc_node(struct pmc_node *node)
|
||||
-{
|
||||
- if (!node->pmc)
|
||||
- return;
|
||||
-
|
||||
- pmc_destroy(node->pmc);
|
||||
- node->pmc = NULL;
|
||||
-}
|
||||
-
|
||||
static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
{
|
||||
struct port *port;
|
||||
@@ -1259,30 +929,6 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Returns: -1 in case of error, 0 otherwise */
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
-{
|
||||
- struct timespec tp;
|
||||
- uint64_t ts;
|
||||
-
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
- pr_err("failed to read clock: %m");
|
||||
- return -1;
|
||||
- }
|
||||
- ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
-
|
||||
- if (node->pmc &&
|
||||
- !(ts > node->pmc_last_update &&
|
||||
- ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
- if (subscribe)
|
||||
- run_pmc_subscribe(node, 0);
|
||||
- if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
- node->pmc_last_update = ts;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
/* Returns: non-zero to skip clock update */
|
||||
static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
int64_t offset, uint64_t ts)
|
||||
diff --git a/pmc_common.c b/pmc_common.c
|
||||
index f07f6f6..c9cdf18 100644
|
||||
--- a/pmc_common.c
|
||||
+++ b/pmc_common.c
|
||||
@@ -18,6 +18,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <errno.h>
|
||||
+#include <net/if.h>
|
||||
+#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
@@ -56,6 +58,13 @@
|
||||
/* Includes one extra byte to make length even. */
|
||||
#define EMPTY_PTP_TEXT 2
|
||||
|
||||
+#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
|
||||
+#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
|
||||
+/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
|
||||
+ * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
|
||||
+ * renewed.
|
||||
+ */
|
||||
+
|
||||
static void do_get_action(struct pmc *pmc, int action, int index, char *str);
|
||||
static void do_set_action(struct pmc *pmc, int action, int index, char *str);
|
||||
static void not_supported(struct pmc *pmc, int action, int index, char *str);
|
||||
@@ -711,3 +720,331 @@ int pmc_do_command(struct pmc *pmc, char *str)
|
||||
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+static void send_subscription(struct pmc_node *node)
|
||||
+{
|
||||
+ struct subscribe_events_np sen;
|
||||
+
|
||||
+ memset(&sen, 0, sizeof(sen));
|
||||
+ sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
+ sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
+ pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
+}
|
||||
+
|
||||
+static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
+{
|
||||
+ if (!node->clock_identity_set)
|
||||
+ return 1;
|
||||
+ return cid_eq(&node->clock_identity,
|
||||
+ &msg->header.sourcePortIdentity.clockIdentity);
|
||||
+}
|
||||
+
|
||||
+static int is_msg_mgt(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct TLV *tlv;
|
||||
+
|
||||
+ if (msg_type(msg) != MANAGEMENT)
|
||||
+ return 0;
|
||||
+ if (management_action(msg) != RESPONSE)
|
||||
+ return 0;
|
||||
+ if (msg_tlv_count(msg) != 1)
|
||||
+ return 0;
|
||||
+ tlv = (struct TLV *) msg->management.suffix;
|
||||
+ if (tlv->type == TLV_MANAGEMENT)
|
||||
+ return 1;
|
||||
+ if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int get_mgt_id(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+
|
||||
+ mgt = (struct management_tlv *) msg->management.suffix;
|
||||
+ return mgt->id;
|
||||
+}
|
||||
+
|
||||
+void *get_mgt_data(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+
|
||||
+ mgt = (struct management_tlv *) msg->management.suffix;
|
||||
+ return mgt->data;
|
||||
+}
|
||||
+
|
||||
+static int get_mgt_err_id(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_error_status *mgt;
|
||||
+
|
||||
+ mgt = (struct management_error_status *)msg->management.suffix;
|
||||
+ return mgt->id;
|
||||
+}
|
||||
+
|
||||
+/* Return values:
|
||||
+ * 1: success
|
||||
+ * 0: timeout
|
||||
+ * -1: error reported by the other side
|
||||
+ * -2: local error, fatal
|
||||
+ */
|
||||
+static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
+ struct ptp_message **msg)
|
||||
+{
|
||||
+#define N_FD 1
|
||||
+ struct pollfd pollfd[N_FD];
|
||||
+ int cnt, res;
|
||||
+
|
||||
+ while (1) {
|
||||
+ pollfd[0].fd = pmc_get_transport_fd(node->pmc);
|
||||
+ pollfd[0].events = POLLIN|POLLPRI;
|
||||
+ if (!node->pmc_ds_requested && ds_id >= 0)
|
||||
+ pollfd[0].events |= POLLOUT;
|
||||
+
|
||||
+ cnt = poll(pollfd, N_FD, timeout);
|
||||
+ if (cnt < 0) {
|
||||
+ pr_err("poll failed");
|
||||
+ return -2;
|
||||
+ }
|
||||
+ if (!cnt) {
|
||||
+ /* Request the data set again in the next run. */
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Send a new request if there are no pending messages. */
|
||||
+ if ((pollfd[0].revents & POLLOUT) &&
|
||||
+ !(pollfd[0].revents & (POLLIN|POLLPRI))) {
|
||||
+ switch (ds_id) {
|
||||
+ case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
+ send_subscription(node);
|
||||
+ break;
|
||||
+ default:
|
||||
+ pmc_send_get_action(node->pmc, ds_id);
|
||||
+ break;
|
||||
+ }
|
||||
+ node->pmc_ds_requested = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
+ continue;
|
||||
+
|
||||
+ *msg = pmc_recv(node->pmc);
|
||||
+
|
||||
+ if (!*msg)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!check_clock_identity(node, *msg)) {
|
||||
+ msg_put(*msg);
|
||||
+ *msg = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ res = is_msg_mgt(*msg);
|
||||
+ if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
+ get_mgt_id(*msg) != ds_id) {
|
||||
+ msg_put(*msg);
|
||||
+ *msg = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ Enumeration8 portState;
|
||||
+ void *data;
|
||||
+ int res;
|
||||
+
|
||||
+ while (1) {
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ data = get_mgt_data(msg);
|
||||
+ portState = ((struct portDS *)data)->portState;
|
||||
+ msg_put(msg);
|
||||
+
|
||||
+ switch (portState) {
|
||||
+ case PS_MASTER:
|
||||
+ case PS_SLAVE:
|
||||
+ return 1;
|
||||
+ }
|
||||
+ /* try to get more data sets (for other ports) */
|
||||
+ node->pmc_ds_requested = 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+ struct timePropertiesDS *tds;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
+ if (tds->flags & PTP_TIMESCALE) {
|
||||
+ node->sync_offset = tds->currentUtcOffset;
|
||||
+ if (tds->flags & LEAP_61)
|
||||
+ node->leap = 1;
|
||||
+ else if (tds->flags & LEAP_59)
|
||||
+ node->leap = -1;
|
||||
+ else
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
+ tds->flags & TIME_TRACEABLE;
|
||||
+ } else {
|
||||
+ node->sync_offset = 0;
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = 0;
|
||||
+ }
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+ struct defaultDS *dds;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
+ res = dds->numberPorts;
|
||||
+ msg_put(msg);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+void run_pmc_events(struct pmc_node *node)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+
|
||||
+ run_pmc(node, 0, -1, &msg);
|
||||
+}
|
||||
+
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res, len;
|
||||
+ struct port_properties_np *ppn;
|
||||
+
|
||||
+ pmc_target_port(node->pmc, port);
|
||||
+ while (1) {
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
+ if (res <= 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ ppn = get_mgt_data(msg);
|
||||
+ if (ppn->portIdentity.portNumber != port) {
|
||||
+ msg_put(msg);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ *state = ppn->port_state;
|
||||
+ *tstamping = ppn->timestamping;
|
||||
+ len = ppn->interface.length;
|
||||
+ if (len > IFNAMSIZ - 1)
|
||||
+ len = IFNAMSIZ - 1;
|
||||
+ memcpy(iface, ppn->interface.text, len);
|
||||
+ iface[len] = '\0';
|
||||
+
|
||||
+ msg_put(msg);
|
||||
+ res = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+out:
|
||||
+ pmc_target_all(node->pmc);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_clock_identity(struct pmc_node *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 *)get_mgt_data(msg);
|
||||
+ memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
+ sizeof(struct ClockIdentity));
|
||||
+ node->clock_identity_set = 1;
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/* Returns: -1 in case of error, 0 otherwise */
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
+{
|
||||
+ struct timespec tp;
|
||||
+ uint64_t ts;
|
||||
+
|
||||
+ if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
+ pr_err("failed to read clock: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
+
|
||||
+ if (node->pmc &&
|
||||
+ !(ts > node->pmc_last_update &&
|
||||
+ ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
+ if (subscribe)
|
||||
+ run_pmc_subscribe(node, 0);
|
||||
+ if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
+ node->pmc_last_update = ts;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
+{
|
||||
+ node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
+ config_get_int(cfg, NULL, "domainNumber"),
|
||||
+ config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
|
||||
+ if (!node->pmc) {
|
||||
+ pr_err("failed to create pmc");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ node->recv_subscribed = recv_subscribed;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void close_pmc_node(struct pmc_node *node)
|
||||
+{
|
||||
+ if (!node->pmc)
|
||||
+ return;
|
||||
+
|
||||
+ pmc_destroy(node->pmc);
|
||||
+ node->pmc = NULL;
|
||||
+}
|
||||
diff --git a/pmc_common.h b/pmc_common.h
|
||||
index 9fa72de..476ccea 100644
|
||||
--- a/pmc_common.h
|
||||
+++ b/pmc_common.h
|
||||
@@ -22,6 +22,7 @@
|
||||
#define HAVE_PMC_COMMON_H
|
||||
|
||||
#include "config.h"
|
||||
+#include "fsm.h"
|
||||
#include "msg.h"
|
||||
#include "transport.h"
|
||||
|
||||
@@ -49,4 +50,38 @@ void pmc_target_all(struct pmc *pmc);
|
||||
const char *pmc_action_string(int action);
|
||||
int pmc_do_command(struct pmc *pmc, char *str);
|
||||
|
||||
+struct pmc_node;
|
||||
+
|
||||
+typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
+ struct ptp_message *msg,
|
||||
+ int excluded);
|
||||
+
|
||||
+struct pmc_node {
|
||||
+ struct pmc *pmc;
|
||||
+ int pmc_ds_requested;
|
||||
+ uint64_t pmc_last_update;
|
||||
+ int sync_offset;
|
||||
+ int leap;
|
||||
+ int utc_offset_traceable;
|
||||
+ int clock_identity_set;
|
||||
+ struct ClockIdentity clock_identity;
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
+};
|
||||
+
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed);
|
||||
+void close_pmc_node(struct pmc_node *node);
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
+int run_pmc_subscribe(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_clock_identity(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_wait_sync(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_get_number_ports(struct pmc_node *node, int timeout);
|
||||
+void run_pmc_events(struct pmc_node *node);
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface);
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
+int get_mgt_id(struct ptp_message *msg);
|
||||
+void *get_mgt_data(struct ptp_message *msg);
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,913 @@
|
||||
From c00e75286b2ad882cf8e89549ea58e438c877f95 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:40:59 -0300
|
||||
Subject: [PATCH 14/47] Introduce the PMC agent module.
|
||||
|
||||
The logic for placing PTP management queries migrated out of phc2sys into
|
||||
pmc_common in order to be shared with other programs in the future. This
|
||||
logic uses pmc_common rather than extending it, and so it should live in
|
||||
its own module stacked on top of pmc_common.
|
||||
|
||||
This patch moves the code into its own file verbatim without making any
|
||||
other changes.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit f266740e1a8aacc03f97205ae14fc43c59081433 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
makefile | 6 +-
|
||||
phc2sys.c | 2 +-
|
||||
pmc_agent.c | 361 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
pmc_agent.h | 62 +++++++++
|
||||
pmc_common.c | 338 -----------------------------------------------
|
||||
pmc_common.h | 34 -----
|
||||
6 files changed, 427 insertions(+), 376 deletions(-)
|
||||
create mode 100644 pmc_agent.c
|
||||
create mode 100644 pmc_agent.h
|
||||
|
||||
diff --git a/makefile b/makefile
|
||||
index 27c4d78..33e7ca0 100644
|
||||
--- a/makefile
|
||||
+++ b/makefile
|
||||
@@ -34,8 +34,8 @@ OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \
|
||||
sk.o stats.o tc.o $(TRANSP) telecom.o tlv.o tsproc.o unicast_client.o \
|
||||
unicast_fsm.o unicast_service.o util.o version.o
|
||||
|
||||
-OBJECTS = $(OBJ) hwstamp_ctl.o nsm.o phc2sys.o phc_ctl.o pmc.o pmc_common.o \
|
||||
- sysoff.o timemaster.o $(TS2PHC)
|
||||
+OBJECTS = $(OBJ) hwstamp_ctl.o nsm.o phc2sys.o phc_ctl.o pmc.o pmc_agent.o \
|
||||
+ pmc_common.o sysoff.o timemaster.o $(TS2PHC)
|
||||
SRC = $(OBJECTS:.o=.c)
|
||||
DEPEND = $(OBJECTS:.o=.d)
|
||||
srcdir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
@@ -59,7 +59,7 @@ pmc: config.o hash.o interface.o msg.o phc.o pmc.o pmc_common.o print.o sk.o \
|
||||
tlv.o $(TRANSP) util.o version.o
|
||||
|
||||
phc2sys: clockadj.o clockcheck.o config.o hash.o interface.o msg.o \
|
||||
- phc.o phc2sys.o pmc_common.o print.o $(SERVOS) sk.o stats.o \
|
||||
+ phc.o phc2sys.o pmc_agent.o pmc_common.o print.o $(SERVOS) sk.o stats.o \
|
||||
sysoff.o tlv.o $(TRANSP) util.o version.o
|
||||
|
||||
hwstamp_ctl: hwstamp_ctl.o version.o
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 9184db6..648ba61 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -47,7 +47,7 @@
|
||||
#include "ntpshm.h"
|
||||
#include "phc.h"
|
||||
#include "pi.h"
|
||||
-#include "pmc_common.h"
|
||||
+#include "pmc_agent.h"
|
||||
#include "print.h"
|
||||
#include "servo.h"
|
||||
#include "sk.h"
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
new file mode 100644
|
||||
index 0000000..774e94d
|
||||
--- /dev/null
|
||||
+++ b/pmc_agent.c
|
||||
@@ -0,0 +1,361 @@
|
||||
+/**
|
||||
+ * @file pmc_agent.c
|
||||
+ * @note Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
|
||||
+ * @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License along
|
||||
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ */
|
||||
+#include <net/if.h>
|
||||
+#include <poll.h>
|
||||
+
|
||||
+#include "notification.h"
|
||||
+#include "pmc_agent.h"
|
||||
+#include "print.h"
|
||||
+#include "util.h"
|
||||
+
|
||||
+#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
|
||||
+#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
|
||||
+/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
|
||||
+ * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
|
||||
+ * renewed.
|
||||
+ */
|
||||
+
|
||||
+static void send_subscription(struct pmc_node *node)
|
||||
+{
|
||||
+ struct subscribe_events_np sen;
|
||||
+
|
||||
+ memset(&sen, 0, sizeof(sen));
|
||||
+ sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
+ sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
+ pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
+}
|
||||
+
|
||||
+static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
+{
|
||||
+ if (!node->clock_identity_set)
|
||||
+ return 1;
|
||||
+ return cid_eq(&node->clock_identity,
|
||||
+ &msg->header.sourcePortIdentity.clockIdentity);
|
||||
+}
|
||||
+
|
||||
+static int is_msg_mgt(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct TLV *tlv;
|
||||
+
|
||||
+ if (msg_type(msg) != MANAGEMENT)
|
||||
+ return 0;
|
||||
+ if (management_action(msg) != RESPONSE)
|
||||
+ return 0;
|
||||
+ if (msg_tlv_count(msg) != 1)
|
||||
+ return 0;
|
||||
+ tlv = (struct TLV *) msg->management.suffix;
|
||||
+ if (tlv->type == TLV_MANAGEMENT)
|
||||
+ return 1;
|
||||
+ if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
|
||||
+ return -1;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int get_mgt_id(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+
|
||||
+ mgt = (struct management_tlv *) msg->management.suffix;
|
||||
+ return mgt->id;
|
||||
+}
|
||||
+
|
||||
+void *get_mgt_data(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+
|
||||
+ mgt = (struct management_tlv *) msg->management.suffix;
|
||||
+ return mgt->data;
|
||||
+}
|
||||
+
|
||||
+static int get_mgt_err_id(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_error_status *mgt;
|
||||
+
|
||||
+ mgt = (struct management_error_status *)msg->management.suffix;
|
||||
+ return mgt->id;
|
||||
+}
|
||||
+
|
||||
+/* Return values:
|
||||
+ * 1: success
|
||||
+ * 0: timeout
|
||||
+ * -1: error reported by the other side
|
||||
+ * -2: local error, fatal
|
||||
+ */
|
||||
+static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
+ struct ptp_message **msg)
|
||||
+{
|
||||
+#define N_FD 1
|
||||
+ struct pollfd pollfd[N_FD];
|
||||
+ int cnt, res;
|
||||
+
|
||||
+ while (1) {
|
||||
+ pollfd[0].fd = pmc_get_transport_fd(node->pmc);
|
||||
+ pollfd[0].events = POLLIN|POLLPRI;
|
||||
+ if (!node->pmc_ds_requested && ds_id >= 0)
|
||||
+ pollfd[0].events |= POLLOUT;
|
||||
+
|
||||
+ cnt = poll(pollfd, N_FD, timeout);
|
||||
+ if (cnt < 0) {
|
||||
+ pr_err("poll failed");
|
||||
+ return -2;
|
||||
+ }
|
||||
+ if (!cnt) {
|
||||
+ /* Request the data set again in the next run. */
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Send a new request if there are no pending messages. */
|
||||
+ if ((pollfd[0].revents & POLLOUT) &&
|
||||
+ !(pollfd[0].revents & (POLLIN|POLLPRI))) {
|
||||
+ switch (ds_id) {
|
||||
+ case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
+ send_subscription(node);
|
||||
+ break;
|
||||
+ default:
|
||||
+ pmc_send_get_action(node->pmc, ds_id);
|
||||
+ break;
|
||||
+ }
|
||||
+ node->pmc_ds_requested = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
+ continue;
|
||||
+
|
||||
+ *msg = pmc_recv(node->pmc);
|
||||
+
|
||||
+ if (!*msg)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!check_clock_identity(node, *msg)) {
|
||||
+ msg_put(*msg);
|
||||
+ *msg = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ res = is_msg_mgt(*msg);
|
||||
+ if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
+ get_mgt_id(*msg) != ds_id) {
|
||||
+ msg_put(*msg);
|
||||
+ *msg = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+ node->pmc_ds_requested = 0;
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ Enumeration8 portState;
|
||||
+ void *data;
|
||||
+ int res;
|
||||
+
|
||||
+ while (1) {
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ data = get_mgt_data(msg);
|
||||
+ portState = ((struct portDS *)data)->portState;
|
||||
+ msg_put(msg);
|
||||
+
|
||||
+ switch (portState) {
|
||||
+ case PS_MASTER:
|
||||
+ case PS_SLAVE:
|
||||
+ return 1;
|
||||
+ }
|
||||
+ /* try to get more data sets (for other ports) */
|
||||
+ node->pmc_ds_requested = 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+ struct timePropertiesDS *tds;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
+ if (tds->flags & PTP_TIMESCALE) {
|
||||
+ node->sync_offset = tds->currentUtcOffset;
|
||||
+ if (tds->flags & LEAP_61)
|
||||
+ node->leap = 1;
|
||||
+ else if (tds->flags & LEAP_59)
|
||||
+ node->leap = -1;
|
||||
+ else
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
+ tds->flags & TIME_TRACEABLE;
|
||||
+ } else {
|
||||
+ node->sync_offset = 0;
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = 0;
|
||||
+ }
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+ struct defaultDS *dds;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+
|
||||
+ dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
+ res = dds->numberPorts;
|
||||
+ msg_put(msg);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
+ if (res <= 0)
|
||||
+ return res;
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+void run_pmc_events(struct pmc_node *node)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+
|
||||
+ run_pmc(node, 0, -1, &msg);
|
||||
+}
|
||||
+
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res, len;
|
||||
+ struct port_properties_np *ppn;
|
||||
+
|
||||
+ pmc_target_port(node->pmc, port);
|
||||
+ while (1) {
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
+ if (res <= 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ ppn = get_mgt_data(msg);
|
||||
+ if (ppn->portIdentity.portNumber != port) {
|
||||
+ msg_put(msg);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ *state = ppn->port_state;
|
||||
+ *tstamping = ppn->timestamping;
|
||||
+ len = ppn->interface.length;
|
||||
+ if (len > IFNAMSIZ - 1)
|
||||
+ len = IFNAMSIZ - 1;
|
||||
+ memcpy(iface, ppn->interface.text, len);
|
||||
+ iface[len] = '\0';
|
||||
+
|
||||
+ msg_put(msg);
|
||||
+ res = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+out:
|
||||
+ pmc_target_all(node->pmc);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+int run_pmc_clock_identity(struct pmc_node *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 *)get_mgt_data(msg);
|
||||
+ memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
+ sizeof(struct ClockIdentity));
|
||||
+ node->clock_identity_set = 1;
|
||||
+ msg_put(msg);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/* Returns: -1 in case of error, 0 otherwise */
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
+{
|
||||
+ struct timespec tp;
|
||||
+ uint64_t ts;
|
||||
+
|
||||
+ if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
+ pr_err("failed to read clock: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
+
|
||||
+ if (node->pmc &&
|
||||
+ !(ts > node->pmc_last_update &&
|
||||
+ ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
+ if (subscribe)
|
||||
+ run_pmc_subscribe(node, 0);
|
||||
+ if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
+ node->pmc_last_update = ts;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
+{
|
||||
+ node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
+ config_get_int(cfg, NULL, "domainNumber"),
|
||||
+ config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
|
||||
+ if (!node->pmc) {
|
||||
+ pr_err("failed to create pmc");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ node->recv_subscribed = recv_subscribed;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void close_pmc_node(struct pmc_node *node)
|
||||
+{
|
||||
+ if (!node->pmc)
|
||||
+ return;
|
||||
+
|
||||
+ pmc_destroy(node->pmc);
|
||||
+ node->pmc = NULL;
|
||||
+}
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
new file mode 100644
|
||||
index 0000000..90245b1
|
||||
--- /dev/null
|
||||
+++ b/pmc_agent.h
|
||||
@@ -0,0 +1,62 @@
|
||||
+/**
|
||||
+ * @file pmc_agent.h
|
||||
+ * @brief Client code for making PTP management requests.
|
||||
+ * @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
||||
+ * @note Copyright (C) 2020 Richard Cochran <richardcochran@gmail.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License along
|
||||
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ */
|
||||
+
|
||||
+#ifndef HAVE_PMC_AGENT_H
|
||||
+#define HAVE_PMC_AGENT_H
|
||||
+
|
||||
+#include "pmc_common.h"
|
||||
+
|
||||
+struct pmc_node;
|
||||
+
|
||||
+typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
+ struct ptp_message *msg,
|
||||
+ int excluded);
|
||||
+
|
||||
+struct pmc_node {
|
||||
+ struct pmc *pmc;
|
||||
+ int pmc_ds_requested;
|
||||
+ uint64_t pmc_last_update;
|
||||
+ int sync_offset;
|
||||
+ int leap;
|
||||
+ int utc_offset_traceable;
|
||||
+ int clock_identity_set;
|
||||
+ struct ClockIdentity clock_identity;
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
+};
|
||||
+
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed);
|
||||
+void close_pmc_node(struct pmc_node *node);
|
||||
+int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
+int run_pmc_subscribe(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_clock_identity(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_wait_sync(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_get_number_ports(struct pmc_node *node, int timeout);
|
||||
+void run_pmc_events(struct pmc_node *node);
|
||||
+int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface);
|
||||
+int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
+int get_mgt_id(struct ptp_message *msg);
|
||||
+void *get_mgt_data(struct ptp_message *msg);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
diff --git a/pmc_common.c b/pmc_common.c
|
||||
index c9cdf18..a117904 100644
|
||||
--- a/pmc_common.c
|
||||
+++ b/pmc_common.c
|
||||
@@ -18,8 +18,6 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <errno.h>
|
||||
-#include <net/if.h>
|
||||
-#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
@@ -29,7 +27,6 @@
|
||||
#include "print.h"
|
||||
#include "tlv.h"
|
||||
#include "transport.h"
|
||||
-#include "util.h"
|
||||
#include "pmc_common.h"
|
||||
|
||||
#define BAD_ACTION -1
|
||||
@@ -58,13 +55,6 @@
|
||||
/* Includes one extra byte to make length even. */
|
||||
#define EMPTY_PTP_TEXT 2
|
||||
|
||||
-#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
|
||||
-#define PMC_SUBSCRIBE_DURATION 180 /* 3 minutes */
|
||||
-/* Note that PMC_SUBSCRIBE_DURATION has to be longer than
|
||||
- * PMC_UPDATE_INTERVAL otherwise subscription will time out before it is
|
||||
- * renewed.
|
||||
- */
|
||||
-
|
||||
static void do_get_action(struct pmc *pmc, int action, int index, char *str);
|
||||
static void do_set_action(struct pmc *pmc, int action, int index, char *str);
|
||||
static void not_supported(struct pmc *pmc, int action, int index, char *str);
|
||||
@@ -720,331 +710,3 @@ int pmc_do_command(struct pmc *pmc, char *str)
|
||||
|
||||
return 0;
|
||||
}
|
||||
-
|
||||
-static void send_subscription(struct pmc_node *node)
|
||||
-{
|
||||
- struct subscribe_events_np sen;
|
||||
-
|
||||
- memset(&sen, 0, sizeof(sen));
|
||||
- sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
- sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
- pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
-}
|
||||
-
|
||||
-static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
-{
|
||||
- if (!node->clock_identity_set)
|
||||
- return 1;
|
||||
- return cid_eq(&node->clock_identity,
|
||||
- &msg->header.sourcePortIdentity.clockIdentity);
|
||||
-}
|
||||
-
|
||||
-static int is_msg_mgt(struct ptp_message *msg)
|
||||
-{
|
||||
- struct TLV *tlv;
|
||||
-
|
||||
- if (msg_type(msg) != MANAGEMENT)
|
||||
- return 0;
|
||||
- if (management_action(msg) != RESPONSE)
|
||||
- return 0;
|
||||
- if (msg_tlv_count(msg) != 1)
|
||||
- return 0;
|
||||
- tlv = (struct TLV *) msg->management.suffix;
|
||||
- if (tlv->type == TLV_MANAGEMENT)
|
||||
- return 1;
|
||||
- if (tlv->type == TLV_MANAGEMENT_ERROR_STATUS)
|
||||
- return -1;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int get_mgt_id(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt;
|
||||
-
|
||||
- mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->id;
|
||||
-}
|
||||
-
|
||||
-void *get_mgt_data(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt;
|
||||
-
|
||||
- mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->data;
|
||||
-}
|
||||
-
|
||||
-static int get_mgt_err_id(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_error_status *mgt;
|
||||
-
|
||||
- mgt = (struct management_error_status *)msg->management.suffix;
|
||||
- return mgt->id;
|
||||
-}
|
||||
-
|
||||
-/* Return values:
|
||||
- * 1: success
|
||||
- * 0: timeout
|
||||
- * -1: error reported by the other side
|
||||
- * -2: local error, fatal
|
||||
- */
|
||||
-static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
- struct ptp_message **msg)
|
||||
-{
|
||||
-#define N_FD 1
|
||||
- struct pollfd pollfd[N_FD];
|
||||
- int cnt, res;
|
||||
-
|
||||
- while (1) {
|
||||
- pollfd[0].fd = pmc_get_transport_fd(node->pmc);
|
||||
- pollfd[0].events = POLLIN|POLLPRI;
|
||||
- if (!node->pmc_ds_requested && ds_id >= 0)
|
||||
- pollfd[0].events |= POLLOUT;
|
||||
-
|
||||
- cnt = poll(pollfd, N_FD, timeout);
|
||||
- if (cnt < 0) {
|
||||
- pr_err("poll failed");
|
||||
- return -2;
|
||||
- }
|
||||
- if (!cnt) {
|
||||
- /* Request the data set again in the next run. */
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- /* Send a new request if there are no pending messages. */
|
||||
- if ((pollfd[0].revents & POLLOUT) &&
|
||||
- !(pollfd[0].revents & (POLLIN|POLLPRI))) {
|
||||
- switch (ds_id) {
|
||||
- case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
- send_subscription(node);
|
||||
- break;
|
||||
- default:
|
||||
- pmc_send_get_action(node->pmc, ds_id);
|
||||
- break;
|
||||
- }
|
||||
- node->pmc_ds_requested = 1;
|
||||
- }
|
||||
-
|
||||
- if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
- continue;
|
||||
-
|
||||
- *msg = pmc_recv(node->pmc);
|
||||
-
|
||||
- if (!*msg)
|
||||
- continue;
|
||||
-
|
||||
- if (!check_clock_identity(node, *msg)) {
|
||||
- msg_put(*msg);
|
||||
- *msg = NULL;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- res = is_msg_mgt(*msg);
|
||||
- if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return -1;
|
||||
- }
|
||||
- if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
- get_mgt_id(*msg) != ds_id) {
|
||||
- msg_put(*msg);
|
||||
- *msg = NULL;
|
||||
- continue;
|
||||
- }
|
||||
- node->pmc_ds_requested = 0;
|
||||
- return 1;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- Enumeration8 portState;
|
||||
- void *data;
|
||||
- int res;
|
||||
-
|
||||
- while (1) {
|
||||
- res = run_pmc(node, timeout, TLV_PORT_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- data = get_mgt_data(msg);
|
||||
- portState = ((struct portDS *)data)->portState;
|
||||
- msg_put(msg);
|
||||
-
|
||||
- switch (portState) {
|
||||
- case PS_MASTER:
|
||||
- case PS_SLAVE:
|
||||
- return 1;
|
||||
- }
|
||||
- /* try to get more data sets (for other ports) */
|
||||
- node->pmc_ds_requested = 1;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct timePropertiesDS *tds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
- if (tds->flags & PTP_TIMESCALE) {
|
||||
- node->sync_offset = tds->currentUtcOffset;
|
||||
- if (tds->flags & LEAP_61)
|
||||
- node->leap = 1;
|
||||
- else if (tds->flags & LEAP_59)
|
||||
- node->leap = -1;
|
||||
- else
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
- tds->flags & TIME_TRACEABLE;
|
||||
- } else {
|
||||
- node->sync_offset = 0;
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = 0;
|
||||
- }
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct defaultDS *dds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
- res = dds->numberPorts;
|
||||
- msg_put(msg);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
-int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-void run_pmc_events(struct pmc_node *node)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
-
|
||||
- run_pmc(node, 0, -1, &msg);
|
||||
-}
|
||||
-
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res, len;
|
||||
- struct port_properties_np *ppn;
|
||||
-
|
||||
- pmc_target_port(node->pmc, port);
|
||||
- while (1) {
|
||||
- res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- goto out;
|
||||
-
|
||||
- ppn = get_mgt_data(msg);
|
||||
- if (ppn->portIdentity.portNumber != port) {
|
||||
- msg_put(msg);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- *state = ppn->port_state;
|
||||
- *tstamping = ppn->timestamping;
|
||||
- len = ppn->interface.length;
|
||||
- if (len > IFNAMSIZ - 1)
|
||||
- len = IFNAMSIZ - 1;
|
||||
- memcpy(iface, ppn->interface.text, len);
|
||||
- iface[len] = '\0';
|
||||
-
|
||||
- msg_put(msg);
|
||||
- res = 1;
|
||||
- break;
|
||||
- }
|
||||
-out:
|
||||
- pmc_target_all(node->pmc);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
-int run_pmc_clock_identity(struct pmc_node *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 *)get_mgt_data(msg);
|
||||
- memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
- sizeof(struct ClockIdentity));
|
||||
- node->clock_identity_set = 1;
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-/* Returns: -1 in case of error, 0 otherwise */
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
-{
|
||||
- struct timespec tp;
|
||||
- uint64_t ts;
|
||||
-
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
- pr_err("failed to read clock: %m");
|
||||
- return -1;
|
||||
- }
|
||||
- ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
-
|
||||
- if (node->pmc &&
|
||||
- !(ts > node->pmc_last_update &&
|
||||
- ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
- if (subscribe)
|
||||
- run_pmc_subscribe(node, 0);
|
||||
- if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
- node->pmc_last_update = ts;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
-{
|
||||
- node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
- config_get_int(cfg, NULL, "domainNumber"),
|
||||
- config_get_int(cfg, NULL, "transportSpecific") << 4, 1);
|
||||
- if (!node->pmc) {
|
||||
- pr_err("failed to create pmc");
|
||||
- return -1;
|
||||
- }
|
||||
- node->recv_subscribed = recv_subscribed;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-void close_pmc_node(struct pmc_node *node)
|
||||
-{
|
||||
- if (!node->pmc)
|
||||
- return;
|
||||
-
|
||||
- pmc_destroy(node->pmc);
|
||||
- node->pmc = NULL;
|
||||
-}
|
||||
diff --git a/pmc_common.h b/pmc_common.h
|
||||
index 476ccea..8bea2e0 100644
|
||||
--- a/pmc_common.h
|
||||
+++ b/pmc_common.h
|
||||
@@ -50,38 +50,4 @@ void pmc_target_all(struct pmc *pmc);
|
||||
const char *pmc_action_string(int action);
|
||||
int pmc_do_command(struct pmc *pmc, char *str);
|
||||
|
||||
-struct pmc_node;
|
||||
-
|
||||
-typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
- struct ptp_message *msg,
|
||||
- int excluded);
|
||||
-
|
||||
-struct pmc_node {
|
||||
- struct pmc *pmc;
|
||||
- int pmc_ds_requested;
|
||||
- uint64_t pmc_last_update;
|
||||
- int sync_offset;
|
||||
- int leap;
|
||||
- int utc_offset_traceable;
|
||||
- int clock_identity_set;
|
||||
- struct ClockIdentity clock_identity;
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
-};
|
||||
-
|
||||
-int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed);
|
||||
-void close_pmc_node(struct pmc_node *node);
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
-int run_pmc_subscribe(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_clock_identity(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_wait_sync(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_get_number_ports(struct pmc_node *node, int timeout);
|
||||
-void run_pmc_events(struct pmc_node *node);
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface);
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
-int get_mgt_id(struct ptp_message *msg);
|
||||
-void *get_mgt_data(struct ptp_message *msg);
|
||||
-
|
||||
#endif
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,212 @@
|
||||
From 82258917b8de7110545f3d4f99d3ac88a609f019 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:47:36 -0300
|
||||
Subject: [PATCH 15/47] pmc_agent: Rename pmc_node to something more
|
||||
descriptive.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit bb6865cdf59572fcb09c11d549828269281c6841 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 4 ++--
|
||||
pmc_agent.c | 26 +++++++++++++-------------
|
||||
pmc_agent.h | 26 +++++++++++++-------------
|
||||
3 files changed, 28 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 648ba61..74ee9d1 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -103,7 +103,7 @@ struct phc2sys_private {
|
||||
int forced_sync_offset;
|
||||
int kernel_leap;
|
||||
int state_changed;
|
||||
- struct pmc_node node;
|
||||
+ struct pmc_agent node;
|
||||
LIST_HEAD(port_head, port) ports;
|
||||
LIST_HEAD(clock_head, clock) clocks;
|
||||
LIST_HEAD(dst_clock_head, clock) dst_clocks;
|
||||
@@ -813,7 +813,7 @@ static int clock_compute_state(struct phc2sys_private *priv,
|
||||
#define node_to_phc2sys(node) \
|
||||
container_of(node, struct phc2sys_private, node)
|
||||
|
||||
-static int phc2sys_recv_subscribed(struct pmc_node *node,
|
||||
+static int phc2sys_recv_subscribed(struct pmc_agent *node,
|
||||
struct ptp_message *msg, int excluded)
|
||||
{
|
||||
struct phc2sys_private *priv = node_to_phc2sys(node);
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 774e94d..e83895c 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -32,7 +32,7 @@
|
||||
* renewed.
|
||||
*/
|
||||
|
||||
-static void send_subscription(struct pmc_node *node)
|
||||
+static void send_subscription(struct pmc_agent *node)
|
||||
{
|
||||
struct subscribe_events_np sen;
|
||||
|
||||
@@ -42,7 +42,7 @@ static void send_subscription(struct pmc_node *node)
|
||||
pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
}
|
||||
|
||||
-static int check_clock_identity(struct pmc_node *node, struct ptp_message *msg)
|
||||
+static int check_clock_identity(struct pmc_agent *node, struct ptp_message *msg)
|
||||
{
|
||||
if (!node->clock_identity_set)
|
||||
return 1;
|
||||
@@ -98,7 +98,7 @@ static int get_mgt_err_id(struct ptp_message *msg)
|
||||
* -1: error reported by the other side
|
||||
* -2: local error, fatal
|
||||
*/
|
||||
-static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
+static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
struct ptp_message **msg)
|
||||
{
|
||||
#define N_FD 1
|
||||
@@ -166,7 +166,7 @@ static int run_pmc(struct pmc_node *node, int timeout, int ds_id,
|
||||
}
|
||||
}
|
||||
|
||||
-int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_wait_sync(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
Enumeration8 portState;
|
||||
@@ -192,7 +192,7 @@ int run_pmc_wait_sync(struct pmc_node *node, int timeout)
|
||||
}
|
||||
}
|
||||
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_get_utc_offset(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -222,7 +222,7 @@ int run_pmc_get_utc_offset(struct pmc_node *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_get_number_ports(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -238,7 +238,7 @@ int run_pmc_get_number_ports(struct pmc_node *node, int timeout)
|
||||
return res;
|
||||
}
|
||||
|
||||
-int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_subscribe(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
int res;
|
||||
@@ -250,14 +250,14 @@ int run_pmc_subscribe(struct pmc_node *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-void run_pmc_events(struct pmc_node *node)
|
||||
+void run_pmc_events(struct pmc_agent *node)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
|
||||
run_pmc(node, 0, -1, &msg);
|
||||
}
|
||||
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+int run_pmc_port_properties(struct pmc_agent *node, int timeout,
|
||||
unsigned int port, int *state,
|
||||
int *tstamping, char *iface)
|
||||
{
|
||||
@@ -294,7 +294,7 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
-int run_pmc_clock_identity(struct pmc_node *node, int timeout)
|
||||
+int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
struct defaultDS *dds;
|
||||
@@ -313,7 +313,7 @@ int run_pmc_clock_identity(struct pmc_node *node, int timeout)
|
||||
}
|
||||
|
||||
/* Returns: -1 in case of error, 0 otherwise */
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
+int update_pmc_node(struct pmc_agent *node, int subscribe)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
@@ -336,7 +336,7 @@ int update_pmc_node(struct pmc_node *node, int subscribe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
|
||||
pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
{
|
||||
node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
@@ -351,7 +351,7 @@ int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void close_pmc_node(struct pmc_node *node)
|
||||
+void close_pmc_node(struct pmc_agent *node)
|
||||
{
|
||||
if (!node->pmc)
|
||||
return;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 90245b1..10ef4b5 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -24,13 +24,13 @@
|
||||
|
||||
#include "pmc_common.h"
|
||||
|
||||
-struct pmc_node;
|
||||
+struct pmc_agent;
|
||||
|
||||
-typedef int pmc_node_recv_subscribed_t(struct pmc_node *node,
|
||||
+typedef int pmc_node_recv_subscribed_t(struct pmc_agent *agent,
|
||||
struct ptp_message *msg,
|
||||
int excluded);
|
||||
|
||||
-struct pmc_node {
|
||||
+struct pmc_agent {
|
||||
struct pmc *pmc;
|
||||
int pmc_ds_requested;
|
||||
uint64_t pmc_last_update;
|
||||
@@ -42,19 +42,19 @@ struct pmc_node {
|
||||
pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
};
|
||||
|
||||
-int init_pmc_node(struct config *cfg, struct pmc_node *node, const char *uds,
|
||||
+int init_pmc_node(struct config *cfg, struct pmc_agent *agent, const char *uds,
|
||||
pmc_node_recv_subscribed_t *recv_subscribed);
|
||||
-void close_pmc_node(struct pmc_node *node);
|
||||
-int update_pmc_node(struct pmc_node *node, int subscribe);
|
||||
-int run_pmc_subscribe(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_clock_identity(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_wait_sync(struct pmc_node *node, int timeout);
|
||||
-int run_pmc_get_number_ports(struct pmc_node *node, int timeout);
|
||||
-void run_pmc_events(struct pmc_node *node);
|
||||
-int run_pmc_port_properties(struct pmc_node *node, int timeout,
|
||||
+void close_pmc_node(struct pmc_agent *agent);
|
||||
+int update_pmc_node(struct pmc_agent *agent, int subscribe);
|
||||
+int run_pmc_subscribe(struct pmc_agent *agent, int timeout);
|
||||
+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);
|
||||
+int run_pmc_port_properties(struct pmc_agent *agent, int timeout,
|
||||
unsigned int port, int *state,
|
||||
int *tstamping, char *iface);
|
||||
-int run_pmc_get_utc_offset(struct pmc_node *node, int timeout);
|
||||
+int run_pmc_get_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
int get_mgt_id(struct ptp_message *msg);
|
||||
void *get_mgt_data(struct ptp_message *msg);
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,448 @@
|
||||
From f6d7bb0a62f15fcca0343c42891f7e056f502949 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:55:29 -0300
|
||||
Subject: [PATCH 16/47] pmc_agent: Hide the implementation.
|
||||
|
||||
The PMC agent's implementation should not be exposed to its users. This
|
||||
patch hides the details and provides a method to create an instance. In
|
||||
addition, the signature of the receive callback is made generic, removing
|
||||
the container_of pattern meant for sub-classing modules.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit 826698791769e0ba4431fe98f02d4d09c109542e upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 76 +++++++++++++++++++++++++++++------------------------
|
||||
pmc_agent.c | 58 +++++++++++++++++++++++++++++++++++-----
|
||||
pmc_agent.h | 62 +++++++++++++++++++++++++++++++------------
|
||||
3 files changed, 138 insertions(+), 58 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 74ee9d1..037b1b9 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -103,7 +103,7 @@ struct phc2sys_private {
|
||||
int forced_sync_offset;
|
||||
int kernel_leap;
|
||||
int state_changed;
|
||||
- struct pmc_agent node;
|
||||
+ struct pmc_agent *node;
|
||||
LIST_HEAD(port_head, port) ports;
|
||||
LIST_HEAD(clock_head, clock) clocks;
|
||||
LIST_HEAD(dst_clock_head, clock) dst_clocks;
|
||||
@@ -306,7 +306,7 @@ static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
|
||||
LIST_FOREACH(p, &priv->ports, list) {
|
||||
if (p->clock == clock) {
|
||||
- ret = run_pmc_port_properties(&priv->node, 1000, p->number,
|
||||
+ ret = run_pmc_port_properties(priv->node, 1000, p->number,
|
||||
&state, ×tamping,
|
||||
iface);
|
||||
if (ret > 0)
|
||||
@@ -641,7 +641,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
|
||||
if (src == CLOCK_INVALID) {
|
||||
/* The sync offset can't be applied with PPS alone. */
|
||||
- priv->node.sync_offset = 0;
|
||||
+ pmc_agent_set_sync_offset(priv->node, 0);
|
||||
} else {
|
||||
enable_pps_output(priv->master->clkid);
|
||||
}
|
||||
@@ -672,7 +672,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
- if (update_pmc_node(&priv->node, 0) < 0)
|
||||
+ if (update_pmc_node(priv->node, 0) < 0)
|
||||
continue;
|
||||
update_clock(priv, clock, pps_offset, pps_ts, -1);
|
||||
}
|
||||
@@ -710,15 +710,15 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
|
||||
while (is_running()) {
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
|
||||
- if (update_pmc_node(&priv->node, subscriptions) < 0)
|
||||
+ if (update_pmc_node(priv->node, subscriptions) < 0)
|
||||
continue;
|
||||
|
||||
if (subscriptions) {
|
||||
- run_pmc_events(&priv->node);
|
||||
+ run_pmc_events(priv->node);
|
||||
if (priv->state_changed) {
|
||||
/* force getting offset, as it may have
|
||||
* changed after the port state change */
|
||||
- if (run_pmc_get_utc_offset(&priv->node, 1000) <= 0) {
|
||||
+ if (run_pmc_get_utc_offset(priv->node, 1000) <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
continue;
|
||||
}
|
||||
@@ -810,13 +810,10 @@ static int clock_compute_state(struct phc2sys_private *priv,
|
||||
return state;
|
||||
}
|
||||
|
||||
-#define node_to_phc2sys(node) \
|
||||
- container_of(node, struct phc2sys_private, node)
|
||||
-
|
||||
-static int phc2sys_recv_subscribed(struct pmc_agent *node,
|
||||
- struct ptp_message *msg, int excluded)
|
||||
+static int phc2sys_recv_subscribed(void *context, struct ptp_message *msg,
|
||||
+ int excluded)
|
||||
{
|
||||
- struct phc2sys_private *priv = node_to_phc2sys(node);
|
||||
+ struct phc2sys_private *priv = (struct phc2sys_private *) context;
|
||||
int mgt_id, state;
|
||||
struct portDS *pds;
|
||||
struct port *port;
|
||||
@@ -863,7 +860,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
while (1) {
|
||||
if (!is_running())
|
||||
return -1;
|
||||
- res = run_pmc_clock_identity(&priv->node, 1000);
|
||||
+ res = run_pmc_clock_identity(priv->node, 1000);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
if (res > 0)
|
||||
@@ -872,20 +869,20 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
pr_notice("Waiting for ptp4l...");
|
||||
}
|
||||
|
||||
- number_ports = run_pmc_get_number_ports(&priv->node, 1000);
|
||||
+ number_ports = run_pmc_get_number_ports(priv->node, 1000);
|
||||
if (number_ports <= 0) {
|
||||
pr_err("failed to get number of ports");
|
||||
return -1;
|
||||
}
|
||||
|
||||
- res = run_pmc_subscribe(&priv->node, 1000);
|
||||
+ res = run_pmc_subscribe(priv->node, 1000);
|
||||
if (res <= 0) {
|
||||
pr_err("failed to subscribe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i <= number_ports; i++) {
|
||||
- res = run_pmc_port_properties(&priv->node, 1000, i, &state,
|
||||
+ res = run_pmc_port_properties(priv->node, 1000, i, &state,
|
||||
×tamping, iface);
|
||||
if (res == -1) {
|
||||
/* port does not exist, ignore the port */
|
||||
@@ -922,7 +919,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* get initial offset */
|
||||
- if (run_pmc_get_utc_offset(&priv->node, 1000) <= 0) {
|
||||
+ if (run_pmc_get_utc_offset(priv->node, 1000) <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
return -1;
|
||||
}
|
||||
@@ -933,9 +930,9 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
int64_t offset, uint64_t ts)
|
||||
{
|
||||
- int clock_leap, node_leap = priv->node.leap;
|
||||
+ int clock_leap, node_leap = pmc_agent_get_leap(priv->node);
|
||||
|
||||
- clock->sync_offset = priv->node.sync_offset;
|
||||
+ clock->sync_offset = pmc_agent_get_sync_offset(priv->node);
|
||||
|
||||
if ((node_leap || clock->leap_set) &&
|
||||
clock->is_utc != priv->master->is_utc) {
|
||||
@@ -976,7 +973,7 @@ static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
}
|
||||
}
|
||||
|
||||
- if (priv->node.utc_offset_traceable &&
|
||||
+ if (pmc_agent_utc_offset_traceable(priv->node) &&
|
||||
clock->utc_offset_set != clock->sync_offset) {
|
||||
if (clock->clkid == CLOCK_REALTIME)
|
||||
sysclk_set_tai_offset(clock->sync_offset);
|
||||
@@ -1032,11 +1029,13 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
char *config = NULL, *dst_name = NULL, *progname, *src_name = NULL;
|
||||
char uds_local[MAX_IFNAME_SIZE + 1];
|
||||
+ int autocfg = 0, c, domain_number = 0, index, ntpshm_segment, offset;
|
||||
+ int pps_fd = -1, print_level = LOG_INFO, r = -1, rt = 0;
|
||||
+ int wait_sync = 0;
|
||||
struct clock *src, *dst;
|
||||
struct config *cfg;
|
||||
struct option *opts;
|
||||
- int autocfg = 0, c, domain_number = 0, default_sync = 1, index, ntpshm_segment;
|
||||
- int pps_fd = -1, print_level = LOG_INFO, r = -1, rt = 0, wait_sync = 0;
|
||||
+ int default_sync = 1;
|
||||
double phc_rate, tmp;
|
||||
struct phc2sys_private priv = {
|
||||
.phc_readings = 5,
|
||||
@@ -1049,6 +1048,10 @@ int main(int argc, char *argv[])
|
||||
if (!cfg) {
|
||||
return -1;
|
||||
}
|
||||
+ priv.node = pmc_agent_create();
|
||||
+ if (!priv.node) {
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
opts = config_long_options(cfg);
|
||||
|
||||
@@ -1140,9 +1143,10 @@ int main(int argc, char *argv[])
|
||||
goto end;
|
||||
break;
|
||||
case 'O':
|
||||
- if (get_arg_val_i(c, optarg, &priv.node.sync_offset,
|
||||
- INT_MIN, INT_MAX))
|
||||
+ if (get_arg_val_i(c, optarg, &offset, INT_MIN, INT_MAX)) {
|
||||
goto end;
|
||||
+ }
|
||||
+ pmc_agent_set_sync_offset(priv.node, offset);
|
||||
priv.forced_sync_offset = -1;
|
||||
break;
|
||||
case 'L':
|
||||
@@ -1271,8 +1275,8 @@ int main(int argc, char *argv[])
|
||||
getpid());
|
||||
|
||||
if (autocfg) {
|
||||
- if (init_pmc_node(cfg, &priv.node, uds_local,
|
||||
- phc2sys_recv_subscribed))
|
||||
+ if (init_pmc_node(cfg, priv.node, uds_local,
|
||||
+ phc2sys_recv_subscribed, &priv))
|
||||
goto end;
|
||||
if (auto_init_ports(&priv, rt) < 0)
|
||||
goto end;
|
||||
@@ -1309,12 +1313,12 @@ int main(int argc, char *argv[])
|
||||
r = -1;
|
||||
|
||||
if (wait_sync) {
|
||||
- if (init_pmc_node(cfg, &priv.node, uds_local,
|
||||
- phc2sys_recv_subscribed))
|
||||
+ if (init_pmc_node(cfg, priv.node, uds_local,
|
||||
+ phc2sys_recv_subscribed, &priv))
|
||||
goto end;
|
||||
|
||||
while (is_running()) {
|
||||
- r = run_pmc_wait_sync(&priv.node, 1000);
|
||||
+ r = run_pmc_wait_sync(priv.node, 1000);
|
||||
if (r < 0)
|
||||
goto end;
|
||||
if (r > 0)
|
||||
@@ -1324,7 +1328,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!priv.forced_sync_offset) {
|
||||
- r = run_pmc_get_utc_offset(&priv.node, 1000);
|
||||
+ r = run_pmc_get_utc_offset(priv.node, 1000);
|
||||
if (r <= 0) {
|
||||
pr_err("failed to get UTC offset");
|
||||
goto end;
|
||||
@@ -1333,8 +1337,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (priv.forced_sync_offset ||
|
||||
(src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
- src->clkid == CLOCK_INVALID)
|
||||
- close_pmc_node(&priv.node);
|
||||
+ src->clkid == CLOCK_INVALID) {
|
||||
+ pmc_agent_destroy(priv.node);
|
||||
+ priv.node = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (pps_fd >= 0) {
|
||||
@@ -1347,7 +1353,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
end:
|
||||
- close_pmc_node(&priv.node);
|
||||
+ if (priv.node) {
|
||||
+ pmc_agent_destroy(priv.node);
|
||||
+ }
|
||||
clock_cleanup(&priv);
|
||||
port_cleanup(&priv);
|
||||
config_destroy(cfg);
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index e83895c..8ccafe2 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
#include <net/if.h>
|
||||
#include <poll.h>
|
||||
+#include <stdlib.h>
|
||||
|
||||
#include "notification.h"
|
||||
#include "pmc_agent.h"
|
||||
@@ -32,6 +33,22 @@
|
||||
* renewed.
|
||||
*/
|
||||
|
||||
+struct pmc_agent {
|
||||
+ struct pmc *pmc;
|
||||
+ uint64_t pmc_last_update;
|
||||
+
|
||||
+ struct ClockIdentity clock_identity;
|
||||
+ int clock_identity_set;
|
||||
+ int leap;
|
||||
+ int pmc_ds_requested;
|
||||
+ int sync_offset;
|
||||
+ int utc_offset_traceable;
|
||||
+
|
||||
+ /* Callback on message reception */
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
+ void *recv_context;
|
||||
+};
|
||||
+
|
||||
static void send_subscription(struct pmc_agent *node)
|
||||
{
|
||||
struct subscribe_events_np sen;
|
||||
@@ -155,7 +172,8 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
node->pmc_ds_requested = 0;
|
||||
return -1;
|
||||
}
|
||||
- if (res <= 0 || node->recv_subscribed(node, *msg, ds_id) ||
|
||||
+ if (res <= 0 ||
|
||||
+ node->recv_subscribed(node->recv_context, *msg, ds_id) ||
|
||||
get_mgt_id(*msg) != ds_id) {
|
||||
msg_put(*msg);
|
||||
*msg = NULL;
|
||||
@@ -337,7 +355,7 @@ int update_pmc_node(struct pmc_agent *node, int subscribe)
|
||||
}
|
||||
|
||||
int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed)
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed, void *context)
|
||||
{
|
||||
node->pmc = pmc_create(cfg, TRANS_UDS, uds, 0,
|
||||
config_get_int(cfg, NULL, "domainNumber"),
|
||||
@@ -347,15 +365,41 @@ int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
|
||||
return -1;
|
||||
}
|
||||
node->recv_subscribed = recv_subscribed;
|
||||
+ node->recv_context = context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void close_pmc_node(struct pmc_agent *node)
|
||||
+struct pmc_agent *pmc_agent_create(void)
|
||||
+{
|
||||
+ struct pmc_agent *agent = calloc(1, sizeof(*agent));
|
||||
+ return agent;
|
||||
+}
|
||||
+
|
||||
+void pmc_agent_destroy(struct pmc_agent *agent)
|
||||
+{
|
||||
+ if (agent->pmc) {
|
||||
+ pmc_destroy(agent->pmc);
|
||||
+ }
|
||||
+ free(agent);
|
||||
+}
|
||||
+
|
||||
+int pmc_agent_get_leap(struct pmc_agent *agent)
|
||||
{
|
||||
- if (!node->pmc)
|
||||
- return;
|
||||
+ return agent->leap;
|
||||
+}
|
||||
+
|
||||
+int pmc_agent_get_sync_offset(struct pmc_agent *agent)
|
||||
+{
|
||||
+ return agent->sync_offset;
|
||||
+}
|
||||
|
||||
- pmc_destroy(node->pmc);
|
||||
- node->pmc = NULL;
|
||||
+void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset)
|
||||
+{
|
||||
+ agent->sync_offset = offset;
|
||||
+}
|
||||
+
|
||||
+bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent)
|
||||
+{
|
||||
+ return agent->utc_offset_traceable;
|
||||
}
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 10ef4b5..c0b4525 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -22,29 +22,17 @@
|
||||
#ifndef HAVE_PMC_AGENT_H
|
||||
#define HAVE_PMC_AGENT_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
#include "pmc_common.h"
|
||||
|
||||
struct pmc_agent;
|
||||
|
||||
-typedef int pmc_node_recv_subscribed_t(struct pmc_agent *agent,
|
||||
- struct ptp_message *msg,
|
||||
+typedef int pmc_node_recv_subscribed_t(void *context, struct ptp_message *msg,
|
||||
int excluded);
|
||||
|
||||
-struct pmc_agent {
|
||||
- struct pmc *pmc;
|
||||
- int pmc_ds_requested;
|
||||
- uint64_t pmc_last_update;
|
||||
- int sync_offset;
|
||||
- int leap;
|
||||
- int utc_offset_traceable;
|
||||
- int clock_identity_set;
|
||||
- struct ClockIdentity clock_identity;
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
-};
|
||||
-
|
||||
int init_pmc_node(struct config *cfg, struct pmc_agent *agent, const char *uds,
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed);
|
||||
-void close_pmc_node(struct pmc_agent *agent);
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed, void *context);
|
||||
int update_pmc_node(struct pmc_agent *agent, int subscribe);
|
||||
int run_pmc_subscribe(struct pmc_agent *agent, int timeout);
|
||||
int run_pmc_clock_identity(struct pmc_agent *agent, int timeout);
|
||||
@@ -58,5 +46,45 @@ int run_pmc_get_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
int get_mgt_id(struct ptp_message *msg);
|
||||
void *get_mgt_data(struct ptp_message *msg);
|
||||
|
||||
-#endif
|
||||
|
||||
+/**
|
||||
+ * Creates an instance of a PMC agent.
|
||||
+ * @return Pointer to a PMC instance on success, NULL otherwise.
|
||||
+ */
|
||||
+struct pmc_agent *pmc_agent_create(void);
|
||||
+
|
||||
+/**
|
||||
+ * Destroys an instance of a PMC agent.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ */
|
||||
+void pmc_agent_destroy(struct pmc_agent *agent);
|
||||
+
|
||||
+/**
|
||||
+ * Gets the current leap adjustment.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @return The leap adjustment in seconds, either 1, 0, or -1.
|
||||
+ */
|
||||
+int pmc_agent_get_leap(struct pmc_agent *agent);
|
||||
+
|
||||
+/**
|
||||
+ * Gets the TAI-UTC offset.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @return Current offset in seconds.
|
||||
+ */
|
||||
+int pmc_agent_get_sync_offset(struct pmc_agent *agent);
|
||||
+
|
||||
+/**
|
||||
+ * Sets the TAI-UTC offset.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @param offset Desired offset in seconds.
|
||||
+ */
|
||||
+void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset);
|
||||
+
|
||||
+/**
|
||||
+ * Tests whether the current UTC offset is traceable.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @return True is the offset is traceable, false otherwise.
|
||||
+ */
|
||||
+bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent);
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,96 @@
|
||||
From 4ebb69f5c55e7f1f08d1a73df87d42fe70147ec9 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:58:09 -0300
|
||||
Subject: [PATCH 17/47] Find a better home for the management TLV ID helper
|
||||
function.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit d95bb9f9d62f4f372934905e97e052aa68dcfc58 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
msg.h | 12 ++++++++++++
|
||||
phc2sys.c | 2 +-
|
||||
pmc_agent.c | 10 +---------
|
||||
pmc_agent.h | 1 -
|
||||
4 files changed, 14 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/msg.h b/msg.h
|
||||
index e71d3ce..b600ff0 100644
|
||||
--- a/msg.h
|
||||
+++ b/msg.h
|
||||
@@ -247,6 +247,18 @@ static inline uint8_t management_action(struct ptp_message *m)
|
||||
return m->management.flags & 0x0f;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * Obtain the ID field from the TLV in a management message.
|
||||
+ * @param m A management message.
|
||||
+ * @return The value of the ID field.
|
||||
+ */
|
||||
+static inline int management_tlv_id(struct ptp_message *m)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+ mgt = (struct management_tlv *) m->management.suffix;
|
||||
+ return mgt->id;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Test a given bit in a message's flag field.
|
||||
* @param m Message to test.
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 037b1b9..1f74f27 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -819,7 +819,7 @@ static int phc2sys_recv_subscribed(void *context, struct ptp_message *msg,
|
||||
struct port *port;
|
||||
struct clock *clock;
|
||||
|
||||
- mgt_id = get_mgt_id(msg);
|
||||
+ mgt_id = management_tlv_id(msg);
|
||||
if (mgt_id == excluded)
|
||||
return 0;
|
||||
switch (mgt_id) {
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 8ccafe2..6dfb3ca 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -85,14 +85,6 @@ static int is_msg_mgt(struct ptp_message *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int get_mgt_id(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt;
|
||||
-
|
||||
- mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->id;
|
||||
-}
|
||||
-
|
||||
void *get_mgt_data(struct ptp_message *msg)
|
||||
{
|
||||
struct management_tlv *mgt;
|
||||
@@ -174,7 +166,7 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
}
|
||||
if (res <= 0 ||
|
||||
node->recv_subscribed(node->recv_context, *msg, ds_id) ||
|
||||
- get_mgt_id(*msg) != ds_id) {
|
||||
+ management_tlv_id(*msg) != ds_id) {
|
||||
msg_put(*msg);
|
||||
*msg = NULL;
|
||||
continue;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index c0b4525..09249ff 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -43,7 +43,6 @@ int run_pmc_port_properties(struct pmc_agent *agent, int timeout,
|
||||
unsigned int port, int *state,
|
||||
int *tstamping, char *iface);
|
||||
int run_pmc_get_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
-int get_mgt_id(struct ptp_message *msg);
|
||||
void *get_mgt_data(struct ptp_message *msg);
|
||||
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,132 @@
|
||||
From 6e4f8ea8531b7678a44a9b3ed021fda94eccdc27 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 14:59:57 -0300
|
||||
Subject: [PATCH 18/47] Find a better home for the management TLV data helper
|
||||
function.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit 5dd47c873cae8e0a2815b43c1ef3a86b9aca9dac upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
msg.h | 12 ++++++++++++
|
||||
phc2sys.c | 2 +-
|
||||
pmc_agent.c | 18 +++++-------------
|
||||
pmc_agent.h | 1 -
|
||||
4 files changed, 18 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/msg.h b/msg.h
|
||||
index b600ff0..84380da 100644
|
||||
--- a/msg.h
|
||||
+++ b/msg.h
|
||||
@@ -247,6 +247,18 @@ static inline uint8_t management_action(struct ptp_message *m)
|
||||
return m->management.flags & 0x0f;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * Obtain the data field from the TLV in a management message.
|
||||
+ * @param m A management message.
|
||||
+ * @return A pointer to the TLV data field.
|
||||
+ */
|
||||
+static inline void *management_tlv_data(struct ptp_message *msg)
|
||||
+{
|
||||
+ struct management_tlv *mgt;
|
||||
+ mgt = (struct management_tlv *) msg->management.suffix;
|
||||
+ return mgt->data;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* Obtain the ID field from the TLV in a management message.
|
||||
* @param m A management message.
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 1f74f27..280e249 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -824,7 +824,7 @@ static int phc2sys_recv_subscribed(void *context, struct ptp_message *msg,
|
||||
return 0;
|
||||
switch (mgt_id) {
|
||||
case TLV_PORT_DATA_SET:
|
||||
- pds = get_mgt_data(msg);
|
||||
+ pds = management_tlv_data(msg);
|
||||
port = port_get(priv, pds->portIdentity.portNumber);
|
||||
if (!port) {
|
||||
pr_info("received data for unknown port %s",
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 6dfb3ca..6e9c023 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -85,14 +85,6 @@ static int is_msg_mgt(struct ptp_message *msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void *get_mgt_data(struct ptp_message *msg)
|
||||
-{
|
||||
- struct management_tlv *mgt;
|
||||
-
|
||||
- mgt = (struct management_tlv *) msg->management.suffix;
|
||||
- return mgt->data;
|
||||
-}
|
||||
-
|
||||
static int get_mgt_err_id(struct ptp_message *msg)
|
||||
{
|
||||
struct management_error_status *mgt;
|
||||
@@ -188,7 +180,7 @@ int run_pmc_wait_sync(struct pmc_agent *node, int timeout)
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
- data = get_mgt_data(msg);
|
||||
+ data = management_tlv_data(msg);
|
||||
portState = ((struct portDS *)data)->portState;
|
||||
msg_put(msg);
|
||||
|
||||
@@ -212,7 +204,7 @@ int run_pmc_get_utc_offset(struct pmc_agent *node, int timeout)
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
- tds = (struct timePropertiesDS *)get_mgt_data(msg);
|
||||
+ tds = (struct timePropertiesDS *) management_tlv_data(msg);
|
||||
if (tds->flags & PTP_TIMESCALE) {
|
||||
node->sync_offset = tds->currentUtcOffset;
|
||||
if (tds->flags & LEAP_61)
|
||||
@@ -242,7 +234,7 @@ int run_pmc_get_number_ports(struct pmc_agent *node, int timeout)
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
- dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
+ dds = (struct defaultDS *) management_tlv_data(msg);
|
||||
res = dds->numberPorts;
|
||||
msg_put(msg);
|
||||
return res;
|
||||
@@ -281,7 +273,7 @@ int run_pmc_port_properties(struct pmc_agent *node, int timeout,
|
||||
if (res <= 0)
|
||||
goto out;
|
||||
|
||||
- ppn = get_mgt_data(msg);
|
||||
+ ppn = management_tlv_data(msg);
|
||||
if (ppn->portIdentity.portNumber != port) {
|
||||
msg_put(msg);
|
||||
continue;
|
||||
@@ -314,7 +306,7 @@ int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
- dds = (struct defaultDS *)get_mgt_data(msg);
|
||||
+ dds = (struct defaultDS *) management_tlv_data(msg);
|
||||
memcpy(&node->clock_identity, &dds->clockIdentity,
|
||||
sizeof(struct ClockIdentity));
|
||||
node->clock_identity_set = 1;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 09249ff..f3a26fe 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -43,7 +43,6 @@ int run_pmc_port_properties(struct pmc_agent *agent, int timeout,
|
||||
unsigned int port, int *state,
|
||||
int *tstamping, char *iface);
|
||||
int run_pmc_get_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
-void *get_mgt_data(struct ptp_message *msg);
|
||||
|
||||
|
||||
/**
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,81 @@
|
||||
From 95e4983c9ab517b9dda1faf171721f0dd877e076 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:04:11 -0300
|
||||
Subject: [PATCH 19/47] Introduce error codes for the run_pmc method.
|
||||
|
||||
The run_pmc function is used by several of the PMC agent methods, but it
|
||||
breaks the pattern of returning zero on success. However, the user facing
|
||||
PMC agent methods will need to conform to the return code convention used
|
||||
throughout the stack.
|
||||
|
||||
In order to migrate to proper return codes, this patch replaces the hard
|
||||
coded result values with macros so that the interface methods can translate
|
||||
them to the required semantics of zero on success.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 802259bbe40faa5f8bdebab36e6fbcbc51c3c2a2 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 19 +++++++++----------
|
||||
1 file changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 6e9c023..22d9c5b 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -93,12 +93,11 @@ static int get_mgt_err_id(struct ptp_message *msg)
|
||||
return mgt->id;
|
||||
}
|
||||
|
||||
-/* Return values:
|
||||
- * 1: success
|
||||
- * 0: timeout
|
||||
- * -1: error reported by the other side
|
||||
- * -2: local error, fatal
|
||||
- */
|
||||
+#define RUN_PMC_OKAY 1
|
||||
+#define RUN_PMC_TMO 0
|
||||
+#define RUN_PMC_NODEV -1
|
||||
+#define RUN_PMC_INTR -2
|
||||
+
|
||||
static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
struct ptp_message **msg)
|
||||
{
|
||||
@@ -115,12 +114,12 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
cnt = poll(pollfd, N_FD, timeout);
|
||||
if (cnt < 0) {
|
||||
pr_err("poll failed");
|
||||
- return -2;
|
||||
+ return RUN_PMC_INTR;
|
||||
}
|
||||
if (!cnt) {
|
||||
/* Request the data set again in the next run. */
|
||||
node->pmc_ds_requested = 0;
|
||||
- return 0;
|
||||
+ return RUN_PMC_TMO;
|
||||
}
|
||||
|
||||
/* Send a new request if there are no pending messages. */
|
||||
@@ -154,7 +153,7 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
res = is_msg_mgt(*msg);
|
||||
if (res < 0 && get_mgt_err_id(*msg) == ds_id) {
|
||||
node->pmc_ds_requested = 0;
|
||||
- return -1;
|
||||
+ return RUN_PMC_NODEV;
|
||||
}
|
||||
if (res <= 0 ||
|
||||
node->recv_subscribed(node->recv_context, *msg, ds_id) ||
|
||||
@@ -164,7 +163,7 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
continue;
|
||||
}
|
||||
node->pmc_ds_requested = 0;
|
||||
- return 1;
|
||||
+ return RUN_PMC_OKAY;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,153 @@
|
||||
From 8c1dd261683d27acba49e047d9f6da52dada3c98 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:08:01 -0300
|
||||
Subject: [PATCH 20/47] pmc_agent: Convert the subscribe method into the
|
||||
canonical form.
|
||||
|
||||
This patch renames the function to have the module prefix and corrects the
|
||||
return code semantics.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit cc98d39f58adc1fd05db0038acfdcc5669f2ba8c upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 4 ++--
|
||||
pmc_agent.c | 48 +++++++++++++++++++++++++++++++++++-------------
|
||||
pmc_agent.h | 9 ++++++++-
|
||||
3 files changed, 45 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 280e249..f61e699 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -875,8 +875,8 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- res = run_pmc_subscribe(priv->node, 1000);
|
||||
- if (res <= 0) {
|
||||
+ res = pmc_agent_subscribe(priv->node, 1000);
|
||||
+ if (res) {
|
||||
pr_err("failed to subscribe");
|
||||
return -1;
|
||||
}
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 22d9c5b..9c5eb71 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -17,6 +17,7 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
+#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
@@ -98,6 +99,26 @@ static int get_mgt_err_id(struct ptp_message *msg)
|
||||
#define RUN_PMC_NODEV -1
|
||||
#define RUN_PMC_INTR -2
|
||||
|
||||
+static bool is_run_pmc_error(int code)
|
||||
+{
|
||||
+ return code != RUN_PMC_OKAY;
|
||||
+}
|
||||
+
|
||||
+static int run_pmc_err2errno(int code)
|
||||
+{
|
||||
+ switch (code) {
|
||||
+ case RUN_PMC_TMO:
|
||||
+ return -ETIMEDOUT;
|
||||
+ case RUN_PMC_NODEV:
|
||||
+ return -ENODEV;
|
||||
+ case RUN_PMC_INTR:
|
||||
+ return -EINTR;
|
||||
+ case RUN_PMC_OKAY:
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
struct ptp_message **msg)
|
||||
{
|
||||
@@ -239,18 +260,6 @@ int run_pmc_get_number_ports(struct pmc_agent *node, int timeout)
|
||||
return res;
|
||||
}
|
||||
|
||||
-int run_pmc_subscribe(struct pmc_agent *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
void run_pmc_events(struct pmc_agent *node)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
@@ -329,7 +338,7 @@ int update_pmc_node(struct pmc_agent *node, int subscribe)
|
||||
!(ts > node->pmc_last_update &&
|
||||
ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
if (subscribe)
|
||||
- run_pmc_subscribe(node, 0);
|
||||
+ pmc_agent_subscribe(node, 0);
|
||||
if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
node->pmc_last_update = ts;
|
||||
}
|
||||
@@ -382,6 +391,19 @@ void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset)
|
||||
agent->sync_offset = offset;
|
||||
}
|
||||
|
||||
+int pmc_agent_subscribe(struct pmc_agent *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
+ if (is_run_pmc_error(res)) {
|
||||
+ return run_pmc_err2errno(res);
|
||||
+ }
|
||||
+ msg_put(msg);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent)
|
||||
{
|
||||
return agent->utc_offset_traceable;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index f3a26fe..9dc684e 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -34,7 +34,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 update_pmc_node(struct pmc_agent *agent, int subscribe);
|
||||
-int run_pmc_subscribe(struct pmc_agent *agent, int timeout);
|
||||
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);
|
||||
@@ -78,6 +77,14 @@ int pmc_agent_get_sync_offset(struct pmc_agent *agent);
|
||||
*/
|
||||
void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset);
|
||||
|
||||
+/**
|
||||
+ * Subscribes to push notifications of changes in port state.
|
||||
+ * @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_subscribe(struct pmc_agent *agent, int timeout);
|
||||
+
|
||||
/**
|
||||
* Tests whether the current UTC offset is traceable.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,133 @@
|
||||
From 82a369b4fe44a7cea41fb0ccf408c02b1b6aa694 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:17:26 -0300
|
||||
Subject: [PATCH 21/47] pmc_agent: Simplify the update method.
|
||||
|
||||
The main method that causes the PMC agent to update its status takes a flag
|
||||
that results in different behavior when push notifications are active.
|
||||
This patch simplifies the interface by letting the agent remember whether
|
||||
or not the caller subscribed to the notifications in the first place.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 1126f8f67e853199f05a7c993c910ebc7807bd3d upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 6 ++++--
|
||||
pmc_agent.c | 32 ++++++++++++++++++++------------
|
||||
pmc_agent.h | 2 +-
|
||||
3 files changed, 25 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index f61e699..b155961 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -672,7 +672,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
- if (update_pmc_node(priv->node, 0) < 0)
|
||||
+ if (update_pmc_node(priv->node) < 0)
|
||||
continue;
|
||||
update_clock(priv, clock, pps_offset, pps_ts, -1);
|
||||
}
|
||||
@@ -710,8 +710,10 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
|
||||
while (is_running()) {
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
|
||||
- if (update_pmc_node(priv->node, subscriptions) < 0)
|
||||
+
|
||||
+ if (update_pmc_node(priv->node) < 0) {
|
||||
continue;
|
||||
+ }
|
||||
|
||||
if (subscriptions) {
|
||||
run_pmc_events(priv->node);
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 9c5eb71..dd509af 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -42,6 +42,7 @@ struct pmc_agent {
|
||||
int clock_identity_set;
|
||||
int leap;
|
||||
int pmc_ds_requested;
|
||||
+ bool stay_subscribed;
|
||||
int sync_offset;
|
||||
int utc_offset_traceable;
|
||||
|
||||
@@ -188,6 +189,19 @@ static int run_pmc(struct pmc_agent *node, int timeout, int ds_id,
|
||||
}
|
||||
}
|
||||
|
||||
+static int renew_subscription(struct pmc_agent *node, int timeout)
|
||||
+{
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
+ if (is_run_pmc_error(res)) {
|
||||
+ return run_pmc_err2errno(res);
|
||||
+ }
|
||||
+ msg_put(msg);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int run_pmc_wait_sync(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
@@ -323,7 +337,7 @@ int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
||||
}
|
||||
|
||||
/* Returns: -1 in case of error, 0 otherwise */
|
||||
-int update_pmc_node(struct pmc_agent *node, int subscribe)
|
||||
+int update_pmc_node(struct pmc_agent *node)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
@@ -337,8 +351,9 @@ int update_pmc_node(struct pmc_agent *node, int subscribe)
|
||||
if (node->pmc &&
|
||||
!(ts > node->pmc_last_update &&
|
||||
ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
- if (subscribe)
|
||||
- pmc_agent_subscribe(node, 0);
|
||||
+ if (node->stay_subscribed) {
|
||||
+ renew_subscription(node, 0);
|
||||
+ }
|
||||
if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
node->pmc_last_update = ts;
|
||||
}
|
||||
@@ -393,15 +408,8 @@ void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset)
|
||||
|
||||
int pmc_agent_subscribe(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_SUBSCRIBE_EVENTS_NP, &msg);
|
||||
- if (is_run_pmc_error(res)) {
|
||||
- return run_pmc_err2errno(res);
|
||||
- }
|
||||
- msg_put(msg);
|
||||
- return 0;
|
||||
+ node->stay_subscribed = true;
|
||||
+ return renew_subscription(node, timeout);
|
||||
}
|
||||
|
||||
bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent)
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 9dc684e..743818f 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -33,7 +33,7 @@ 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 update_pmc_node(struct pmc_agent *agent, int subscribe);
|
||||
+int update_pmc_node(struct pmc_agent *agent);
|
||||
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);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 731e8938953e56578007a679dbaa29e9471650ac Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:18:36 -0300
|
||||
Subject: [PATCH 22/47] pmc_agent: Simplify logic in update method.
|
||||
|
||||
If the pmc pointer is not set, then there is no need to read the time only
|
||||
to later discard the result. This patch simplifies the flow by returning
|
||||
early if there is no work to be done.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 956b7eeb8247e3f0658b1205dfd3bea3e1011ee2 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index dd509af..f30f174 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -342,14 +342,16 @@ int update_pmc_node(struct pmc_agent *node)
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
|
||||
+ if (!node->pmc) {
|
||||
+ return 0;
|
||||
+ }
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
pr_err("failed to read clock: %m");
|
||||
return -1;
|
||||
}
|
||||
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
|
||||
- if (node->pmc &&
|
||||
- !(ts > node->pmc_last_update &&
|
||||
+ if (!(ts > node->pmc_last_update &&
|
||||
ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
if (node->stay_subscribed) {
|
||||
renew_subscription(node, 0);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,40 @@
|
||||
From 357e24c897e1e2d29cf011b3a38c3a6b2a7943c3 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:33:43 -0300
|
||||
Subject: [PATCH 23/47] pmc_agent: Remove bogus comparison between last update
|
||||
and now.
|
||||
|
||||
The monotonic clock can never go backwards. If you take T1 and later T2
|
||||
from that clock, then (T2 > T1) is always true.
|
||||
|
||||
This patch removes the useless test.
|
||||
|
||||
[ This test evolved over the years. Originally the time stamp in question
|
||||
came from a PHC. ]
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 2f2f7fc5881a88295350430edaf4505dc03b1602 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index f30f174..df3a562 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -351,8 +351,7 @@ int update_pmc_node(struct pmc_agent *node)
|
||||
}
|
||||
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
|
||||
- if (!(ts > node->pmc_last_update &&
|
||||
- ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
+ if (!(ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
if (node->stay_subscribed) {
|
||||
renew_subscription(node, 0);
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,43 @@
|
||||
From d5421e4d4d86907648a59810ab9c27e739591971 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:35:23 -0300
|
||||
Subject: [PATCH 24/47] pmc_agent: Perform time comparison using positive
|
||||
logic.
|
||||
|
||||
In the update_pmc_node() method, reduce the expression
|
||||
!(x < y) to (x >= y).
|
||||
|
||||
While we're at it, clean the coding style as well.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit fb92fec7cef9ee3345950c2633a7781b8bd3ca08 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index df3a562..ea6b3b7 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -351,12 +351,13 @@ int update_pmc_node(struct pmc_agent *node)
|
||||
}
|
||||
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
|
||||
- if (!(ts - node->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
+ if (ts - node->pmc_last_update >= PMC_UPDATE_INTERVAL) {
|
||||
if (node->stay_subscribed) {
|
||||
renew_subscription(node, 0);
|
||||
}
|
||||
- if (run_pmc_get_utc_offset(node, 0) > 0)
|
||||
+ if (run_pmc_get_utc_offset(node, 0) > 0) {
|
||||
node->pmc_last_update = ts;
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,155 @@
|
||||
From a304d4df86a76c187fc7074755fe9b5ad349efbe Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:36:38 -0300
|
||||
Subject: [PATCH 25/47] pmc_agent: Rename the update method and attempt to
|
||||
document it.
|
||||
|
||||
This patch renames the function to have the module prefix and tries to
|
||||
put into words what it does.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
||||
|
||||
[commit 9a2dae984e0d355d751913e3308f9a954da11aa3 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 4 ++--
|
||||
pmc_agent.c | 53 ++++++++++++++++++++++++++---------------------------
|
||||
pmc_agent.h | 21 ++++++++++++++++++++-
|
||||
3 files changed, 48 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index b155961..cbe80f2 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -672,7 +672,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
- if (update_pmc_node(priv->node) < 0)
|
||||
+ if (pmc_agent_update(priv->node) < 0)
|
||||
continue;
|
||||
update_clock(priv, clock, pps_offset, pps_ts, -1);
|
||||
}
|
||||
@@ -711,7 +711,7 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
while (is_running()) {
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
|
||||
|
||||
- if (update_pmc_node(priv->node) < 0) {
|
||||
+ if (pmc_agent_update(priv->node) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index ea6b3b7..22af306 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -336,33 +336,6 @@ int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
-/* Returns: -1 in case of error, 0 otherwise */
|
||||
-int update_pmc_node(struct pmc_agent *node)
|
||||
-{
|
||||
- struct timespec tp;
|
||||
- uint64_t ts;
|
||||
-
|
||||
- if (!node->pmc) {
|
||||
- return 0;
|
||||
- }
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
- pr_err("failed to read clock: %m");
|
||||
- return -1;
|
||||
- }
|
||||
- ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
-
|
||||
- if (ts - node->pmc_last_update >= PMC_UPDATE_INTERVAL) {
|
||||
- if (node->stay_subscribed) {
|
||||
- renew_subscription(node, 0);
|
||||
- }
|
||||
- if (run_pmc_get_utc_offset(node, 0) > 0) {
|
||||
- node->pmc_last_update = ts;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int init_pmc_node(struct config *cfg, struct pmc_agent *node, const char *uds,
|
||||
pmc_node_recv_subscribed_t *recv_subscribed, void *context)
|
||||
{
|
||||
@@ -414,6 +387,32 @@ int pmc_agent_subscribe(struct pmc_agent *node, int timeout)
|
||||
return renew_subscription(node, timeout);
|
||||
}
|
||||
|
||||
+int pmc_agent_update(struct pmc_agent *node)
|
||||
+{
|
||||
+ struct timespec tp;
|
||||
+ uint64_t ts;
|
||||
+
|
||||
+ if (!node->pmc) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (clock_gettime(CLOCK_MONOTONIC, &tp)) {
|
||||
+ pr_err("failed to read clock: %m");
|
||||
+ return -errno;
|
||||
+ }
|
||||
+ ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
+
|
||||
+ if (ts - node->pmc_last_update >= PMC_UPDATE_INTERVAL) {
|
||||
+ if (node->stay_subscribed) {
|
||||
+ renew_subscription(node, 0);
|
||||
+ }
|
||||
+ if (run_pmc_get_utc_offset(node, 0) > 0) {
|
||||
+ node->pmc_last_update = ts;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent)
|
||||
{
|
||||
return agent->utc_offset_traceable;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 743818f..483a21b 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 update_pmc_node(struct pmc_agent *agent);
|
||||
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);
|
||||
@@ -85,6 +84,26 @@ void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset);
|
||||
*/
|
||||
int pmc_agent_subscribe(struct pmc_agent *agent, int timeout);
|
||||
|
||||
+/**
|
||||
+ * Queries the local ptp4l instance to update the TAI-UTC offset and
|
||||
+ * the current leap second flags.
|
||||
+ *
|
||||
+ * In addition:
|
||||
+ *
|
||||
+ * - Any active port state subscription will be renewed.
|
||||
+ * - The port state notification callback might be invoked.
|
||||
+ *
|
||||
+ * This function should be called periodically at least once per
|
||||
+ * minute to keep both the port state and the leap second flags up to
|
||||
+ * date. Note that the PMC agent rate limits the query to once per
|
||||
+ * minute, and so the caller may safely invoke this method more often
|
||||
+ * than that.
|
||||
+ *
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @return Zero on success, negative error code otherwise.
|
||||
+ */
|
||||
+int pmc_agent_update(struct pmc_agent *agent);
|
||||
+
|
||||
/**
|
||||
* Tests whether the current UTC offset is traceable.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,91 @@
|
||||
From 5aacbe319db97907a15741005e2790bbf4c742a0 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 15:37:46 -0300
|
||||
Subject: [PATCH 26/47] phc2sys: Fix null pointer de-reference in manual mode.
|
||||
|
||||
If both the -w and -O command line options are specified (or when
|
||||
using -w when both source and destination clocks are PHCs), then
|
||||
pointer to the PMC agent will be incorrectly freed.
|
||||
|
||||
Fix the segfault by introducing a method to "disable" the agent as was
|
||||
done before the PMC agent code was introduced.
|
||||
|
||||
Unfortunately the resulting PMC agent API now has both create/destroy
|
||||
and init/disable methods. This clunky arrangement can be cleaned up
|
||||
later on, but it entails re-factoring the phc2sys program even more.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Fixes: 8266987 ("pmc_agent: Hide the implementation.")
|
||||
|
||||
[commit 68fd0b010e9761e3dc580026eb6f2366c7c8e82d upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 7 ++-----
|
||||
pmc_agent.c | 8 ++++++++
|
||||
pmc_agent.h | 6 ++++++
|
||||
3 files changed, 16 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index cbe80f2..3cafbb2 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -1340,8 +1340,7 @@ int main(int argc, char *argv[])
|
||||
if (priv.forced_sync_offset ||
|
||||
(src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
src->clkid == CLOCK_INVALID) {
|
||||
- pmc_agent_destroy(priv.node);
|
||||
- priv.node = NULL;
|
||||
+ pmc_agent_disable(priv.node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1355,9 +1354,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
end:
|
||||
- if (priv.node) {
|
||||
- pmc_agent_destroy(priv.node);
|
||||
- }
|
||||
+ pmc_agent_destroy(priv.node);
|
||||
clock_cleanup(&priv);
|
||||
port_cleanup(&priv);
|
||||
config_destroy(cfg);
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 22af306..833d1c1 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -366,6 +366,14 @@ void pmc_agent_destroy(struct pmc_agent *agent)
|
||||
free(agent);
|
||||
}
|
||||
|
||||
+void pmc_agent_disable(struct pmc_agent *agent)
|
||||
+{
|
||||
+ if (agent->pmc) {
|
||||
+ pmc_destroy(agent->pmc);
|
||||
+ }
|
||||
+ agent->pmc = NULL;
|
||||
+}
|
||||
+
|
||||
int pmc_agent_get_leap(struct pmc_agent *agent)
|
||||
{
|
||||
return agent->leap;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 483a21b..0ed10f8 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -55,6 +55,12 @@ struct pmc_agent *pmc_agent_create(void);
|
||||
*/
|
||||
void pmc_agent_destroy(struct pmc_agent *agent);
|
||||
|
||||
+/**
|
||||
+ * Disconnects the PMC agent from the ptp4l service.
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ */
|
||||
+void pmc_agent_disable(struct pmc_agent *agent);
|
||||
+
|
||||
/**
|
||||
* Gets the current leap adjustment.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,182 @@
|
||||
From b8188a4fd51bc8983e5d19f18fe37b8ca39d03a6 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:20:04 -0300
|
||||
Subject: [PATCH 27/47] pmc_agent: Convert the method that queries TAI-UTC
|
||||
offset into the canonical form.
|
||||
|
||||
This patch renames the function to have the module prefix and corrects the
|
||||
return code semantics.
|
||||
|
||||
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>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
|
||||
[commit 943c8f51c56acb72277d1a9459bbf7b7a5ac5fe7 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 8 +++----
|
||||
pmc_agent.c | 63 +++++++++++++++++++++++++++--------------------------
|
||||
pmc_agent.h | 16 ++++++++++++--
|
||||
3 files changed, 50 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 3cafbb2..78d662b 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -720,7 +720,7 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
if (priv->state_changed) {
|
||||
/* force getting offset, as it may have
|
||||
* changed after the port state change */
|
||||
- if (run_pmc_get_utc_offset(priv->node, 1000) <= 0) {
|
||||
+ if (pmc_agent_query_utc_offset(priv->node, 1000)) {
|
||||
pr_err("failed to get UTC offset");
|
||||
continue;
|
||||
}
|
||||
@@ -921,7 +921,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* get initial offset */
|
||||
- if (run_pmc_get_utc_offset(priv->node, 1000) <= 0) {
|
||||
+ if (pmc_agent_query_utc_offset(priv->node, 1000)) {
|
||||
pr_err("failed to get UTC offset");
|
||||
return -1;
|
||||
}
|
||||
@@ -1330,8 +1330,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!priv.forced_sync_offset) {
|
||||
- r = run_pmc_get_utc_offset(priv.node, 1000);
|
||||
- if (r <= 0) {
|
||||
+ r = pmc_agent_query_utc_offset(priv.node, 1000);
|
||||
+ if (r) {
|
||||
pr_err("failed to get UTC offset");
|
||||
goto end;
|
||||
}
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 833d1c1..7a57a2f 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -228,36 +228,6 @@ int run_pmc_wait_sync(struct pmc_agent *node, int timeout)
|
||||
}
|
||||
}
|
||||
|
||||
-int run_pmc_get_utc_offset(struct pmc_agent *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct timePropertiesDS *tds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- tds = (struct timePropertiesDS *) management_tlv_data(msg);
|
||||
- if (tds->flags & PTP_TIMESCALE) {
|
||||
- node->sync_offset = tds->currentUtcOffset;
|
||||
- if (tds->flags & LEAP_61)
|
||||
- node->leap = 1;
|
||||
- else if (tds->flags & LEAP_59)
|
||||
- node->leap = -1;
|
||||
- else
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
- tds->flags & TIME_TRACEABLE;
|
||||
- } else {
|
||||
- node->sync_offset = 0;
|
||||
- node->leap = 0;
|
||||
- node->utc_offset_traceable = 0;
|
||||
- }
|
||||
- msg_put(msg);
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
int run_pmc_get_number_ports(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
@@ -384,6 +354,37 @@ int pmc_agent_get_sync_offset(struct pmc_agent *agent)
|
||||
return agent->sync_offset;
|
||||
}
|
||||
|
||||
+int pmc_agent_query_utc_offset(struct pmc_agent *node, int timeout)
|
||||
+{
|
||||
+ struct timePropertiesDS *tds;
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, TLV_TIME_PROPERTIES_DATA_SET, &msg);
|
||||
+ if (is_run_pmc_error(res)) {
|
||||
+ return run_pmc_err2errno(res);
|
||||
+ }
|
||||
+
|
||||
+ tds = (struct timePropertiesDS *) management_tlv_data(msg);
|
||||
+ if (tds->flags & PTP_TIMESCALE) {
|
||||
+ node->sync_offset = tds->currentUtcOffset;
|
||||
+ if (tds->flags & LEAP_61)
|
||||
+ node->leap = 1;
|
||||
+ else if (tds->flags & LEAP_59)
|
||||
+ node->leap = -1;
|
||||
+ else
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
+ tds->flags & TIME_TRACEABLE;
|
||||
+ } else {
|
||||
+ node->sync_offset = 0;
|
||||
+ node->leap = 0;
|
||||
+ node->utc_offset_traceable = 0;
|
||||
+ }
|
||||
+ msg_put(msg);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset)
|
||||
{
|
||||
agent->sync_offset = offset;
|
||||
@@ -413,7 +414,7 @@ int pmc_agent_update(struct pmc_agent *node)
|
||||
if (node->stay_subscribed) {
|
||||
renew_subscription(node, 0);
|
||||
}
|
||||
- if (run_pmc_get_utc_offset(node, 0) > 0) {
|
||||
+ if (!pmc_agent_query_utc_offset(node, 0)) {
|
||||
node->pmc_last_update = ts;
|
||||
}
|
||||
}
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 0ed10f8..44326d2 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -40,8 +40,6 @@ void run_pmc_events(struct pmc_agent *agent);
|
||||
int run_pmc_port_properties(struct pmc_agent *agent, int timeout,
|
||||
unsigned int port, int *state,
|
||||
int *tstamping, char *iface);
|
||||
-int run_pmc_get_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
-
|
||||
|
||||
/**
|
||||
* Creates an instance of a PMC agent.
|
||||
@@ -75,6 +73,20 @@ int pmc_agent_get_leap(struct pmc_agent *agent);
|
||||
*/
|
||||
int pmc_agent_get_sync_offset(struct pmc_agent *agent);
|
||||
|
||||
+/**
|
||||
+ * Queries the TAI-UTC offset and the current leap adjustment from the
|
||||
+ * ptp4l service.
|
||||
+ *
|
||||
+ * 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_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
+
|
||||
/**
|
||||
* Sets the TAI-UTC offset.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,244 @@
|
||||
From acdf74df9fa69b81c1e9332f10d4efcd3e9bae48 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:23:29 -0300
|
||||
Subject: [PATCH 28/47] pmc_agent: Convert the method that queries the port
|
||||
properties.
|
||||
|
||||
Prefix the function with the module name and correct the return code
|
||||
semantics.
|
||||
|
||||
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 ac7d69bbc476b94d76e5cee4992b9682f003feaf upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 41 +++++++++++++++--------------
|
||||
pmc_agent.c | 74 ++++++++++++++++++++++++++---------------------------
|
||||
pmc_agent.h | 22 +++++++++++++---
|
||||
3 files changed, 78 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 78d662b..32e6e13 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -296,8 +296,7 @@ static struct port *port_add(struct phc2sys_private *priv, unsigned int number,
|
||||
static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
int new_state)
|
||||
{
|
||||
- int phc_index = -1, phc_switched = 0;
|
||||
- int state, timestamping, ret = -1;
|
||||
+ int err = -1, phc_index = -1, phc_switched = 0, state, timestamping;
|
||||
struct port *p;
|
||||
struct servo *servo;
|
||||
struct sk_ts_info ts_info;
|
||||
@@ -305,16 +304,19 @@ static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
clockid_t clkid = CLOCK_INVALID;
|
||||
|
||||
LIST_FOREACH(p, &priv->ports, list) {
|
||||
- if (p->clock == clock) {
|
||||
- ret = run_pmc_port_properties(priv->node, 1000, p->number,
|
||||
- &state, ×tamping,
|
||||
- iface);
|
||||
- if (ret > 0)
|
||||
- p->state = normalize_state(state);
|
||||
+ if (p->clock != clock) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ err = pmc_agent_query_port_properties(priv->node, 1000,
|
||||
+ p->number, &state,
|
||||
+ ×tamping, iface);
|
||||
+ if (!err) {
|
||||
+ p->state = normalize_state(state);
|
||||
}
|
||||
+ break;
|
||||
}
|
||||
|
||||
- if (ret > 0 && timestamping != TS_SOFTWARE) {
|
||||
+ if (!err && timestamping != TS_SOFTWARE) {
|
||||
/* Check if device changed */
|
||||
if (strcmp(clock->device, iface)) {
|
||||
free(clock->device);
|
||||
@@ -852,12 +854,12 @@ static int phc2sys_recv_subscribed(void *context, struct ptp_message *msg,
|
||||
|
||||
static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
{
|
||||
- struct port *port;
|
||||
- struct clock *clock;
|
||||
- int number_ports, res;
|
||||
- unsigned int i;
|
||||
+ int err, number_ports, res;
|
||||
int state, timestamping;
|
||||
char iface[IFNAMSIZ];
|
||||
+ struct clock *clock;
|
||||
+ struct port *port;
|
||||
+ unsigned int i;
|
||||
|
||||
while (1) {
|
||||
if (!is_running())
|
||||
@@ -877,20 +879,21 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- res = pmc_agent_subscribe(priv->node, 1000);
|
||||
- if (res) {
|
||||
+ err = pmc_agent_subscribe(priv->node, 1000);
|
||||
+ if (err) {
|
||||
pr_err("failed to subscribe");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i <= number_ports; i++) {
|
||||
- res = run_pmc_port_properties(priv->node, 1000, i, &state,
|
||||
- ×tamping, iface);
|
||||
- if (res == -1) {
|
||||
+ err = pmc_agent_query_port_properties(priv->node, 1000, i,
|
||||
+ &state, ×tamping,
|
||||
+ iface);
|
||||
+ if (err == -ENODEV) {
|
||||
/* port does not exist, ignore the port */
|
||||
continue;
|
||||
}
|
||||
- if (res <= 0) {
|
||||
+ if (err) {
|
||||
pr_err("failed to get port properties");
|
||||
return -1;
|
||||
}
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 7a57a2f..cc729ab 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -251,43 +251,6 @@ void run_pmc_events(struct pmc_agent *node)
|
||||
run_pmc(node, 0, -1, &msg);
|
||||
}
|
||||
|
||||
-int run_pmc_port_properties(struct pmc_agent *node, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res, len;
|
||||
- struct port_properties_np *ppn;
|
||||
-
|
||||
- pmc_target_port(node->pmc, port);
|
||||
- while (1) {
|
||||
- res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
- if (res <= 0)
|
||||
- goto out;
|
||||
-
|
||||
- ppn = management_tlv_data(msg);
|
||||
- if (ppn->portIdentity.portNumber != port) {
|
||||
- msg_put(msg);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- *state = ppn->port_state;
|
||||
- *tstamping = ppn->timestamping;
|
||||
- len = ppn->interface.length;
|
||||
- if (len > IFNAMSIZ - 1)
|
||||
- len = IFNAMSIZ - 1;
|
||||
- memcpy(iface, ppn->interface.text, len);
|
||||
- iface[len] = '\0';
|
||||
-
|
||||
- msg_put(msg);
|
||||
- res = 1;
|
||||
- break;
|
||||
- }
|
||||
-out:
|
||||
- pmc_target_all(node->pmc);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
int run_pmc_clock_identity(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
@@ -354,6 +317,43 @@ int pmc_agent_get_sync_offset(struct pmc_agent *agent)
|
||||
return agent->sync_offset;
|
||||
}
|
||||
|
||||
+int pmc_agent_query_port_properties(struct pmc_agent *node, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface)
|
||||
+{
|
||||
+ struct port_properties_np *ppn;
|
||||
+ struct ptp_message *msg;
|
||||
+ int res, len;
|
||||
+
|
||||
+ pmc_target_port(node->pmc, port);
|
||||
+ while (1) {
|
||||
+ res = run_pmc(node, timeout, TLV_PORT_PROPERTIES_NP, &msg);
|
||||
+ if (is_run_pmc_error(res)) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ppn = management_tlv_data(msg);
|
||||
+ if (ppn->portIdentity.portNumber != port) {
|
||||
+ msg_put(msg);
|
||||
+ continue;
|
||||
+ }
|
||||
+ *state = ppn->port_state;
|
||||
+ *tstamping = ppn->timestamping;
|
||||
+ len = ppn->interface.length;
|
||||
+ if (len > IFNAMSIZ - 1) {
|
||||
+ len = IFNAMSIZ - 1;
|
||||
+ }
|
||||
+ memcpy(iface, ppn->interface.text, len);
|
||||
+ iface[len] = '\0';
|
||||
+
|
||||
+ msg_put(msg);
|
||||
+ res = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+out:
|
||||
+ pmc_target_all(node->pmc);
|
||||
+ return run_pmc_err2errno(res);
|
||||
+}
|
||||
+
|
||||
int pmc_agent_query_utc_offset(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct timePropertiesDS *tds;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 44326d2..ea37bf9 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -37,9 +37,6 @@ 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);
|
||||
-int run_pmc_port_properties(struct pmc_agent *agent, int timeout,
|
||||
- unsigned int port, int *state,
|
||||
- int *tstamping, char *iface);
|
||||
|
||||
/**
|
||||
* Creates an instance of a PMC agent.
|
||||
@@ -73,6 +70,25 @@ int pmc_agent_get_leap(struct pmc_agent *agent);
|
||||
*/
|
||||
int pmc_agent_get_sync_offset(struct pmc_agent *agent);
|
||||
|
||||
+/**
|
||||
+ * Queries the port properties of a given port from the ptp4l service.
|
||||
+ *
|
||||
+ * 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.
|
||||
+ * @param port The port index of interest.
|
||||
+ * @param state Buffer to hold the returned port state.
|
||||
+ * @param tstamping Buffer to hold the returned time stamping flavor.
|
||||
+ * @param iface Buffer to hold the returned interface name.
|
||||
+ * @return Zero on success, negative error code otherwise.
|
||||
+ */
|
||||
+int pmc_agent_query_port_properties(struct pmc_agent *agent, int timeout,
|
||||
+ unsigned int port, int *state,
|
||||
+ int *tstamping, char *iface);
|
||||
+
|
||||
/**
|
||||
* Queries the TAI-UTC offset and the current leap adjustment from the
|
||||
* ptp4l service.
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,183 @@
|
||||
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/47] 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
|
||||
|
@ -0,0 +1,106 @@
|
||||
From d3b877cae9576beddb00d4c5db67bf49c944b222 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:30:57 -0300
|
||||
Subject: [PATCH 30/47] pmc_agent: Simplify the method that gets of the number
|
||||
of local ports.
|
||||
|
||||
The number of ports is already available in the cached default data
|
||||
set. Use it directly.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit 6bc9eb81dd254d90b5fe059684271b9beebf6b9b upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 2 +-
|
||||
pmc_agent.c | 24 ++++++++----------------
|
||||
pmc_agent.h | 11 ++++++++++-
|
||||
3 files changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 0f33630..569544e 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -875,7 +875,7 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
}
|
||||
|
||||
- number_ports = run_pmc_get_number_ports(priv->node, 1000);
|
||||
+ number_ports = pmc_agent_get_number_ports(priv->node);
|
||||
if (number_ports <= 0) {
|
||||
pr_err("failed to get number of ports");
|
||||
return -1;
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 51023d1..aa2347d 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -229,22 +229,6 @@ int run_pmc_wait_sync(struct pmc_agent *node, int timeout)
|
||||
}
|
||||
}
|
||||
|
||||
-int run_pmc_get_number_ports(struct pmc_agent *node, int timeout)
|
||||
-{
|
||||
- struct ptp_message *msg;
|
||||
- int res;
|
||||
- struct defaultDS *dds;
|
||||
-
|
||||
- res = run_pmc(node, timeout, TLV_DEFAULT_DATA_SET, &msg);
|
||||
- if (res <= 0)
|
||||
- return res;
|
||||
-
|
||||
- dds = (struct defaultDS *) management_tlv_data(msg);
|
||||
- res = dds->numberPorts;
|
||||
- msg_put(msg);
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
void run_pmc_events(struct pmc_agent *node)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
@@ -300,6 +284,14 @@ int pmc_agent_get_sync_offset(struct pmc_agent *agent)
|
||||
return agent->sync_offset;
|
||||
}
|
||||
|
||||
+int pmc_agent_get_number_ports(struct pmc_agent *node)
|
||||
+{
|
||||
+ if (!node->dds_valid) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return node->dds.numberPorts;
|
||||
+}
|
||||
+
|
||||
int pmc_agent_query_dds(struct pmc_agent *node, int timeout)
|
||||
{
|
||||
struct ptp_message *msg;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 9d8bd1c..f0e2c7a 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -34,7 +34,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_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);
|
||||
|
||||
/**
|
||||
@@ -62,6 +61,16 @@ void pmc_agent_disable(struct pmc_agent *agent);
|
||||
*/
|
||||
int pmc_agent_get_leap(struct pmc_agent *agent);
|
||||
|
||||
+/**
|
||||
+ * Gets the number of local ports from the default data set. Users
|
||||
+ * should first call pmc_agent_query_dds() before invoking this
|
||||
+ * function.
|
||||
+ *
|
||||
+ * @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
+ * @return The non-negative number of ports, or -1 if unknown.
|
||||
+ */
|
||||
+int pmc_agent_get_number_ports(struct pmc_agent *agent);
|
||||
+
|
||||
/**
|
||||
* Gets the TAI-UTC offset.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 156728d14591dd2b3131bcff49959e806523c1bb Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:32:27 -0300
|
||||
Subject: [PATCH 31/47] pmc_agent: Let the update method poll for push events.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit c4a5eef1f4763805e6e2a2d25eb1d436018d4745 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 3 +++
|
||||
pmc_agent.h | 5 +++--
|
||||
2 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index aa2347d..6e6627d 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -390,6 +390,7 @@ int pmc_agent_subscribe(struct pmc_agent *node, int timeout)
|
||||
|
||||
int pmc_agent_update(struct pmc_agent *node)
|
||||
{
|
||||
+ struct ptp_message *msg;
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
|
||||
@@ -411,6 +412,8 @@ int pmc_agent_update(struct pmc_agent *node)
|
||||
}
|
||||
}
|
||||
|
||||
+ run_pmc(node, 0, -1, &msg);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index f0e2c7a..dd34d30 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -141,11 +141,12 @@ void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset);
|
||||
int pmc_agent_subscribe(struct pmc_agent *agent, int timeout);
|
||||
|
||||
/**
|
||||
- * Queries the local ptp4l instance to update the TAI-UTC offset and
|
||||
- * the current leap second flags.
|
||||
+ * Polls for push notifications from the local ptp4l service.
|
||||
*
|
||||
* In addition:
|
||||
*
|
||||
+ * - Queries the local ptp4l instance to update the TAI-UTC offset and
|
||||
+ * the current leap second flags.
|
||||
* - Any active port state subscription will be renewed.
|
||||
* - The port state notification callback might be invoked.
|
||||
*
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,37 @@
|
||||
From 0e504e57af6c576202bbe1abe5a99eb24a981b73 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:51:10 -0300
|
||||
Subject: [PATCH 32/47] phc2sys: Fix regression in the automatic mode.
|
||||
|
||||
Commit ac7d69bbc476 ("pmc_agent: Convert the method that queries the
|
||||
port properties.") had the well meant intention of the cleaning up the
|
||||
error code semantics of the port properties query function. However,
|
||||
that commit mixed up the normal, external semantics of zero meaning
|
||||
success with the internal semantics where zero is an error. Correct
|
||||
the issue by replacing the hard coded number with the proper macro.
|
||||
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
Fixes: ac7d69bbc476 ("pmc_agent: Convert the method that queries the port properties.")
|
||||
|
||||
[commit 0fb1be2f5c4d6905f33a2b1c31e7496d52296748 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
pmc_agent.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 6e6627d..623f300 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -338,7 +338,7 @@ int pmc_agent_query_port_properties(struct pmc_agent *node, int timeout,
|
||||
iface[len] = '\0';
|
||||
|
||||
msg_put(msg);
|
||||
- res = 0;
|
||||
+ res = RUN_PMC_OKAY;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,188 @@
|
||||
From 06a6734e3350e4020b4bb7b24a15d43aa42b4ca7 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 17:57:11 -0300
|
||||
Subject: [PATCH 33/47] Implement push notification for TIME_STATUS_NP
|
||||
|
||||
Subscribers to NOTIFY_TIME_SYNC will be notified on every clock
|
||||
synchronization.
|
||||
|
||||
[ RC:
|
||||
- Don't subscribe this in pmc_agent.
|
||||
- Use stdbool/stdint types in event_bitmask_get/set. ]
|
||||
|
||||
Signed-off-by: Juergen Werner <pogojotz@gmx.net>
|
||||
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
|
||||
|
||||
[commit 6d7c090706e76af334185ffcec9cc56d0570e215 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
clock.c | 14 +++++++++-----
|
||||
notification.h | 22 ++++++++++++++++++++++
|
||||
pmc.c | 6 ++++--
|
||||
pmc_agent.c | 2 +-
|
||||
pmc_common.c | 23 +++++++++++++++--------
|
||||
5 files changed, 51 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/clock.c b/clock.c
|
||||
index 437cd1c..f048771 100644
|
||||
--- a/clock.c
|
||||
+++ b/clock.c
|
||||
@@ -243,13 +243,11 @@ static void clock_prune_subscriptions(struct clock *c)
|
||||
void clock_send_notification(struct clock *c, struct ptp_message *msg,
|
||||
enum notification event)
|
||||
{
|
||||
- unsigned int event_pos = event / 8;
|
||||
- uint8_t mask = 1 << (event % 8);
|
||||
struct port *uds = c->uds_port;
|
||||
struct clock_subscriber *s;
|
||||
|
||||
LIST_FOREACH(s, &c->subscribers, list) {
|
||||
- if (!(s->events[event_pos] & mask))
|
||||
+ if (!event_bitmask_get(s->events, event))
|
||||
continue;
|
||||
/* send event */
|
||||
msg->header.sequenceId = htons(s->sequenceId);
|
||||
@@ -1501,7 +1499,9 @@ void clock_notify_event(struct clock *c, enum notification event)
|
||||
int id;
|
||||
|
||||
switch (event) {
|
||||
- /* set id */
|
||||
+ case NOTIFY_TIME_SYNC:
|
||||
+ id = TLV_TIME_STATUS_NP;
|
||||
+ break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -1731,7 +1731,9 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin)
|
||||
c->cur.offsetFromMaster = tmv_to_TimeInterval(c->master_offset);
|
||||
|
||||
if (c->free_running) {
|
||||
- return clock_no_adjust(c, ingress, origin);
|
||||
+ state = clock_no_adjust(c, ingress, origin);
|
||||
+ clock_notify_event(c, NOTIFY_TIME_SYNC);
|
||||
+ return state;
|
||||
}
|
||||
|
||||
offset = tmv_to_nanoseconds(c->master_offset);
|
||||
@@ -1777,6 +1779,8 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t origin)
|
||||
tmv_to_nanoseconds(c->path_delay));
|
||||
}
|
||||
|
||||
+ clock_notify_event(c, NOTIFY_TIME_SYNC);
|
||||
+
|
||||
return state;
|
||||
}
|
||||
|
||||
diff --git a/notification.h b/notification.h
|
||||
index 47c9b56..115f864 100644
|
||||
--- a/notification.h
|
||||
+++ b/notification.h
|
||||
@@ -20,8 +20,30 @@
|
||||
#ifndef HAVE_NOTIFICATION_H
|
||||
#define HAVE_NOTIFICATION_H
|
||||
|
||||
+#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+static inline void event_bitmask_set(uint8_t *bitmask, unsigned int event,
|
||||
+ bool value)
|
||||
+{
|
||||
+ unsigned int event_pos = event / 8;
|
||||
+ uint8_t event_bit = 1 << (event % 8);
|
||||
+
|
||||
+ if (value) {
|
||||
+ bitmask[event_pos] |= event_bit;
|
||||
+ } else {
|
||||
+ bitmask[event_pos] &= ~(event_bit);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline bool event_bitmask_get(uint8_t *bitmask, unsigned int event)
|
||||
+{
|
||||
+ return (bitmask[event / 8] & (1 << (event % 8))) ? true : false;
|
||||
+}
|
||||
+
|
||||
enum notification {
|
||||
NOTIFY_PORT_STATE,
|
||||
+ NOTIFY_TIME_SYNC,
|
||||
};
|
||||
|
||||
#endif
|
||||
diff --git a/pmc.c b/pmc.c
|
||||
index 65d1d61..3678800 100644
|
||||
--- a/pmc.c
|
||||
+++ b/pmc.c
|
||||
@@ -387,9 +387,11 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
|
||||
sen = (struct subscribe_events_np *) mgt->data;
|
||||
fprintf(fp, "SUBSCRIBE_EVENTS_NP "
|
||||
IFMT "duration %hu"
|
||||
- IFMT "NOTIFY_PORT_STATE %s",
|
||||
+ IFMT "NOTIFY_PORT_STATE %s"
|
||||
+ IFMT "NOTIFY_TIME_SYNC %s",
|
||||
sen->duration,
|
||||
- (sen->bitmask[0] & 1 << NOTIFY_PORT_STATE) ? "on" : "off");
|
||||
+ event_bitmask_get(sen->bitmask, NOTIFY_PORT_STATE) ? "on" : "off",
|
||||
+ event_bitmask_get(sen->bitmask, NOTIFY_TIME_SYNC) ? "on" : "off");
|
||||
break;
|
||||
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||
mtd = (struct management_tlv_datum *) mgt->data;
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 623f300..37910b3 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -57,7 +57,7 @@ static void send_subscription(struct pmc_agent *node)
|
||||
|
||||
memset(&sen, 0, sizeof(sen));
|
||||
sen.duration = PMC_SUBSCRIBE_DURATION;
|
||||
- sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
+ event_bitmask_set(sen.bitmask, NOTIFY_PORT_STATE, TRUE);
|
||||
pmc_send_set_action(node->pmc, TLV_SUBSCRIBE_EVENTS_NP, &sen, sizeof(sen));
|
||||
}
|
||||
|
||||
diff --git a/pmc_common.c b/pmc_common.c
|
||||
index a117904..c5cd992 100644
|
||||
--- a/pmc_common.c
|
||||
+++ b/pmc_common.c
|
||||
@@ -149,7 +149,8 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
||||
struct management_tlv_datum mtd;
|
||||
struct subscribe_events_np sen;
|
||||
struct port_ds_np pnp;
|
||||
- char onoff[4] = {0};
|
||||
+ char onoff_port_state[4] = "off";
|
||||
+ char onoff_time_status[4] = "off";
|
||||
|
||||
switch (action) {
|
||||
case GET:
|
||||
@@ -223,16 +224,22 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str)
|
||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
memset(&sen, 0, sizeof(sen));
|
||||
cnt = sscanf(str, " %*s %*s "
|
||||
- "duration %hu "
|
||||
- "NOTIFY_PORT_STATE %3s ",
|
||||
- &sen.duration, onoff);
|
||||
- if (cnt != 2) {
|
||||
- fprintf(stderr, "%s SET needs 2 values\n",
|
||||
+ "duration %hu "
|
||||
+ "NOTIFY_PORT_STATE %3s "
|
||||
+ "NOTIFY_TIME_SYNC %3s ",
|
||||
+ &sen.duration,
|
||||
+ onoff_port_state,
|
||||
+ onoff_time_status);
|
||||
+ if (cnt != 3) {
|
||||
+ fprintf(stderr, "%s SET needs 3 values\n",
|
||||
idtab[index].name);
|
||||
break;
|
||||
}
|
||||
- if (!strcasecmp(onoff, "on")) {
|
||||
- sen.bitmask[0] = 1 << NOTIFY_PORT_STATE;
|
||||
+ if (!strcasecmp(onoff_port_state, "on")) {
|
||||
+ event_bitmask_set(sen.bitmask, NOTIFY_PORT_STATE, TRUE);
|
||||
+ }
|
||||
+ if (!strcasecmp(onoff_time_status, "on")) {
|
||||
+ event_bitmask_set(sen.bitmask, NOTIFY_TIME_SYNC, TRUE);
|
||||
}
|
||||
pmc_send_set_action(pmc, code, &sen, sizeof(sen));
|
||||
break;
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,214 @@
|
||||
From babbe47ab091071e16fcd527bf1aad06e5aec377 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 18:16:31 -0300
|
||||
Subject: [PATCH 34/47] clock: Rename UDS variables to read-write.
|
||||
|
||||
In preparation for a new read-only UDS port, rename variables of the
|
||||
current UDS port to make it clear it is read-write, as opposed to
|
||||
read-only.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
[commit 1b781a5a086571859b0cfba687706d8fdc764d7f upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
clock.c | 52 +++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 29 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/clock.c b/clock.c
|
||||
index f048771..d653c33 100644
|
||||
--- a/clock.c
|
||||
+++ b/clock.c
|
||||
@@ -95,7 +95,7 @@ struct clock {
|
||||
struct foreign_clock *best;
|
||||
struct ClockIdentity best_id;
|
||||
LIST_HEAD(ports_head, port) ports;
|
||||
- struct port *uds_port;
|
||||
+ struct port *uds_rw_port;
|
||||
struct pollfd *pollfd;
|
||||
int pollfd_valid;
|
||||
int nports; /* does not include the UDS port */
|
||||
@@ -129,7 +129,7 @@ struct clock {
|
||||
struct clock_stats stats;
|
||||
int stats_interval;
|
||||
struct clockcheck *sanity_check;
|
||||
- struct interface *udsif;
|
||||
+ struct interface *uds_rw_if;
|
||||
LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
|
||||
struct monitor *slave_event_monitor;
|
||||
};
|
||||
@@ -243,7 +243,7 @@ static void clock_prune_subscriptions(struct clock *c)
|
||||
void clock_send_notification(struct clock *c, struct ptp_message *msg,
|
||||
enum notification event)
|
||||
{
|
||||
- struct port *uds = c->uds_port;
|
||||
+ struct port *uds = c->uds_rw_port;
|
||||
struct clock_subscriber *s;
|
||||
|
||||
LIST_FOREACH(s, &c->subscribers, list) {
|
||||
@@ -265,13 +265,13 @@ void clock_destroy(struct clock *c)
|
||||
{
|
||||
struct port *p, *tmp;
|
||||
|
||||
- interface_destroy(c->udsif);
|
||||
+ interface_destroy(c->uds_rw_if);
|
||||
clock_flush_subscriptions(c);
|
||||
LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
|
||||
clock_remove_port(c, p);
|
||||
}
|
||||
monitor_destroy(c->slave_event_monitor);
|
||||
- port_close(c->uds_port);
|
||||
+ port_close(c->uds_rw_port);
|
||||
free(c->pollfd);
|
||||
if (c->clkid != CLOCK_REALTIME) {
|
||||
phc_close(c->clkid);
|
||||
@@ -440,7 +440,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
|
||||
datalen = sizeof(*gsn);
|
||||
break;
|
||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
- if (p != c->uds_port) {
|
||||
+ if (p != c->uds_rw_port) {
|
||||
/* Only the UDS port allowed. */
|
||||
break;
|
||||
}
|
||||
@@ -782,7 +782,7 @@ static int forwarding(struct clock *c, struct port *p)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
- if (p == c->uds_port && ps != PS_FAULTY) {
|
||||
+ if (p == c->uds_rw_port && ps != PS_FAULTY) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1042,20 +1042,20 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
|
||||
/* Configure the UDS. */
|
||||
uds_ifname = config_get_string(config, NULL, "uds_address");
|
||||
- c->udsif = interface_create(uds_ifname);
|
||||
- if (config_set_section_int(config, interface_name(c->udsif),
|
||||
+ c->uds_rw_if = interface_create(uds_ifname);
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
|
||||
"announceReceiptTimeout", 0)) {
|
||||
return NULL;
|
||||
}
|
||||
- if (config_set_section_int(config, interface_name(c->udsif),
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
|
||||
"delay_mechanism", DM_AUTO)) {
|
||||
return NULL;
|
||||
}
|
||||
- if (config_set_section_int(config, interface_name(c->udsif),
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
|
||||
"network_transport", TRANS_UDS)) {
|
||||
return NULL;
|
||||
}
|
||||
- if (config_set_section_int(config, interface_name(c->udsif),
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_rw_if),
|
||||
"delay_filter_length", 1)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1178,14 +1178,15 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
}
|
||||
|
||||
/* Create the UDS interface. */
|
||||
- c->uds_port = port_open(phc_device, phc_index, timestamping, 0, c->udsif, c);
|
||||
- if (!c->uds_port) {
|
||||
+ c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0,
|
||||
+ c->uds_rw_if, c);
|
||||
+ if (!c->uds_rw_port) {
|
||||
pr_err("failed to open the UDS port");
|
||||
return NULL;
|
||||
}
|
||||
clock_fda_changed(c);
|
||||
|
||||
- c->slave_event_monitor = monitor_create(config, c->uds_port);
|
||||
+ c->slave_event_monitor = monitor_create(config, c->uds_rw_port);
|
||||
if (!c->slave_event_monitor) {
|
||||
pr_err("failed to create slave event monitor");
|
||||
return NULL;
|
||||
@@ -1204,7 +1205,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
LIST_FOREACH(p, &c->ports, list) {
|
||||
port_dispatch(p, EV_INITIALIZE, 0);
|
||||
}
|
||||
- port_dispatch(c->uds_port, EV_INITIALIZE, 0);
|
||||
+ port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -1312,7 +1313,7 @@ static void clock_check_pollfd(struct clock *c)
|
||||
clock_fill_pollfd(dest, p);
|
||||
dest += N_CLOCK_PFD;
|
||||
}
|
||||
- clock_fill_pollfd(dest, c->uds_port);
|
||||
+ clock_fill_pollfd(dest, c->uds_rw_port);
|
||||
c->pollfd_valid = 1;
|
||||
}
|
||||
|
||||
@@ -1329,7 +1330,7 @@ static int clock_do_forward_mgmt(struct clock *c,
|
||||
return 0;
|
||||
|
||||
/* Don't forward any requests to the UDS port. */
|
||||
- if (out == c->uds_port) {
|
||||
+ if (out == c->uds_rw_port) {
|
||||
switch (management_action(msg)) {
|
||||
case GET:
|
||||
case SET:
|
||||
@@ -1360,7 +1361,7 @@ static void clock_forward_mgmt_msg(struct clock *c, struct port *p, struct ptp_m
|
||||
pr_err("port %d: management forward failed",
|
||||
port_number(piter));
|
||||
}
|
||||
- if (clock_do_forward_mgmt(c, p, c->uds_port, msg, &msg_ready))
|
||||
+ if (clock_do_forward_mgmt(c, p, c->uds_rw_port, msg, &msg_ready))
|
||||
pr_err("uds port: management forward failed");
|
||||
if (msg_ready) {
|
||||
msg_post_recv(msg, pdulen);
|
||||
@@ -1412,7 +1413,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
clock_management_send_error(p, msg, TLV_WRONG_LENGTH);
|
||||
return changed;
|
||||
}
|
||||
- if (p != c->uds_port) {
|
||||
+ if (p != c->uds_rw_port) {
|
||||
/* Sorry, only allowed on the UDS port. */
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
return changed;
|
||||
@@ -1421,6 +1422,11 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
return changed;
|
||||
break;
|
||||
case COMMAND:
|
||||
+ if (p != c->uds_rw_port) {
|
||||
+ /* Sorry, only allowed on the UDS port. */
|
||||
+ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
+ return changed;
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
return changed;
|
||||
@@ -1428,7 +1434,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
|
||||
switch (mgt->id) {
|
||||
case TLV_PORT_PROPERTIES_NP:
|
||||
- if (p != c->uds_port) {
|
||||
+ if (p != c->uds_rw_port) {
|
||||
/* Only the UDS port allowed. */
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
return 0;
|
||||
@@ -1493,7 +1499,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
|
||||
void clock_notify_event(struct clock *c, enum notification event)
|
||||
{
|
||||
- struct port *uds = c->uds_port;
|
||||
+ struct port *uds = c->uds_rw_port;
|
||||
struct PortIdentity pid = port_identity(uds);
|
||||
struct ptp_message *msg;
|
||||
int id;
|
||||
@@ -1599,7 +1605,7 @@ int clock_poll(struct clock *c)
|
||||
/* Check the UDS port. */
|
||||
for (i = 0; i < N_POLLFD; i++) {
|
||||
if (cur[i].revents & (POLLIN|POLLPRI)) {
|
||||
- event = port_event(c->uds_port, i);
|
||||
+ event = port_event(c->uds_rw_port, i);
|
||||
if (EV_STATE_DECISION_EVENT == event) {
|
||||
c->sde = 1;
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,292 @@
|
||||
From 4af24949b94eda84b4b74d77b9164cf3fe0eccf9 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 12 Jun 2023 18:18:29 -0300
|
||||
Subject: [PATCH 35/47] clock: Add read-only UDS port for monitoring.
|
||||
|
||||
Add a second UDS port to allow untrusted applications to monitor ptp4l.
|
||||
On this "read-only" UDS port disable non-GET actions and forwarding.
|
||||
The path can be configured with the uds_ro_address option (default is
|
||||
/var/run/ptp4lro).
|
||||
|
||||
Forwarding is disabled to limit the access to the local ptp4l instance.
|
||||
|
||||
Subscriptions are not enabled to prevent the applications from making a
|
||||
large number of subscriptions or interfere with applications that have
|
||||
access to the read-write UDS port.
|
||||
|
||||
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
|
||||
|
||||
[commit 6823e077b2466dcc3c7cbce8ab384b0ef9a62811 upstream]
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
clock.c | 72 +++++++++++++++++++++++++++++++++++++--------
|
||||
config.c | 1 +
|
||||
configs/default.cfg | 1 +
|
||||
ptp4l.8 | 6 ++++
|
||||
4 files changed, 67 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/clock.c b/clock.c
|
||||
index d653c33..869e35d 100644
|
||||
--- a/clock.c
|
||||
+++ b/clock.c
|
||||
@@ -96,9 +96,10 @@ struct clock {
|
||||
struct ClockIdentity best_id;
|
||||
LIST_HEAD(ports_head, port) ports;
|
||||
struct port *uds_rw_port;
|
||||
+ struct port *uds_ro_port;
|
||||
struct pollfd *pollfd;
|
||||
int pollfd_valid;
|
||||
- int nports; /* does not include the UDS port */
|
||||
+ int nports; /* does not include the two UDS ports */
|
||||
int last_port_number;
|
||||
int sde;
|
||||
int free_running;
|
||||
@@ -130,6 +131,7 @@ struct clock {
|
||||
int stats_interval;
|
||||
struct clockcheck *sanity_check;
|
||||
struct interface *uds_rw_if;
|
||||
+ struct interface *uds_ro_if;
|
||||
LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
|
||||
struct monitor *slave_event_monitor;
|
||||
};
|
||||
@@ -266,12 +268,14 @@ void clock_destroy(struct clock *c)
|
||||
struct port *p, *tmp;
|
||||
|
||||
interface_destroy(c->uds_rw_if);
|
||||
+ interface_destroy(c->uds_ro_if);
|
||||
clock_flush_subscriptions(c);
|
||||
LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
|
||||
clock_remove_port(c, p);
|
||||
}
|
||||
monitor_destroy(c->slave_event_monitor);
|
||||
port_close(c->uds_rw_port);
|
||||
+ port_close(c->uds_ro_port);
|
||||
free(c->pollfd);
|
||||
if (c->clkid != CLOCK_REALTIME) {
|
||||
phc_close(c->clkid);
|
||||
@@ -441,7 +445,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
|
||||
break;
|
||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
if (p != c->uds_rw_port) {
|
||||
- /* Only the UDS port allowed. */
|
||||
+ /* Only the UDS-RW port allowed. */
|
||||
break;
|
||||
}
|
||||
sen = (struct subscribe_events_np *)tlv->data;
|
||||
@@ -772,6 +776,10 @@ static int clock_utc_correct(struct clock *c, tmv_t ingress)
|
||||
static int forwarding(struct clock *c, struct port *p)
|
||||
{
|
||||
enum port_state ps = port_state(p);
|
||||
+
|
||||
+ if (p == c->uds_ro_port)
|
||||
+ return 0;
|
||||
+
|
||||
switch (ps) {
|
||||
case PS_MASTER:
|
||||
case PS_GRAND_MASTER:
|
||||
@@ -816,7 +824,7 @@ static int clock_add_port(struct clock *c, const char *phc_device,
|
||||
{
|
||||
struct port *p, *piter, *lastp = NULL;
|
||||
|
||||
- if (clock_resize_pollfd(c, c->nports + 1)) {
|
||||
+ if (clock_resize_pollfd(c, c->nports + 2)) {
|
||||
return -1;
|
||||
}
|
||||
p = port_open(phc_device, phc_index, timestamping,
|
||||
@@ -1041,6 +1049,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
}
|
||||
|
||||
/* Configure the UDS. */
|
||||
+
|
||||
uds_ifname = config_get_string(config, NULL, "uds_address");
|
||||
c->uds_rw_if = interface_create(uds_ifname);
|
||||
if (config_set_section_int(config, interface_name(c->uds_rw_if),
|
||||
@@ -1060,6 +1069,25 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ uds_ifname = config_get_string(config, NULL, "uds_ro_address");
|
||||
+ c->uds_ro_if = interface_create(uds_ifname);
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
|
||||
+ "announceReceiptTimeout", 0)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
|
||||
+ "delay_mechanism", DM_AUTO)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
|
||||
+ "network_transport", TRANS_UDS)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (config_set_section_int(config, interface_name(c->uds_ro_if),
|
||||
+ "delay_filter_length", 1)) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
c->config = config;
|
||||
c->free_running = config_get_int(config, NULL, "free_running");
|
||||
c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval");
|
||||
@@ -1177,11 +1205,18 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* Create the UDS interface. */
|
||||
+ /* Create the UDS interfaces. */
|
||||
+
|
||||
c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0,
|
||||
c->uds_rw_if, c);
|
||||
if (!c->uds_rw_port) {
|
||||
- pr_err("failed to open the UDS port");
|
||||
+ pr_err("failed to open the UDS-RW port");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ c->uds_ro_port = port_open(phc_device, phc_index, timestamping, 0,
|
||||
+ c->uds_ro_if, c);
|
||||
+ if (!c->uds_ro_port) {
|
||||
+ pr_err("failed to open the UDS-RO port");
|
||||
return NULL;
|
||||
}
|
||||
clock_fda_changed(c);
|
||||
@@ -1206,6 +1241,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||
port_dispatch(p, EV_INITIALIZE, 0);
|
||||
}
|
||||
port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
|
||||
+ port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0);
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -1276,9 +1312,9 @@ static int clock_resize_pollfd(struct clock *c, int new_nports)
|
||||
{
|
||||
struct pollfd *new_pollfd;
|
||||
|
||||
- /* Need to allocate one whole extra block of fds for UDS. */
|
||||
+ /* Need to allocate two whole extra blocks of fds for UDS ports. */
|
||||
new_pollfd = realloc(c->pollfd,
|
||||
- (new_nports + 1) * N_CLOCK_PFD *
|
||||
+ (new_nports + 2) * N_CLOCK_PFD *
|
||||
sizeof(struct pollfd));
|
||||
if (!new_pollfd) {
|
||||
return -1;
|
||||
@@ -1314,6 +1350,8 @@ static void clock_check_pollfd(struct clock *c)
|
||||
dest += N_CLOCK_PFD;
|
||||
}
|
||||
clock_fill_pollfd(dest, c->uds_rw_port);
|
||||
+ dest += N_CLOCK_PFD;
|
||||
+ clock_fill_pollfd(dest, c->uds_ro_port);
|
||||
c->pollfd_valid = 1;
|
||||
}
|
||||
|
||||
@@ -1329,7 +1367,8 @@ static int clock_do_forward_mgmt(struct clock *c,
|
||||
if (in == out || !forwarding(c, out))
|
||||
return 0;
|
||||
|
||||
- /* Don't forward any requests to the UDS port. */
|
||||
+ /* Don't forward any requests to the UDS-RW port
|
||||
+ (the UDS-RO port doesn't allow any forwarding). */
|
||||
if (out == c->uds_rw_port) {
|
||||
switch (management_action(msg)) {
|
||||
case GET:
|
||||
@@ -1414,7 +1453,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
return changed;
|
||||
}
|
||||
if (p != c->uds_rw_port) {
|
||||
- /* Sorry, only allowed on the UDS port. */
|
||||
+ /* Sorry, only allowed on the UDS-RW port. */
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
return changed;
|
||||
}
|
||||
@@ -1423,7 +1462,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
break;
|
||||
case COMMAND:
|
||||
if (p != c->uds_rw_port) {
|
||||
- /* Sorry, only allowed on the UDS port. */
|
||||
+ /* Sorry, only allowed on the UDS-RW port. */
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
return changed;
|
||||
}
|
||||
@@ -1435,7 +1474,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||
switch (mgt->id) {
|
||||
case TLV_PORT_PROPERTIES_NP:
|
||||
if (p != c->uds_rw_port) {
|
||||
- /* Only the UDS port allowed. */
|
||||
+ /* Only the UDS-RW port allowed. */
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
@@ -1548,7 +1587,7 @@ int clock_poll(struct clock *c)
|
||||
struct port *p;
|
||||
|
||||
clock_check_pollfd(c);
|
||||
- cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1);
|
||||
+ cnt = poll(c->pollfd, (c->nports + 2) * N_CLOCK_PFD, -1);
|
||||
if (cnt < 0) {
|
||||
if (EINTR == errno) {
|
||||
return 0;
|
||||
@@ -1602,7 +1641,7 @@ int clock_poll(struct clock *c)
|
||||
cur += N_CLOCK_PFD;
|
||||
}
|
||||
|
||||
- /* Check the UDS port. */
|
||||
+ /* Check the UDS ports. */
|
||||
for (i = 0; i < N_POLLFD; i++) {
|
||||
if (cur[i].revents & (POLLIN|POLLPRI)) {
|
||||
event = port_event(c->uds_rw_port, i);
|
||||
@@ -1611,6 +1650,13 @@ int clock_poll(struct clock *c)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ cur += N_CLOCK_PFD;
|
||||
+ for (i = 0; i < N_POLLFD; i++) {
|
||||
+ if (cur[i].revents & (POLLIN|POLLPRI)) {
|
||||
+ event = port_event(c->uds_ro_port, i);
|
||||
+ /* sde is not expected on the UDS-RO port */
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (c->sde) {
|
||||
handle_state_decision_event(c);
|
||||
diff --git a/config.c b/config.c
|
||||
index fea7f67..d45e948 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -323,6 +323,7 @@ struct config_item config_tab[] = {
|
||||
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
|
||||
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
|
||||
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
|
||||
+ GLOB_ITEM_STR("uds_ro_address", "/var/run/ptp4lro"),
|
||||
PORT_ITEM_INT("unicast_listen", 0, 0, 1),
|
||||
PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX),
|
||||
PORT_ITEM_INT("unicast_req_duration", 3600, 10, INT_MAX),
|
||||
diff --git a/configs/default.cfg b/configs/default.cfg
|
||||
index 8c19129..d5bab7d 100644
|
||||
--- a/configs/default.cfg
|
||||
+++ b/configs/default.cfg
|
||||
@@ -90,6 +90,7 @@ p2p_dst_mac 01:80:C2:00:00:0E
|
||||
udp_ttl 1
|
||||
udp6_scope 0x0E
|
||||
uds_address /var/run/ptp4l
|
||||
+uds_ro_address /var/run/ptp4lro
|
||||
#
|
||||
# Default interface options
|
||||
#
|
||||
diff --git a/ptp4l.8 b/ptp4l.8
|
||||
index b179b81..f9bd228 100644
|
||||
--- a/ptp4l.8
|
||||
+++ b/ptp4l.8
|
||||
@@ -615,6 +615,12 @@ is only relevant with IPv6 transport. See RFC 4291. The default is
|
||||
Specifies the address of the UNIX domain socket for receiving local
|
||||
management messages. The default is /var/run/ptp4l.
|
||||
.TP
|
||||
+.B uds_ro_address
|
||||
+Specifies the address of the second UNIX domain socket for receiving local
|
||||
+management messages, which is restricted to GET actions and does not forward
|
||||
+messages to other ports. Access to this socket can be given to untrusted
|
||||
+applications for monitoring purposes. The default is /var/run/ptp4lro.
|
||||
+.TP
|
||||
.B dscp_event
|
||||
Defines the Differentiated Services Codepoint (DSCP) to be used for PTP
|
||||
event messages. Must be a value between 0 and 63. There are several media
|
||||
--
|
||||
2.25.1
|
||||
|
1388
base/linuxptp/debian/patches/0036-Rename-management-ID-macros.patch
Normal file
1388
base/linuxptp/debian/patches/0036-Rename-management-ID-macros.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,764 @@
|
||||
From 2a6ddfe1b9700ce8e0c62da8a7a4f2edcd4e1cad Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Sun, 18 Jun 2023 20:58:34 -0300
|
||||
Subject: [PATCH 37/47] Enhance phc2sys to accept multiple ptp4l inputs
|
||||
|
||||
A new configuration option called ha_enabled was created. When it is set 1
|
||||
multiple ptp4l inputs are accepted and the high availability algorithms
|
||||
are enabled.
|
||||
|
||||
In addition to ha_enabled 1 a set of interfaces must also be provided.
|
||||
Each interface is one-to-one mapped to a clock source, and must be
|
||||
associated to an unique ptp4l instance using the ha_uds_address
|
||||
configuration option.
|
||||
|
||||
For example:
|
||||
|
||||
ha_enabled 1
|
||||
|
||||
[ens1f1]
|
||||
ha_uds_address /var/run/ptp4l-ptp-inst1
|
||||
|
||||
[ens1f2]
|
||||
ha_uds_address /var/run/ptp4l-ptp-inst2
|
||||
|
||||
A maximum of 128 interfaces is supported.
|
||||
|
||||
Regression: verify non HA phc2sys configuration
|
||||
PASS: Verify auto configuration is still accepted.
|
||||
PASS: Verify manual configuration with a single clock is still accepted.
|
||||
PASS: Verify mix of manual and auto configuration is denied.
|
||||
PASS: Verify manual configuration with zero clock sources is denied.
|
||||
|
||||
Test Plan: verify HA configuration
|
||||
PASS: Verify HA is disabled by default.
|
||||
PASS: Verify HA configuration with 1 or more clock source is accepted.
|
||||
PASS: Verify ha_uds_address default value.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek <andrefernandozanella.kantek@windriver.com>
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
|
||||
[commit 705fe12b294216c7b5797f48d83ff97fcc076294 upstream]
|
||||
[commit e730f006cb56ac55932220c1afff5470de875200 upstream]
|
||||
[commit df8fa0492771f6babb75254619337edb6041daea upstream]
|
||||
[commit 0201340fa5abc17634bfb4d0b2a386d218d3095b upstream]
|
||||
[commit dd7400f4eb548dfb2acfb6ebaf53a6d77b9c5da2 upstream]
|
||||
[commit 904fb44ecebd448f9b2952dd287ac2b5db8249db upstream]
|
||||
[commit 56dcd671d5241b589dc44b776fec9b2752496477 upstream]
|
||||
[commit 7e5617afe8837b77629cc04c9e3abb38ae64678c upstream]
|
||||
[commit 5ea8af40b8b5e4680d8a8e1a19482c28f95ce6b3 upstream]
|
||||
[commit 3d38367a3151845ec543ab9125e2d0a0aefa2f56 upstream]
|
||||
[commit 17a4d6805597fd6ddb911b8246e7b131a42f9191 upstream]
|
||||
[commit 1650d972f4fe9bb39807536df2594d1a85aabf9c upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
config.c | 17 +++
|
||||
config.h | 2 +
|
||||
phc2sys.c | 337 +++++++++++++++++++++++++++++++++++++---------------
|
||||
pmc_agent.c | 17 ---
|
||||
pmc_agent.h | 21 +++-
|
||||
uds.c | 19 ++-
|
||||
6 files changed, 294 insertions(+), 119 deletions(-)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index d45e948..b97e5d7 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -250,6 +250,8 @@ struct config_item config_tab[] = {
|
||||
GLOB_ITEM_INT("G.8275.defaultDS.localPriority", 128, 1, UINT8_MAX),
|
||||
PORT_ITEM_INT("G.8275.portDS.localPriority", 128, 1, UINT8_MAX),
|
||||
GLOB_ITEM_INT("gmCapable", 1, 0, 1),
|
||||
+ GLOB_ITEM_INT("ha_enabled", 0, 0, 1),
|
||||
+ PORT_ITEM_STR("ha_uds_address", "/var/run/ptp4l"),
|
||||
GLOB_ITEM_ENU("hwts_filter", HWTS_FILTER_NORMAL, hwts_filter_enu),
|
||||
PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
|
||||
PORT_ITEM_INT("ignore_source_id", 0, 0, 1),
|
||||
@@ -996,6 +998,21 @@ char *config_get_string(struct config *cfg, const char *section,
|
||||
return ci->val.s;
|
||||
}
|
||||
|
||||
+unsigned int config_get_interfaces(struct config *cfg, char *interfaces[], unsigned int max)
|
||||
+{
|
||||
+ struct interface *iface = NULL;
|
||||
+ unsigned int counter = 0;
|
||||
+
|
||||
+ STAILQ_FOREACH(iface, &cfg->interfaces, list) {
|
||||
+ if (counter == max) {
|
||||
+ pr_err("bug: too many interfaces!");
|
||||
+ return (unsigned int)-1;
|
||||
+ }
|
||||
+ interfaces[counter++] = interface_name(iface);
|
||||
+ }
|
||||
+ return counter;
|
||||
+}
|
||||
+
|
||||
int config_harmonize_onestep(struct config *cfg)
|
||||
{
|
||||
enum timestamp_type tstype = config_get_int(cfg, NULL, "time_stamping");
|
||||
diff --git a/config.h b/config.h
|
||||
index 14d2f64..645fb42 100644
|
||||
--- a/config.h
|
||||
+++ b/config.h
|
||||
@@ -64,6 +64,8 @@ int config_get_int(struct config *cfg, const char *section,
|
||||
char *config_get_string(struct config *cfg, const char *section,
|
||||
const char *option);
|
||||
|
||||
+unsigned int config_get_interfaces(struct config *cfg, char *interfaces[], unsigned int max);
|
||||
+
|
||||
int config_harmonize_onestep(struct config *cfg);
|
||||
|
||||
static inline struct option *config_long_options(struct config *cfg)
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index c9fabd7..a4afe01 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -64,6 +64,12 @@
|
||||
|
||||
#define PHC_PPS_OFFSET_LIMIT 10000000
|
||||
|
||||
+#define MAX_SRC_CLOCKS 128
|
||||
+
|
||||
+#define PORT_INDEX_TO_PORT_ID(port, index) (((((unsigned int) port) & 0xFF) << 8) || (((unsigned int) index) & 0xFF))
|
||||
+#define PORT_ID_TO_PORT(id) ((((unsigned int) id) >> 8) & 0xFF)
|
||||
+#define PORT_ID_TO_INDEX(id) (((unsigned int) id) & 0xFF)
|
||||
+
|
||||
struct clock {
|
||||
LIST_ENTRY(clock) list;
|
||||
LIST_ENTRY(clock) dst_list;
|
||||
@@ -85,6 +91,7 @@ struct clock {
|
||||
struct stats *freq_stats;
|
||||
struct stats *delay_stats;
|
||||
struct clockcheck *sanity_check;
|
||||
+ struct pmc_agent *node;
|
||||
};
|
||||
|
||||
struct port {
|
||||
@@ -103,7 +110,7 @@ struct phc2sys_private {
|
||||
int forced_sync_offset;
|
||||
int kernel_leap;
|
||||
int state_changed;
|
||||
- struct pmc_agent *node;
|
||||
+ LIST_HEAD(pmc_agent_head, pmc_agent) pmc_agents;
|
||||
LIST_HEAD(port_head, port) ports;
|
||||
LIST_HEAD(clock_head, clock) clocks;
|
||||
LIST_HEAD(dst_clock_head, clock) dst_clocks;
|
||||
@@ -260,6 +267,18 @@ static struct port *port_get(struct phc2sys_private *priv, unsigned int number)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct port *port_get_by_clock(struct phc2sys_private *priv, struct clock * clock)
|
||||
+{
|
||||
+ struct port *p, *port = NULL;
|
||||
+ LIST_FOREACH(p, &priv->ports, list) {
|
||||
+ if (p->clock == clock) {
|
||||
+ port = p;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return port;
|
||||
+}
|
||||
+
|
||||
static struct port *port_add(struct phc2sys_private *priv, unsigned int number,
|
||||
char *device)
|
||||
{
|
||||
@@ -293,6 +312,42 @@ static struct port *port_add(struct phc2sys_private *priv, unsigned int number,
|
||||
return p;
|
||||
}
|
||||
|
||||
+static struct pmc_agent *pmc_agent_get(struct phc2sys_private *priv, unsigned int index)
|
||||
+{
|
||||
+ struct pmc_agent *node;
|
||||
+ LIST_FOREACH(node, &priv->pmc_agents, list) {
|
||||
+ if (node->index == index) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+static struct pmc_agent *pmc_agent_add(struct phc2sys_private *priv, unsigned int index)
|
||||
+{
|
||||
+ struct pmc_agent *node = pmc_agent_get(priv, index);
|
||||
+ if (node)
|
||||
+ return node;
|
||||
+
|
||||
+ node = pmc_agent_create();
|
||||
+ if (!node) {
|
||||
+ pr_err("failed to allocate memory for a pmc agent");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ node->index = index;
|
||||
+ LIST_INSERT_HEAD(&priv->pmc_agents, node, list);
|
||||
+ return node;
|
||||
+}
|
||||
+
|
||||
+static void pmc_agent_cleanup(struct phc2sys_private *priv)
|
||||
+{
|
||||
+ struct pmc_agent *node, *tmp;
|
||||
+ LIST_FOREACH_SAFE(node, &priv->pmc_agents, list, tmp) {
|
||||
+ pmc_agent_destroy(node);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
int new_state)
|
||||
{
|
||||
@@ -302,12 +357,17 @@ static void clock_reinit(struct phc2sys_private *priv, struct clock *clock,
|
||||
struct sk_ts_info ts_info;
|
||||
char iface[IFNAMSIZ];
|
||||
clockid_t clkid = CLOCK_INVALID;
|
||||
+ struct pmc_agent *node;
|
||||
+ unsigned int pmc_index;
|
||||
|
||||
LIST_FOREACH(p, &priv->ports, list) {
|
||||
if (p->clock != clock) {
|
||||
continue;
|
||||
}
|
||||
- err = pmc_agent_query_port_properties(priv->node, 1000,
|
||||
+
|
||||
+ pmc_index = PORT_ID_TO_INDEX(p->number);
|
||||
+ node = pmc_agent_get(priv, pmc_index);
|
||||
+ err = pmc_agent_query_port_properties(node, 1000,
|
||||
p->number, &state,
|
||||
×tamping, iface);
|
||||
if (!err) {
|
||||
@@ -638,12 +698,13 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
int64_t pps_offset, phc_offset, phc_delay;
|
||||
uint64_t pps_ts, phc_ts;
|
||||
clockid_t src = priv->master->clkid;
|
||||
+ struct pmc_agent *node = LIST_FIRST(&priv->pmc_agents);
|
||||
|
||||
priv->master->source_label = "pps";
|
||||
|
||||
if (src == CLOCK_INVALID) {
|
||||
/* The sync offset can't be applied with PPS alone. */
|
||||
- pmc_agent_set_sync_offset(priv->node, 0);
|
||||
+ pmc_agent_set_sync_offset(node, 0);
|
||||
} else {
|
||||
enable_pps_output(priv->master->clkid);
|
||||
}
|
||||
@@ -674,7 +735,7 @@ static int do_pps_loop(struct phc2sys_private *priv, struct clock *clock,
|
||||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
- if (pmc_agent_update(priv->node) < 0)
|
||||
+ if (pmc_agent_update(node) < 0)
|
||||
continue;
|
||||
update_clock(priv, clock, pps_offset, pps_ts, -1);
|
||||
}
|
||||
@@ -706,6 +767,7 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
uint64_t ts;
|
||||
int64_t offset, delay;
|
||||
int err;
|
||||
+ struct pmc_agent *node = NULL;
|
||||
|
||||
interval.tv_sec = priv->phc_interval;
|
||||
interval.tv_nsec = (priv->phc_interval - interval.tv_sec) * 1e9;
|
||||
@@ -713,22 +775,28 @@ static int do_loop(struct phc2sys_private *priv, int subscriptions)
|
||||
while (is_running()) {
|
||||
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
|
||||
|
||||
- if (pmc_agent_update(priv->node) < 0) {
|
||||
- continue;
|
||||
- }
|
||||
+ LIST_FOREACH(node, &priv->pmc_agents, list) {
|
||||
+ if (pmc_agent_update(node) < 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (subscriptions) {
|
||||
- run_pmc_events(priv->node);
|
||||
- if (priv->state_changed) {
|
||||
- /* force getting offset, as it may have
|
||||
- * changed after the port state change */
|
||||
- if (pmc_agent_query_utc_offset(priv->node, 1000)) {
|
||||
- pr_err("failed to get UTC offset");
|
||||
- continue;
|
||||
+ if (subscriptions) {
|
||||
+ run_pmc_events(node);
|
||||
+ if (priv->state_changed) {
|
||||
+ /* force getting offset, as it may have
|
||||
+ * changed after the port state change */
|
||||
+ if (pmc_agent_query_utc_offset(node, 1000)) {
|
||||
+ pr_err("failed to get UTC offset");
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
- reconfigure(priv);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (subscriptions && priv->state_changed) {
|
||||
+ reconfigure(priv);
|
||||
+ }
|
||||
+
|
||||
if (!priv->master)
|
||||
continue;
|
||||
|
||||
@@ -859,55 +927,65 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
struct clock *clock;
|
||||
struct port *port;
|
||||
unsigned int i;
|
||||
+ struct pmc_agent *node = NULL;
|
||||
+ unsigned int retries, port_number;
|
||||
|
||||
- while (1) {
|
||||
- if (!is_running()) {
|
||||
- return -1;
|
||||
- }
|
||||
- err = pmc_agent_query_dds(priv->node, 1000);
|
||||
- if (!err) {
|
||||
- break;
|
||||
- }
|
||||
- if (err == -ETIMEDOUT) {
|
||||
- pr_notice("Waiting for ptp4l...");
|
||||
- } else {
|
||||
- return -1;
|
||||
+ LIST_FOREACH(node, &priv->pmc_agents, list) {
|
||||
+ retries = 0;
|
||||
+ while(retries < 10) {
|
||||
+ if (!is_running()) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ err = pmc_agent_query_dds(node, 1000);
|
||||
+ if (!err) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ pr_notice("Waiting for ptp4l...");
|
||||
+ retries++;
|
||||
+ } else {
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
|
||||
- number_ports = pmc_agent_get_number_ports(priv->node);
|
||||
- if (number_ports <= 0) {
|
||||
- pr_err("failed to get number of ports");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- err = pmc_agent_subscribe(priv->node, 1000);
|
||||
- if (err) {
|
||||
- pr_err("failed to subscribe");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- for (i = 1; i <= number_ports; i++) {
|
||||
- err = pmc_agent_query_port_properties(priv->node, 1000, i,
|
||||
- &state, ×tamping,
|
||||
- iface);
|
||||
- if (err == -ENODEV) {
|
||||
- /* port does not exist, ignore the port */
|
||||
+ number_ports = pmc_agent_get_number_ports(node);
|
||||
+ if (number_ports <= 0) {
|
||||
+ pr_err("failed to get number of ports");
|
||||
continue;
|
||||
}
|
||||
+
|
||||
+ err = pmc_agent_subscribe(node, 1000);
|
||||
if (err) {
|
||||
- pr_err("failed to get port properties");
|
||||
- return -1;
|
||||
- }
|
||||
- if (timestamping == TS_SOFTWARE) {
|
||||
- /* ignore ports with software time stamping */
|
||||
+ pr_err("failed to subscribe");
|
||||
continue;
|
||||
}
|
||||
- port = port_add(priv, i, iface);
|
||||
- if (!port)
|
||||
- return -1;
|
||||
- port->state = normalize_state(state);
|
||||
+
|
||||
+ for (i = 1; i <= number_ports; i++) {
|
||||
+ err = pmc_agent_query_port_properties(node, 1000, i,
|
||||
+ &state, ×tamping,
|
||||
+ iface);
|
||||
+ if (err == -ENODEV) {
|
||||
+ /* port does not exist, ignore the port */
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (err) {
|
||||
+ pr_err("failed to get port properties");
|
||||
+ break;
|
||||
+ }
|
||||
+ if (timestamping == TS_SOFTWARE) {
|
||||
+ /* ignore ports with software time stamping */
|
||||
+ continue;
|
||||
+ }
|
||||
+ port_number = PORT_INDEX_TO_PORT_ID(i, node->index);
|
||||
+ port = port_add(priv, port_number, iface);
|
||||
+ if (!port)
|
||||
+ return -1;
|
||||
+ port->state = normalize_state(state);
|
||||
+ /* map clock to pmc agent node */
|
||||
+ port->clock->node = node;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
if (LIST_EMPTY(&priv->clocks)) {
|
||||
pr_err("no suitable ports available");
|
||||
return -1;
|
||||
@@ -926,9 +1004,11 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
}
|
||||
|
||||
/* get initial offset */
|
||||
- if (pmc_agent_query_utc_offset(priv->node, 1000)) {
|
||||
- pr_err("failed to get UTC offset");
|
||||
- return -1;
|
||||
+ LIST_FOREACH(node, &priv->pmc_agents, list) {
|
||||
+ if (pmc_agent_query_utc_offset(node, 1000)) {
|
||||
+ pr_err("failed to get UTC offset");
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -937,9 +1017,12 @@ static int auto_init_ports(struct phc2sys_private *priv, int add_rt)
|
||||
static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
int64_t offset, uint64_t ts)
|
||||
{
|
||||
- int clock_leap, node_leap = pmc_agent_get_leap(priv->node);
|
||||
+ int clock_leap, node_leap;
|
||||
+ struct pmc_agent *node = priv->master->node;
|
||||
+
|
||||
+ node_leap = pmc_agent_get_leap(node);
|
||||
|
||||
- clock->sync_offset = pmc_agent_get_sync_offset(priv->node);
|
||||
+ clock->sync_offset = pmc_agent_get_sync_offset(node);
|
||||
|
||||
if ((node_leap || clock->leap_set) &&
|
||||
clock->is_utc != priv->master->is_utc) {
|
||||
@@ -980,7 +1063,7 @@ static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
}
|
||||
}
|
||||
|
||||
- if (pmc_agent_utc_offset_traceable(priv->node) &&
|
||||
+ if (pmc_agent_utc_offset_traceable(node) &&
|
||||
clock->utc_offset_set != clock->sync_offset) {
|
||||
if (clock->clkid == CLOCK_REALTIME)
|
||||
sysclk_set_tai_offset(clock->sync_offset);
|
||||
@@ -1034,7 +1117,8 @@ static void usage(char *progname)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
- char *config = NULL, *dst_name = NULL, *progname, *src_name = NULL;
|
||||
+ char *config = NULL, *dst_name = NULL, *progname;
|
||||
+ char *src_names[MAX_SRC_CLOCKS];
|
||||
char uds_local[MAX_IFNAME_SIZE + 1];
|
||||
int autocfg = 0, c, domain_number = 0, index, ntpshm_segment, offset;
|
||||
int pps_fd = -1, print_level = LOG_INFO, r = -1, rt = 0;
|
||||
@@ -1047,7 +1131,11 @@ int main(int argc, char *argv[])
|
||||
struct phc2sys_private priv = {
|
||||
.phc_readings = 5,
|
||||
.phc_interval = 1.0,
|
||||
+ .master = NULL,
|
||||
};
|
||||
+ struct pmc_agent *node = NULL;
|
||||
+ unsigned int i, src_cnt = 0;
|
||||
+ int ha_enabled = 0;
|
||||
|
||||
handle_term_signals();
|
||||
|
||||
@@ -1055,8 +1143,8 @@ int main(int argc, char *argv[])
|
||||
if (!cfg) {
|
||||
return -1;
|
||||
}
|
||||
- priv.node = pmc_agent_create();
|
||||
- if (!priv.node) {
|
||||
+ node = pmc_agent_add(&priv, 0);
|
||||
+ if (!node) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1102,7 +1190,11 @@ int main(int argc, char *argv[])
|
||||
"'-i' has been deprecated. please use '-s' instead.\n");
|
||||
/* fallthrough */
|
||||
case 's':
|
||||
- src_name = strdup(optarg);
|
||||
+ if (src_cnt == MAX_SRC_CLOCKS) {
|
||||
+ fprintf(stderr, "too many source clocks\n");
|
||||
+ goto bad_usage;
|
||||
+ }
|
||||
+ src_names[src_cnt++] = optarg;
|
||||
break;
|
||||
case 'E':
|
||||
if (!strcasecmp(optarg, "pi")) {
|
||||
@@ -1153,7 +1245,7 @@ int main(int argc, char *argv[])
|
||||
if (get_arg_val_i(c, optarg, &offset, INT_MIN, INT_MAX)) {
|
||||
goto end;
|
||||
}
|
||||
- pmc_agent_set_sync_offset(priv.node, offset);
|
||||
+ pmc_agent_set_sync_offset(node, offset);
|
||||
priv.forced_sync_offset = -1;
|
||||
break;
|
||||
case 'L':
|
||||
@@ -1241,12 +1333,22 @@ int main(int argc, char *argv[])
|
||||
return c;
|
||||
}
|
||||
|
||||
- if (autocfg && (src_name || dst_name || pps_fd >= 0 || wait_sync || priv.forced_sync_offset)) {
|
||||
+ if (src_cnt == 0) {
|
||||
+ /* get the source interface list from configuration file */
|
||||
+ src_cnt = config_get_interfaces(cfg, src_names, MAX_SRC_CLOCKS);
|
||||
+ if (src_cnt == (unsigned int)-1) {
|
||||
+ fprintf(stderr, "too many interfaces in configuration file\n");
|
||||
+ fprintf(stderr, "maximum number of interfaces is %u\n", MAX_SRC_CLOCKS);
|
||||
+ goto bad_usage;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (autocfg && (src_cnt > 0 || dst_name || pps_fd >= 0 || wait_sync || priv.forced_sync_offset)) {
|
||||
fprintf(stderr,
|
||||
"autoconfiguration cannot be mixed with manual config options.\n");
|
||||
goto bad_usage;
|
||||
}
|
||||
- if (!autocfg && pps_fd < 0 && !src_name) {
|
||||
+ if (!autocfg && pps_fd < 0 && src_cnt == 0) {
|
||||
fprintf(stderr,
|
||||
"autoconfiguration or valid source clock must be selected.\n");
|
||||
goto bad_usage;
|
||||
@@ -1282,7 +1384,7 @@ int main(int argc, char *argv[])
|
||||
getpid());
|
||||
|
||||
if (autocfg) {
|
||||
- if (init_pmc_node(cfg, priv.node, uds_local,
|
||||
+ if (init_pmc_node(cfg, node, uds_local,
|
||||
phc2sys_recv_subscribed, &priv))
|
||||
goto end;
|
||||
if (auto_init_ports(&priv, rt) < 0)
|
||||
@@ -1291,15 +1393,26 @@ int main(int argc, char *argv[])
|
||||
goto end;
|
||||
}
|
||||
|
||||
- src = clock_add(&priv, src_name);
|
||||
- free(src_name);
|
||||
- if (!src) {
|
||||
- fprintf(stderr,
|
||||
- "valid source clock must be selected.\n");
|
||||
+ ha_enabled = config_get_int(cfg, NULL, "ha_enabled");
|
||||
+ if (!ha_enabled && src_cnt > 1) {
|
||||
+ fprintf(stderr, "too many source clocks\n");
|
||||
+ fprintf(stderr, "Use 'ha_enabled 1' to accept more than one source clocks\n");
|
||||
goto bad_usage;
|
||||
}
|
||||
- src->state = PS_SLAVE;
|
||||
- priv.master = src;
|
||||
+
|
||||
+ for (i = 0; i < src_cnt; ++i) {
|
||||
+ src = clock_add(&priv, src_names[i]);
|
||||
+ if (!src) {
|
||||
+ fprintf(stderr,
|
||||
+ "invalid source clock '%s'.\n", src_names[i]);
|
||||
+ goto bad_usage;
|
||||
+ }
|
||||
+ src->state = PS_SLAVE;
|
||||
+ /* select the first clock */
|
||||
+ if (priv.master == NULL) {
|
||||
+ priv.master = src;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
dst = clock_add(&priv, dst_name ? dst_name : "CLOCK_REALTIME");
|
||||
free(dst_name);
|
||||
@@ -1320,32 +1433,58 @@ int main(int argc, char *argv[])
|
||||
r = -1;
|
||||
|
||||
if (wait_sync) {
|
||||
- if (init_pmc_node(cfg, priv.node, uds_local,
|
||||
- phc2sys_recv_subscribed, &priv))
|
||||
- goto end;
|
||||
+ i = 0;
|
||||
+ for (src = LIST_FIRST(&priv.clocks);
|
||||
+ src != NULL;
|
||||
+ src = LIST_NEXT(src, list)) {
|
||||
|
||||
- while (is_running()) {
|
||||
- r = run_pmc_wait_sync(priv.node, 1000);
|
||||
- if (r < 0)
|
||||
- goto end;
|
||||
- if (r > 0)
|
||||
- break;
|
||||
- else
|
||||
- pr_notice("Waiting for ptp4l...");
|
||||
- }
|
||||
+ /* skip dst clock */
|
||||
+ if (src == dst) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (!priv.forced_sync_offset) {
|
||||
- r = pmc_agent_query_utc_offset(priv.node, 1000);
|
||||
- if (r) {
|
||||
- pr_err("failed to get UTC offset");
|
||||
+ if (i > 0) {
|
||||
+ node = pmc_agent_add(&priv, i);
|
||||
+ if (!node)
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ /* uds local is formated '/var/run/phc2sys.<pid>.<source_interface>' */
|
||||
+ snprintf(uds_local, sizeof(uds_local), "/var/run/phc2sys.%d.%s",
|
||||
+ getpid(), src->device);
|
||||
+
|
||||
+ if (init_pmc_node(cfg, node, uds_local,
|
||||
+ phc2sys_recv_subscribed, &priv))
|
||||
goto end;
|
||||
+
|
||||
+ /* map clock to pmc agent node */
|
||||
+ src->node = node;
|
||||
+
|
||||
+ while (is_running()) {
|
||||
+ r = run_pmc_wait_sync(node, 1000);
|
||||
+ if (r < 0)
|
||||
+ goto end;
|
||||
+ if (r > 0)
|
||||
+ break;
|
||||
+ else
|
||||
+ pr_notice("Waiting for ptp4l...");
|
||||
+ }
|
||||
+
|
||||
+ if (!priv.forced_sync_offset) {
|
||||
+ r = pmc_agent_query_utc_offset(node, 1000);
|
||||
+ if (r) {
|
||||
+ pr_err("failed to get UTC offset");
|
||||
+ goto end;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (priv.forced_sync_offset ||
|
||||
+ (src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
+ src->clkid == CLOCK_INVALID) {
|
||||
+ pmc_agent_disable(node);
|
||||
}
|
||||
- }
|
||||
|
||||
- if (priv.forced_sync_offset ||
|
||||
- (src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
- src->clkid == CLOCK_INVALID) {
|
||||
- pmc_agent_disable(priv.node);
|
||||
+ ++i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1359,7 +1498,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
end:
|
||||
- pmc_agent_destroy(priv.node);
|
||||
+ pmc_agent_cleanup(&priv);
|
||||
clock_cleanup(&priv);
|
||||
port_cleanup(&priv);
|
||||
config_destroy(cfg);
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index 3034f65..d13f569 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -34,23 +34,6 @@
|
||||
* renewed.
|
||||
*/
|
||||
|
||||
-struct pmc_agent {
|
||||
- struct pmc *pmc;
|
||||
- uint64_t pmc_last_update;
|
||||
-
|
||||
- struct defaultDS dds;
|
||||
- bool dds_valid;
|
||||
- int leap;
|
||||
- int pmc_ds_requested;
|
||||
- bool stay_subscribed;
|
||||
- int sync_offset;
|
||||
- int utc_offset_traceable;
|
||||
-
|
||||
- /* Callback on message reception */
|
||||
- pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
- void *recv_context;
|
||||
-};
|
||||
-
|
||||
static void send_subscription(struct pmc_agent *node)
|
||||
{
|
||||
struct subscribe_events_np sen;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index dd34d30..5f25984 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -26,11 +26,28 @@
|
||||
|
||||
#include "pmc_common.h"
|
||||
|
||||
-struct pmc_agent;
|
||||
-
|
||||
typedef int pmc_node_recv_subscribed_t(void *context, struct ptp_message *msg,
|
||||
int excluded);
|
||||
|
||||
+struct pmc_agent {
|
||||
+ LIST_ENTRY(pmc_agent) list;
|
||||
+ struct pmc *pmc;
|
||||
+ uint64_t pmc_last_update;
|
||||
+
|
||||
+ struct defaultDS dds;
|
||||
+ bool dds_valid;
|
||||
+ int leap;
|
||||
+ int pmc_ds_requested;
|
||||
+ bool stay_subscribed;
|
||||
+ int sync_offset;
|
||||
+ int utc_offset_traceable;
|
||||
+ unsigned int index;
|
||||
+
|
||||
+ /* Callback on message reception */
|
||||
+ pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
+ void *recv_context;
|
||||
+};
|
||||
+
|
||||
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_wait_sync(struct pmc_agent *agent, int timeout);
|
||||
diff --git a/uds.c b/uds.c
|
||||
index 641a672..57d4796 100644
|
||||
--- a/uds.c
|
||||
+++ b/uds.c
|
||||
@@ -55,11 +55,13 @@ static int uds_close(struct transport *t, struct fdarray *fda)
|
||||
static int uds_open(struct transport *t, struct interface *iface, struct fdarray *fda,
|
||||
enum timestamp_type tt)
|
||||
{
|
||||
- char *uds_path = config_get_string(t->cfg, NULL, "uds_address");
|
||||
+ char *uds_path = NULL;
|
||||
struct uds *uds = container_of(t, struct uds, t);
|
||||
const char *name = interface_name(iface);
|
||||
struct sockaddr_un sa;
|
||||
int fd, err;
|
||||
+ char *point = NULL, *source = NULL;
|
||||
+ int ha_enabled = config_get_int(t->cfg, NULL, "ha_enabled");
|
||||
|
||||
fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
@@ -82,6 +84,21 @@ static int uds_open(struct transport *t, struct interface *iface, struct fdarray
|
||||
/* For client use, pre load the server path. */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_LOCAL;
|
||||
+
|
||||
+ if (!ha_enabled) {
|
||||
+ uds_path = config_get_string(t->cfg, NULL, "uds_address");
|
||||
+ } else {
|
||||
+ /* The interface name is formated as '/var/run/phc2sys.<pid>.<source>'.
|
||||
+ The last item is the source interface. */
|
||||
+ point = strtok(name, ".");
|
||||
+ while(point != NULL) {
|
||||
+ source = point;
|
||||
+ point = strtok(NULL, ".");
|
||||
+ }
|
||||
+
|
||||
+ uds_path = config_get_string(t->cfg, source, "ha_uds_address");
|
||||
+ }
|
||||
+
|
||||
strncpy(sa.sun_path, uds_path, sizeof(sa.sun_path) - 1);
|
||||
uds->address.sun = sa;
|
||||
uds->address.len = sizeof(sa);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,441 @@
|
||||
From 142b30b1f996a5bd48f0edc9b5fb0f51af0b97fd Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Tue, 4 Jul 2023 17:27:50 -0300
|
||||
Subject: [PATCH 38/47] Best source selection algorithm
|
||||
|
||||
An algorithm to select the best available clock and use it
|
||||
as clock source.
|
||||
|
||||
A new set of configuration options was introduced to control
|
||||
the clock requirements. The clock which fails to match the
|
||||
requirements is discarded.
|
||||
|
||||
If a single clock matches the requirements, it is selected
|
||||
as source.
|
||||
|
||||
If one or more clock match requirements, the clock with the highest
|
||||
priority is selected. In case of tie, the 1st configured clock is
|
||||
selected.
|
||||
|
||||
And if no clock match requirements, the clock with the best local
|
||||
clock class is selected.
|
||||
|
||||
The ha_priority option is an interface setting used to configure
|
||||
the clock priority. The lowest priority is 0 and the highest is 254,
|
||||
and the default value is 0.
|
||||
|
||||
The ha_min_local_clockClass option is a global setting for the minimal
|
||||
local clock class requirement. It ranges from 6 to 255 and its default
|
||||
is 135.
|
||||
|
||||
The ha_min_clockAccuracy option is a global setting for the minimal
|
||||
clock accuracy requirement. It ranges from 0x00 to 0xff and its default
|
||||
is 0xfe.
|
||||
|
||||
The ha_min_offsetScaledLogVariance is a global setting for the minimal
|
||||
offset scaled log variance. It ranges from 0 to 65535 and its default
|
||||
is 65535.
|
||||
|
||||
The ha_timeTraceable is a global setting to enable or disable
|
||||
the time traceable verification. When it's set the clock
|
||||
which time is not traceable is discarded.
|
||||
|
||||
The ha_frequencyTraceable is a global setting to enable or disable
|
||||
the frequency traceable verification. When it's set the clock
|
||||
which frequency is not traceable is discarded.
|
||||
|
||||
The ha_min_gm_ClockClass is a global setting for the minimal
|
||||
GM clock class requirement. It ranges from 6 to 255 and its
|
||||
default is 135.
|
||||
|
||||
Test Plan: clock selection algorithm
|
||||
PASS: Verify clock is discarded when local clock class doesn't match
|
||||
requirements.
|
||||
PASS: Verify clock is discarded when local clock accuracy doesn't match
|
||||
requirements.
|
||||
PASS: Verify clock is discarded when local offset scaled log variance doesn't
|
||||
match requirements.
|
||||
PASS: Verify clock is discarded when time traceable verification is set 1 and
|
||||
the clock hasn't time traceable flag set.
|
||||
PASS: Verify clock is discarded when frequency traceable verification is set 1
|
||||
and the clock hasn't frequency traceable flag set.
|
||||
PASS: Verify clock is discarded when GM clock class doesn't match requirements.
|
||||
PASS: Verify clock is accepted when time traceable verification is set 0 even
|
||||
when clock hasn't time traceable flag set.
|
||||
PASS: Verify clock is accepted when frequency traceable verification is set 0
|
||||
even when clock hasn't frequency traceable flag set.
|
||||
PASS: Verify the highest priority clock is selected when one or more clock
|
||||
match the requirements.
|
||||
PASS: Verify the 1st configured clock is selected when one or more clock of the
|
||||
same priority match the requirements.
|
||||
PASS: Verify the clock with highest local clock class is selected when no clock
|
||||
match the requirements.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek <andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 1c10dd42b32388c2e708ad249dd1f193e7208155 upstream]
|
||||
[commit 373c4fd50aaf52540d3eeb8f38f3e07307dea3a3 upstream]
|
||||
[commit 279d5b6e7f88876ce00f1e87faba65c7cd6a90b0 upstream]
|
||||
[commit 00d9ad798b1f700faefa0b5d4074c46f8ae87ef4 upstream]
|
||||
[commit 1407a51d8000ca7df18ba67d611a761abb6f77f8 upstream]
|
||||
[commit e0c1c7b64f7af8002092c01e023f524bfcc39f8b upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
config.c | 7 ++
|
||||
phc2sys.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
pmc_agent.c | 20 +++++
|
||||
pmc_agent.h | 13 +++
|
||||
4 files changed, 271 insertions(+)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index b97e5d7..8ce5f6c 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -250,7 +250,14 @@ struct config_item config_tab[] = {
|
||||
GLOB_ITEM_INT("G.8275.defaultDS.localPriority", 128, 1, UINT8_MAX),
|
||||
PORT_ITEM_INT("G.8275.portDS.localPriority", 128, 1, UINT8_MAX),
|
||||
GLOB_ITEM_INT("gmCapable", 1, 0, 1),
|
||||
+ GLOB_ITEM_INT("ha_frequencyTraceable", 0, 0, 1),
|
||||
GLOB_ITEM_INT("ha_enabled", 0, 0, 1),
|
||||
+ GLOB_ITEM_INT("ha_min_clockAccuracy", 0xfe, 0, 0xff),
|
||||
+ GLOB_ITEM_INT("ha_min_gm_ClockClass", 135, 6, 255),
|
||||
+ GLOB_ITEM_INT("ha_min_local_clockClass", 135, 6, 255),
|
||||
+ GLOB_ITEM_INT("ha_min_offsetScaledLogVariance", 65535, 0, 65535),
|
||||
+ PORT_ITEM_INT("ha_priority", 0, 0, 255),
|
||||
+ GLOB_ITEM_INT("ha_timeTraceable", 0, 0, 1),
|
||||
PORT_ITEM_STR("ha_uds_address", "/var/run/ptp4l"),
|
||||
GLOB_ITEM_ENU("hwts_filter", HWTS_FILTER_NORMAL, hwts_filter_enu),
|
||||
PORT_ITEM_INT("hybrid_e2e", 0, 0, 1),
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index a4afe01..d148d62 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -73,6 +73,7 @@
|
||||
struct clock {
|
||||
LIST_ENTRY(clock) list;
|
||||
LIST_ENTRY(clock) dst_list;
|
||||
+ LIST_ENTRY(clock) good_list;
|
||||
clockid_t clkid;
|
||||
int phc_index;
|
||||
int sysoff_method;
|
||||
@@ -1073,6 +1074,232 @@ static int clock_handle_leap(struct phc2sys_private *priv, struct clock *clock,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static struct clock* startup_select_clock(struct phc2sys_private *priv, struct config *cfg)
|
||||
+{
|
||||
+ struct clock *clock = NULL, *best = NULL;
|
||||
+ LIST_HEAD(head, clock) good_clocks;
|
||||
+ int clock_priority, highest_priority;
|
||||
+ int min_local_clock_class, min_gm_clock_class, clock_class, lowest_clock_class;
|
||||
+ int err;
|
||||
+ unsigned int min_clock_accuracy, min_offset_scaled_log_variance, retries;
|
||||
+ bool check_time_traceable, check_freq_traceable;
|
||||
+
|
||||
+ LIST_INIT(&good_clocks);
|
||||
+
|
||||
+ /* get requirements */
|
||||
+ min_local_clock_class = config_get_int(cfg, NULL, "ha_min_local_clockClass");
|
||||
+ min_clock_accuracy = config_get_int(cfg, NULL, "ha_min_clockAccuracy");
|
||||
+ min_offset_scaled_log_variance = config_get_int(cfg, NULL, "ha_min_offsetScaledLogVariance");
|
||||
+ check_time_traceable = config_get_int(cfg, NULL, "ha_timeTraceable");
|
||||
+ check_freq_traceable = config_get_int(cfg, NULL, "ha_frequencyTraceable");
|
||||
+ min_gm_clock_class = config_get_int(cfg, NULL, "ha_min_gm_ClockClass");
|
||||
+
|
||||
+ /* save a list of available source clocks that matches requirements */
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+ /* check matching parameters */
|
||||
+ pr_debug("clock %s state %d", clock->device, clock->state);
|
||||
+
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER) {
|
||||
+ pr_debug("clock %s discarded because state is PS_MASTER", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* sanity check */
|
||||
+ if (clock->node == NULL) {
|
||||
+ pr_debug("clock %s discarded because node is (null)", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* get Default Data Set */
|
||||
+ retries = 0;
|
||||
+ while(retries < 10) {
|
||||
+ if (!is_running()) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ err = pmc_agent_query_dds(clock->node, 1000);
|
||||
+ if (!err) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ pr_notice("Waiting for ptp4l...");
|
||||
+ retries++;
|
||||
+ } else {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!clock->node->dds_valid) {
|
||||
+ pr_debug("clock %s discarded because dds is invalid", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* min clockClass
|
||||
+ as lower clock class is better, accept sources which clock class
|
||||
+ is lower then or equal to min local clock class and discard
|
||||
+ the sources which clock class is higher than min local clock class.
|
||||
+ */
|
||||
+ clock_class = clock->node->dds.clockQuality.clockClass;
|
||||
+ pr_debug("clock %s local clockClass %d", clock->device, clock_class);
|
||||
+ if (clock_class > min_local_clock_class) {
|
||||
+ pr_debug("clock %s discarded because local clock class %d > min clock class %d",
|
||||
+ clock->device, clock_class, min_local_clock_class);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* min clockAccuracy (lower is better) */
|
||||
+ pr_debug("clock %s clockAccuracy 0x%x", clock->device,
|
||||
+ clock->node->dds.clockQuality.clockAccuracy);
|
||||
+ if (clock->node->dds.clockQuality.clockAccuracy > min_clock_accuracy) {
|
||||
+ pr_debug("clock %s discarded because clock accuracy %d > min clock accuracy %d",
|
||||
+ clock->device, clock->node->dds.clockQuality.clockAccuracy,
|
||||
+ min_clock_accuracy);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* min offset scaled log variance */
|
||||
+ pr_debug("clock %s offsetScaledLogVariance 0x%x", clock->device,
|
||||
+ clock->node->dds.clockQuality.offsetScaledLogVariance);
|
||||
+ if (clock->node->dds.clockQuality.offsetScaledLogVariance > min_offset_scaled_log_variance) {
|
||||
+ pr_debug("clock %s discarded because offset scaled log variance 0x%x > min offset 0x%x",
|
||||
+ clock->device, clock->node->dds.clockQuality.offsetScaledLogVariance,
|
||||
+ min_offset_scaled_log_variance);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (check_time_traceable || check_freq_traceable) {
|
||||
+ /* get Time Properties Data Set */
|
||||
+ retries = 0;
|
||||
+ while(retries < 10) {
|
||||
+ if (!is_running()) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ err = pmc_agent_query_utc_offset(clock->node, 1000);
|
||||
+ if (!err) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ pr_notice("Waiting for ptp4l...");
|
||||
+ retries++;
|
||||
+ } else {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (err != 0) {
|
||||
+ pr_debug("clock %s discarded because tds is invalid", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* is time traceable */
|
||||
+ pr_debug("clock %s is time traceable %s", clock->device,
|
||||
+ clock->node->utc_offset_traceable ? "yes" : "no");
|
||||
+ if (check_time_traceable && !clock->node->utc_offset_traceable) {
|
||||
+ pr_debug("clock %s discarded because time is not traceable", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* is frequency traceable */
|
||||
+ pr_debug("clock %s is frequency traceable %s", clock->device,
|
||||
+ clock->node->freq_traceable ? "yes" : "no");
|
||||
+ if (check_freq_traceable && !clock->node->freq_traceable) {
|
||||
+ pr_debug("clock %s discarded because frequency is not traceable", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ retries = 0;
|
||||
+ while (retries < 10) {
|
||||
+ if (!is_running()) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ err = pmc_agent_query_pds(clock->node, 1000);
|
||||
+ if (!err) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if (err == -ETIMEDOUT) {
|
||||
+ pr_notice("Waiting for ptp4l...");
|
||||
+ retries++;
|
||||
+ } else {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!clock->node->pds_valid) {
|
||||
+ pr_debug("clock %s discarded because pds is invalid", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* min gm clock class - lower is better */
|
||||
+ clock_class = clock->node->pds.grandmasterClockQuality.clockClass;
|
||||
+ pr_debug("clock %s GM clockClass %d", clock->device, clock_class);
|
||||
+ if (clock_class > min_gm_clock_class) {
|
||||
+ pr_debug("clock %s discarded because GM clock class %d > min clock class %d",
|
||||
+ clock->device, clock_class, min_gm_clock_class);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ pr_notice("clock %s matched requirements", clock->device);
|
||||
+
|
||||
+ clock->good_list.le_next = NULL;
|
||||
+ clock->good_list.le_prev = NULL;
|
||||
+ LIST_INSERT_HEAD(&good_clocks, clock, good_list);
|
||||
+ }
|
||||
+
|
||||
+ /* one or more sources match requirements, select highest priority */
|
||||
+ highest_priority = 0;
|
||||
+ LIST_FOREACH(clock, &good_clocks, good_list) {
|
||||
+ clock_priority = config_get_int(cfg, clock->device, "ha_priority");
|
||||
+
|
||||
+ /* select highest priority clock
|
||||
+ more than one clock with same priority, select first
|
||||
+ don't select clocks with ha_priority 0 */
|
||||
+ if (clock_priority > highest_priority) {
|
||||
+ pr_notice("new highest ha priority clock %s ha_priority %d",
|
||||
+ clock->device, clock_priority);
|
||||
+ best = clock;
|
||||
+ highest_priority = clock_priority;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* no sources match requirements, choose best available clockClass */
|
||||
+ if (!best) {
|
||||
+ lowest_clock_class = 256;
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* get clock class */
|
||||
+ clock_class = clock->node->dds.clockQuality.clockClass;
|
||||
+ if (clock_class <= lowest_clock_class) {
|
||||
+ pr_notice("new better clock class clock %s clock class %d",
|
||||
+ clock->device, clock_class);
|
||||
+ best = clock;
|
||||
+ lowest_clock_class = clock_class;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* no clock selected, select first clock configured (last in list) */
|
||||
+ if (!best) {
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ best = clock;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (best)
|
||||
+ pr_notice("Best clock selected %s", best->device);
|
||||
+
|
||||
+ return best;
|
||||
+};
|
||||
+
|
||||
static void usage(char *progname)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@@ -1486,6 +1713,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
++i;
|
||||
}
|
||||
+
|
||||
+ if (ha_enabled) {
|
||||
+ startup_select_clock(&priv, cfg);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (pps_fd >= 0) {
|
||||
diff --git a/pmc_agent.c b/pmc_agent.c
|
||||
index d13f569..534f483 100644
|
||||
--- a/pmc_agent.c
|
||||
+++ b/pmc_agent.c
|
||||
@@ -351,15 +351,35 @@ int pmc_agent_query_utc_offset(struct pmc_agent *node, int timeout)
|
||||
node->leap = 0;
|
||||
node->utc_offset_traceable = tds->flags & UTC_OFF_VALID &&
|
||||
tds->flags & TIME_TRACEABLE;
|
||||
+ node->freq_traceable = tds->flags & FREQ_TRACEABLE;
|
||||
} else {
|
||||
node->sync_offset = 0;
|
||||
node->leap = 0;
|
||||
node->utc_offset_traceable = 0;
|
||||
+ node->freq_traceable = 0;
|
||||
}
|
||||
msg_put(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int pmc_agent_query_pds(struct pmc_agent *node, int timeout)
|
||||
+{
|
||||
+ struct parentDS *pds;
|
||||
+ struct ptp_message *msg;
|
||||
+ int res;
|
||||
+
|
||||
+ res = run_pmc(node, timeout, MID_PARENT_DATA_SET, &msg);
|
||||
+ if (is_run_pmc_error(res)) {
|
||||
+ return run_pmc_err2errno(res);
|
||||
+ }
|
||||
+
|
||||
+ pds = (struct parentDS *) management_tlv_data(msg);
|
||||
+ memcpy(&node->pds, pds, sizeof(node->pds));
|
||||
+ node->pds_valid = true;
|
||||
+ msg_put(msg);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void pmc_agent_set_sync_offset(struct pmc_agent *agent, int offset)
|
||||
{
|
||||
agent->sync_offset = offset;
|
||||
diff --git a/pmc_agent.h b/pmc_agent.h
|
||||
index 5f25984..2bd7f02 100644
|
||||
--- a/pmc_agent.h
|
||||
+++ b/pmc_agent.h
|
||||
@@ -41,7 +41,10 @@ struct pmc_agent {
|
||||
bool stay_subscribed;
|
||||
int sync_offset;
|
||||
int utc_offset_traceable;
|
||||
+ int freq_traceable;
|
||||
unsigned int index;
|
||||
+ struct parentDS pds;
|
||||
+ bool pds_valid;
|
||||
|
||||
/* Callback on message reception */
|
||||
pmc_node_recv_subscribed_t *recv_subscribed;
|
||||
@@ -142,6 +145,16 @@ int pmc_agent_query_port_properties(struct pmc_agent *agent, int timeout,
|
||||
*/
|
||||
int pmc_agent_query_utc_offset(struct pmc_agent *agent, int timeout);
|
||||
|
||||
+/**
|
||||
+ * Queries the parent data set from the ptp4l service.
|
||||
+ * The result of the query will be cached inside of the agent.
|
||||
+ *
|
||||
+ * @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_pds(struct pmc_agent *agent, int timeout);
|
||||
+
|
||||
/**
|
||||
* Sets the TAI-UTC offset.
|
||||
* @param agent Pointer to a PMC instance obtained via @ref pmc_agent_create().
|
||||
--
|
||||
2.25.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,256 @@
|
||||
From 7d5061d971a8abc2ba8443edccde38e9a7a6f0ce Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Wed, 26 Jul 2023 15:08:15 -0300
|
||||
Subject: [PATCH 40/47] Forced lock a clock source in configuration
|
||||
|
||||
To help on maintenance and debuging tasks was implemented a configuration
|
||||
to forced lock to a single clock. It disables the automatic clock
|
||||
selection algorithm and lock to a source interface.
|
||||
|
||||
When an interface is configured with maximum ha_priority (254)
|
||||
the source selection is locked to it, regardless of its clock
|
||||
status.
|
||||
|
||||
When more than one source clock is configured with ha_priority 254
|
||||
selects the 1st interface in the configuration file.
|
||||
|
||||
Test plan: forced lock by configuration
|
||||
PASS: Verify the clock source is forced lock to an interface, regardless
|
||||
its state.
|
||||
PASS: Verify the clock source remains locked event after change the clock
|
||||
state.
|
||||
PASS: Verify the 1st configured interface with priority 254 is selected
|
||||
when multiple interfaces has the same priority.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek <andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 9563a04ef76cda55f9f014150270dbd320ca4bc4 upstream]
|
||||
[commit 655fe5e304386b4494d864638ca972c4bd892e52 upstream]
|
||||
[commit 3200a16f4cbe2d125bf301827a24d3d01e7f1c70 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
config.c | 2 +-
|
||||
phc2sys.c | 105 ++++++++++++++++++++++++++++++++++++++----------------
|
||||
2 files changed, 75 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index 1ad5157..dba1eef 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -256,7 +256,7 @@ struct config_item config_tab[] = {
|
||||
GLOB_ITEM_INT("ha_min_gm_ClockClass", 135, 6, 255),
|
||||
GLOB_ITEM_INT("ha_min_local_clockClass", 135, 6, 255),
|
||||
GLOB_ITEM_INT("ha_min_offsetScaledLogVariance", 65535, 0, 65535),
|
||||
- PORT_ITEM_INT("ha_priority", 0, 0, 255),
|
||||
+ PORT_ITEM_INT("ha_priority", 0, 0, 254),
|
||||
PORT_ITEM_INT("ha_stability_timer", 0, 0, INT_MAX),
|
||||
GLOB_ITEM_INT("ha_timeTraceable", 0, 0, 1),
|
||||
PORT_ITEM_STR("ha_uds_address", "/var/run/ptp4l"),
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 152e783..0b3f724 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -64,6 +64,7 @@
|
||||
|
||||
#define PHC_PPS_OFFSET_LIMIT 10000000
|
||||
|
||||
+#define FORCED_SOURCE_CLOCK_PRIORITY 254
|
||||
#define MAX_SRC_CLOCKS 128
|
||||
|
||||
#define PORT_INDEX_TO_PORT_ID(port, index) (((((unsigned int) port) & 0xFF) << 8) | (((unsigned int) index) & 0xFF))
|
||||
@@ -121,6 +122,7 @@ struct phc2sys_private {
|
||||
struct clock *better;
|
||||
struct timespec stability_timer;
|
||||
int default_sync;
|
||||
+ int forced_source_clock;
|
||||
};
|
||||
|
||||
static struct config *phc2sys_config;
|
||||
@@ -998,6 +1000,29 @@ static int update_needed(struct clock *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* check configuration if one of the source clocks is force locked to be active */
|
||||
+static struct clock* ha_forced_source_clock(struct phc2sys_private *priv, struct config *cfg)
|
||||
+{
|
||||
+ int clock_priority;
|
||||
+ struct clock *clock = NULL, *best = NULL;
|
||||
+
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ clock_priority = config_get_int(cfg, clock->device, "ha_priority");
|
||||
+ if (FORCED_SOURCE_CLOCK_PRIORITY == clock_priority) {
|
||||
+ pr_info("HA automatic source selection is disabled by configuration");
|
||||
+ priv->forced_source_clock = 1;
|
||||
+ best = clock;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return best;
|
||||
+}
|
||||
+
|
||||
static struct clock* ha_select_clock(struct phc2sys_private *priv, struct config *cfg)
|
||||
{
|
||||
int clock_priority, highest_priority;
|
||||
@@ -1066,7 +1091,7 @@ static struct clock* ha_select_clock(struct phc2sys_private *priv, struct config
|
||||
}
|
||||
|
||||
if (best)
|
||||
- pr_notice("Best clock selected %s", best->device);
|
||||
+ pr_notice("best clock available %s", best->device);
|
||||
|
||||
return best;
|
||||
}
|
||||
@@ -1121,7 +1146,7 @@ static struct clock* check_and_select_clock(struct phc2sys_private *priv, struct
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* stability timer = 0 - change active */
|
||||
+ /* stability timer equal 0 - change active */
|
||||
stability_timer = config_get_int(cfg, NULL, "ha_stability_timer");
|
||||
if (stability_timer == 0) {
|
||||
pr_notice("new source clock selected %s", candidate->device);
|
||||
@@ -1173,6 +1198,10 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
}
|
||||
|
||||
if (node->new_dds || node->new_tpds || node->new_pds) {
|
||||
+ pr_debug("pmc agent index %d clock state changed by %s%s%s",
|
||||
+ node->index, node->new_dds ? "new dds " : "",
|
||||
+ node->new_tpds ? "new tpds " : "",
|
||||
+ node->new_pds ? "new pds " : "");
|
||||
priv->clock_state_changed = 1;
|
||||
}
|
||||
|
||||
@@ -1194,30 +1223,38 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
}
|
||||
|
||||
if (ha_enabled) {
|
||||
- if (priv->clock_state_changed) {
|
||||
- clock = check_and_select_clock(priv, cfg);
|
||||
- if (clock && clock != priv->master) {
|
||||
- priv->master = clock;
|
||||
- priv->better = NULL;
|
||||
- priv->stability_timer.tv_sec = 0;
|
||||
- priv->stability_timer.tv_nsec = 0;
|
||||
+ if (priv->forced_source_clock) {
|
||||
+ /* HA automatic clock selection is disabled */
|
||||
+ if (priv->clock_state_changed) {
|
||||
+ priv->clock_state_changed = 0;
|
||||
+ reset_new_dataset_flags(priv);
|
||||
}
|
||||
+ } else {
|
||||
+ if (priv->clock_state_changed) {
|
||||
+ clock = check_and_select_clock(priv, cfg);
|
||||
+ if (clock && clock != priv->master) {
|
||||
+ priv->master = clock;
|
||||
+ priv->better = NULL;
|
||||
+ priv->stability_timer.tv_sec = 0;
|
||||
+ priv->stability_timer.tv_nsec = 0;
|
||||
+ }
|
||||
|
||||
- priv->clock_state_changed = 0;
|
||||
- reset_new_dataset_flags(priv);
|
||||
- }
|
||||
+ priv->clock_state_changed = 0;
|
||||
+ reset_new_dataset_flags(priv);
|
||||
+ }
|
||||
|
||||
- if (priv->better) {
|
||||
- /* has stability timer expired? */
|
||||
- clock_gettime(CLOCK_REALTIME, &now);
|
||||
- if ((now.tv_sec > priv->stability_timer.tv_sec) ||
|
||||
- (now.tv_sec == priv->stability_timer.tv_sec &&
|
||||
- now.tv_nsec > priv->stability_timer.tv_nsec)) {
|
||||
- pr_notice("new source clock selected %s", priv->better->device);
|
||||
- priv->master = priv->better;
|
||||
- priv->better = NULL;
|
||||
- priv->stability_timer.tv_sec = 0;
|
||||
- priv->stability_timer.tv_nsec = 0;
|
||||
+ if (priv->better) {
|
||||
+ /* has stability timer expired? */
|
||||
+ clock_gettime(CLOCK_REALTIME, &now);
|
||||
+ if ((now.tv_sec > priv->stability_timer.tv_sec) ||
|
||||
+ (now.tv_sec == priv->stability_timer.tv_sec &&
|
||||
+ now.tv_nsec > priv->stability_timer.tv_nsec)) {
|
||||
+ pr_notice("new source clock selected %s", priv->better->device);
|
||||
+ priv->master = priv->better;
|
||||
+ priv->better = NULL;
|
||||
+ priv->stability_timer.tv_sec = 0;
|
||||
+ priv->stability_timer.tv_nsec = 0;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1313,12 +1350,8 @@ static int phc2sys_recv_subscribed(struct pmc_agent *node, void *context, struct
|
||||
struct phc2sys_private *priv = (struct phc2sys_private *) context;
|
||||
int mgt_id, state;
|
||||
struct portDS *pds;
|
||||
- struct defaultDS *dds;
|
||||
- struct parentDS *parentds;
|
||||
- struct timePropertiesDS *tds;
|
||||
struct port *port;
|
||||
struct clock *clock;
|
||||
- int utc_offset_traceable, freq_traceable;
|
||||
|
||||
mgt_id = management_tlv_id(msg);
|
||||
if (mgt_id == excluded)
|
||||
@@ -1563,6 +1596,7 @@ int main(int argc, char *argv[])
|
||||
.master = NULL,
|
||||
.better = NULL,
|
||||
.stability_timer.tv_sec = 0,
|
||||
+ .forced_source_clock = 0,
|
||||
};
|
||||
struct pmc_agent *node = NULL;
|
||||
unsigned int i, src_cnt = 0;
|
||||
@@ -1861,13 +1895,19 @@ int main(int argc, char *argv[])
|
||||
goto bad_usage;
|
||||
}
|
||||
|
||||
+ if (ha_enabled) {
|
||||
+ src = ha_forced_source_clock(&priv, cfg);
|
||||
+ if (src != NULL) {
|
||||
+ pr_info("Only interface %s will be used as source clock", src->device);
|
||||
+ priv.master = src;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
r = -1;
|
||||
|
||||
if (wait_sync) {
|
||||
i = 0;
|
||||
- for (src = LIST_FIRST(&priv.clocks);
|
||||
- src != NULL;
|
||||
- src = LIST_NEXT(src, list)) {
|
||||
+ LIST_FOREACH(src, &priv.clocks, list) {
|
||||
|
||||
/* skip dst clock */
|
||||
if (src == dst) {
|
||||
@@ -1890,6 +1930,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* map clock to pmc agent node */
|
||||
src->node = node;
|
||||
+ pr_debug("pmc node index %d source clock %s initialized",
|
||||
+ node->index, src->device);
|
||||
|
||||
while (is_running()) {
|
||||
r = run_pmc_wait_sync(node, 1000);
|
||||
@@ -1918,8 +1960,9 @@ int main(int argc, char *argv[])
|
||||
++i;
|
||||
}
|
||||
|
||||
- if (ha_enabled) {
|
||||
+ if (ha_enabled && !priv.forced_source_clock) {
|
||||
priv.master = ha_select_clock(&priv, cfg);
|
||||
+ pr_info("interface %s will be used as source clock", priv.master->device);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
451
base/linuxptp/debian/patches/0041-HA-phc2sys-com-socket.patch
Normal file
451
base/linuxptp/debian/patches/0041-HA-phc2sys-com-socket.patch
Normal file
@ -0,0 +1,451 @@
|
||||
From fce993dd36e481aace337a62ff81331cd2411bec Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Thu, 27 Jul 2023 14:22:47 -0300
|
||||
Subject: [PATCH 41/47] HA phc2sys com socket
|
||||
|
||||
A new communication path was created to retrieve status and to control
|
||||
the high availability algorithm.
|
||||
|
||||
The ha_phc2sys_com_socket option is a global setting to configure
|
||||
the socket path. Its default value is /var/run/phc2sys.
|
||||
|
||||
The command 'status' was created to retrieve the current HA clock status.
|
||||
The answer is a table of configured clocks and its status.
|
||||
|
||||
act interface priority clockClass clockAcc offset time freq gm.
|
||||
|
||||
* ens2f1 200 248 0xfe 0xffff no no 6
|
||||
ens1f2 100 248 0xfe 0xffff no no 6
|
||||
|
||||
Source forced? no
|
||||
|
||||
The * sign marks the active source clock.
|
||||
The - sign marks the active candidate source clock, which will be set active
|
||||
after the stability timer expiration.
|
||||
The x sign marks the disabled interfaces (see 'disable source' command).
|
||||
|
||||
The 'Source forced?' field shows if the active source is forced lock or not.
|
||||
|
||||
The 'clock source' command can be used to retrive the active
|
||||
clock source. It returns the interface name of the active
|
||||
clock source or "None" when there is no one select.
|
||||
|
||||
The 'forced lock' command can be used to retrieve if the active
|
||||
clock source is forced lock, and the clock source selection
|
||||
algorithm is disabled. It returns "True" when is forced lock
|
||||
and "False" otherwise.
|
||||
|
||||
Test plan: socket path configuration
|
||||
PASS Verify the socket using the default path.
|
||||
PASS Verify the socket using a given socket path.
|
||||
|
||||
Test plan: status command
|
||||
PASS: Verify the 'status' command after start up.
|
||||
PASS: Verify the 'status' command while stability timer is running.
|
||||
PASS: Verify the 'status' command with a forced lock interface by
|
||||
configuring ha_priority 254.
|
||||
|
||||
Test plan: clock source command
|
||||
PASS: Verify the 'clock source' command response is the highest priority
|
||||
interface after start up.
|
||||
PASS: Verify the 'clock source' command response is the active interface
|
||||
after the primary has degraded.
|
||||
PASS: Verify the 'clock source' command response is the forced lock
|
||||
interface, when ha_priority 254 is configured in one of them.
|
||||
|
||||
Test plan: forced lock command
|
||||
PASS: Verify the 'forced lock' command response is 'False' when no
|
||||
interface is configured with ha_priority 254.
|
||||
PASS: Verify the 'forced lock' command response is 'True' when one
|
||||
interface is configured with ha_priority 254.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek <andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 0cfcbb78485a83d324963130f9558fd0a1962a79 upstream]
|
||||
[commit 73b9afa33a0d8dcfd9c4ebb7bceacee40af8eb2b upstream]
|
||||
[commit 6e93059d34639a3c2aac6b56dcf94ddf1e48e9b4 upstream]
|
||||
[commit 4f118cf954bc3543582765bc039c42aeac05caf5 upstream]
|
||||
[commit 6387ddf644afcb880b67368be8416b8ce906e029 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
config.c | 1 +
|
||||
phc2sys.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 216 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index dba1eef..6a1bfb4 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -256,6 +256,7 @@ struct config_item config_tab[] = {
|
||||
GLOB_ITEM_INT("ha_min_gm_ClockClass", 135, 6, 255),
|
||||
GLOB_ITEM_INT("ha_min_local_clockClass", 135, 6, 255),
|
||||
GLOB_ITEM_INT("ha_min_offsetScaledLogVariance", 65535, 0, 65535),
|
||||
+ GLOB_ITEM_STR("ha_phc2sys_com_socket", "/var/run/phc2sys-phc-inst1"),
|
||||
PORT_ITEM_INT("ha_priority", 0, 0, 254),
|
||||
PORT_ITEM_INT("ha_stability_timer", 0, 0, INT_MAX),
|
||||
GLOB_ITEM_INT("ha_timeTraceable", 0, 0, 1),
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 0b3f724..0bc3709 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -66,6 +66,9 @@
|
||||
|
||||
#define FORCED_SOURCE_CLOCK_PRIORITY 254
|
||||
#define MAX_SRC_CLOCKS 128
|
||||
+#define HA_SCK_N_FD 1
|
||||
+#define HA_SCK_BUFFER_SIZE 1024
|
||||
+#define HA_SCK_FILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) /*0660*/
|
||||
|
||||
#define PORT_INDEX_TO_PORT_ID(port, index) (((((unsigned int) port) & 0xFF) << 8) | (((unsigned int) index) & 0xFF))
|
||||
#define PORT_ID_TO_PORT(id) ((((unsigned int) id) >> 8) & 0xFF)
|
||||
@@ -94,6 +97,7 @@ struct clock {
|
||||
struct stats *delay_stats;
|
||||
struct clockcheck *sanity_check;
|
||||
struct pmc_agent *node;
|
||||
+ int ha_priority;
|
||||
};
|
||||
typedef LIST_HEAD(head, clock) clock_list_head_t;
|
||||
|
||||
@@ -123,6 +127,7 @@ struct phc2sys_private {
|
||||
struct timespec stability_timer;
|
||||
int default_sync;
|
||||
int forced_source_clock;
|
||||
+ int ha_socket_fd;
|
||||
};
|
||||
|
||||
static struct config *phc2sys_config;
|
||||
@@ -1003,7 +1008,6 @@ static int update_needed(struct clock *c)
|
||||
/* check configuration if one of the source clocks is force locked to be active */
|
||||
static struct clock* ha_forced_source_clock(struct phc2sys_private *priv, struct config *cfg)
|
||||
{
|
||||
- int clock_priority;
|
||||
struct clock *clock = NULL, *best = NULL;
|
||||
|
||||
LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
@@ -1012,8 +1016,7 @@ static struct clock* ha_forced_source_clock(struct phc2sys_private *priv, struct
|
||||
continue;
|
||||
}
|
||||
|
||||
- clock_priority = config_get_int(cfg, clock->device, "ha_priority");
|
||||
- if (FORCED_SOURCE_CLOCK_PRIORITY == clock_priority) {
|
||||
+ if (FORCED_SOURCE_CLOCK_PRIORITY == clock->ha_priority) {
|
||||
pr_info("HA automatic source selection is disabled by configuration");
|
||||
priv->forced_source_clock = 1;
|
||||
best = clock;
|
||||
@@ -1025,7 +1028,7 @@ static struct clock* ha_forced_source_clock(struct phc2sys_private *priv, struct
|
||||
|
||||
static struct clock* ha_select_clock(struct phc2sys_private *priv, struct config *cfg)
|
||||
{
|
||||
- int clock_priority, highest_priority;
|
||||
+ int highest_priority;
|
||||
int clock_class, lowest_clock_class;
|
||||
struct clock *clock = NULL, *best = NULL;
|
||||
clock_list_head_t ha_available_clocks;
|
||||
@@ -1038,17 +1041,14 @@ static struct clock* ha_select_clock(struct phc2sys_private *priv, struct config
|
||||
|
||||
/* one or more sources match requirements, select highest priority */
|
||||
highest_priority = 0;
|
||||
- LIST_FOREACH(clock, &ha_available_clocks, ha_list) {
|
||||
- clock_priority = config_get_int(cfg, clock->device, "ha_priority");
|
||||
-
|
||||
- /* select highest priority clock
|
||||
+ LIST_FOREACH(clock, &ha_available_clocks, ha_list) {/* select highest priority clock
|
||||
more than one clock with same priority, select first
|
||||
don't select clocks with ha_priority 0 */
|
||||
- if (clock_priority > highest_priority) {
|
||||
+ if (clock->ha_priority > highest_priority) {
|
||||
pr_notice("new highest ha priority clock %s ha_priority %d",
|
||||
- clock->device, clock_priority);
|
||||
+ clock->device, clock->ha_priority);
|
||||
best = clock;
|
||||
- highest_priority = clock_priority;
|
||||
+ highest_priority = clock->ha_priority;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1101,7 +1101,6 @@ static struct clock* check_and_select_clock(struct phc2sys_private *priv, struct
|
||||
struct clock *active = priv->master, *candidate = NULL;
|
||||
int stability_timer = 0;
|
||||
struct timespec now;
|
||||
- int active_priority, candidate_priority;
|
||||
int active_clock_class, candidate_clock_class;
|
||||
|
||||
/* Active source degrades - re-run ha_select_clock algorithm */
|
||||
@@ -1137,11 +1136,9 @@ static struct clock* check_and_select_clock(struct phc2sys_private *priv, struct
|
||||
/* new clock candidate */
|
||||
|
||||
/* candidate has equal priority and clockClass than active - don't change active */
|
||||
- active_priority = config_get_int(cfg, active->device, "ha_priority");
|
||||
- candidate_priority = config_get_int(cfg, candidate->device, "ha_priority");
|
||||
active_clock_class = active->node->dds.clockQuality.clockClass;
|
||||
candidate_clock_class = candidate->node->dds.clockQuality.clockClass;
|
||||
- if ((active_priority == candidate_priority) &&
|
||||
+ if ((active->ha_priority == candidate->ha_priority) &&
|
||||
(active_clock_class == candidate_clock_class)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1175,6 +1172,196 @@ static void reset_new_dataset_flags(struct phc2sys_private *priv)
|
||||
}
|
||||
}
|
||||
|
||||
+static int ha_com_socket_close(int fd)
|
||||
+{
|
||||
+ struct sockaddr_un sa;
|
||||
+ socklen_t len = sizeof(sa);
|
||||
+
|
||||
+ // if (fd < 0)
|
||||
+ // return -1;
|
||||
+
|
||||
+ if (!getsockname(fd, (struct sockaddr *) &sa, &len) &&
|
||||
+ sa.sun_family == AF_LOCAL) {
|
||||
+ unlink(sa.sun_path);
|
||||
+ }
|
||||
+
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
+{
|
||||
+ int fd, err;
|
||||
+ struct sockaddr_un sa;
|
||||
+ const char *name = config_get_string(cfg, NULL, "ha_phc2sys_com_socket");
|
||||
+
|
||||
+ fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
|
||||
+ if (fd < 0) {
|
||||
+ pr_err("ha_com_socket: failed to create socket: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.sun_family = AF_LOCAL;
|
||||
+ strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1);
|
||||
+
|
||||
+ err = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
|
||||
+ if (err < 0) {
|
||||
+ pr_err("ha_com_socket: bind failed: %m");
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ *fd_out = fd;
|
||||
+ chmod(name, HA_SCK_FILEMODE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ha_com_socket_recv(int fd, void *buf, size_t buflen,
|
||||
+ struct address *addr)
|
||||
+{
|
||||
+ int cnt;
|
||||
+
|
||||
+ addr->len = sizeof(addr->sun);
|
||||
+ cnt = recvfrom(fd, buf, buflen, 0, &addr->sa, &addr->len);
|
||||
+ if (cnt <= 0) {
|
||||
+ pr_err("ha_com_socket: recvfrom failed: %m");
|
||||
+ return cnt;
|
||||
+ }
|
||||
+
|
||||
+ ((char*)buf)[cnt] = '\0';
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ha_com_socket_send(int fd, struct address *addr, void *buf,
|
||||
+ size_t buflen)
|
||||
+{
|
||||
+ int cnt;
|
||||
+
|
||||
+ cnt = sendto(fd, buf, buflen, 0, &addr->sa, addr->len);
|
||||
+ if (cnt < 1) {
|
||||
+ return -errno;
|
||||
+ }
|
||||
+ return cnt;
|
||||
+}
|
||||
+
|
||||
+static int ha_handle_status_msg(struct phc2sys_private *priv, char *response,
|
||||
+ size_t resplen)
|
||||
+{
|
||||
+ struct clock *clock;
|
||||
+ size_t curlen = 0;
|
||||
+
|
||||
+ /* header */
|
||||
+ curlen = snprintf(response, resplen,
|
||||
+ "act interface priority clockClass clockAcc offset time freq "
|
||||
+ "gm.clockClass\n\n");
|
||||
+
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER)
|
||||
+ continue;
|
||||
+
|
||||
+ /* sanity check */
|
||||
+ if (clock->node == NULL)
|
||||
+ continue;
|
||||
+
|
||||
+ curlen += snprintf(response + curlen, resplen - curlen,
|
||||
+ " %c %9s %8d %10d 0x%2x 0x%4x %s %s %d\n",
|
||||
+ (priv->master == clock) ? '*' :
|
||||
+ (priv->better == clock) ? '-' : ' ',
|
||||
+ clock->device, clock->ha_priority,
|
||||
+ clock->node->dds.clockQuality.clockClass,
|
||||
+ clock->node->dds.clockQuality.clockAccuracy,
|
||||
+ clock->node->dds.clockQuality.offsetScaledLogVariance,
|
||||
+ clock->node->utc_offset_traceable ? "yes" : "no ",
|
||||
+ clock->node->freq_traceable ? "yes" : "no ",
|
||||
+ clock->node->pds.grandmasterClockQuality.clockClass);
|
||||
+ }
|
||||
+
|
||||
+ curlen += snprintf(response + curlen, resplen - curlen,
|
||||
+ "\n\nSource forced? %s\n", priv->forced_source_clock ? "yes" : "no");
|
||||
+
|
||||
+ return curlen;
|
||||
+}
|
||||
+
|
||||
+static int ha_com_socket_handle_msg(struct phc2sys_private *priv)
|
||||
+{
|
||||
+ struct pollfd pollfd[HA_SCK_N_FD];
|
||||
+ struct address sender;
|
||||
+ int cnt, res = 0;
|
||||
+ int timeout = 0;
|
||||
+ void * buffer = NULL;
|
||||
+ void * response = NULL;
|
||||
+
|
||||
+ while(1) {
|
||||
+ pollfd[0].fd = priv->ha_socket_fd;
|
||||
+ pollfd[0].events = POLLIN|POLLPRI;
|
||||
+
|
||||
+ cnt = poll(pollfd, HA_SCK_N_FD, timeout);
|
||||
+ if (cnt < 0) {
|
||||
+ pr_err("ha_com_socket: poll failed: %m");
|
||||
+ res = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!cnt) {
|
||||
+ /* timeout and fd wasn't ready */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
+ break;
|
||||
+
|
||||
+ buffer = malloc(HA_SCK_BUFFER_SIZE);
|
||||
+ if (!buffer) {
|
||||
+ pr_err("ha_com_socket: failed to allocate memory for message");
|
||||
+ res = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ res = ha_com_socket_recv(pollfd[0].fd, buffer, HA_SCK_BUFFER_SIZE, &sender);
|
||||
+ if (res < 0)
|
||||
+ break;
|
||||
+
|
||||
+ fprintf(stderr, "ha_com_socket: received: %s\n", (char*)buffer);
|
||||
+ fprintf(stderr, "ha_com_socket: recvd from: %s\n", ((struct sockaddr_un*)&sender.sa)->sun_path);
|
||||
+
|
||||
+ response = malloc(HA_SCK_BUFFER_SIZE);
|
||||
+ if (!response) {
|
||||
+ pr_err("ha_com_socket: failed to allocate memory for response message");
|
||||
+ res = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* handle messages and create responses */
|
||||
+ if (strcmp((const char*)buffer, "status") == 0) {
|
||||
+ cnt = ha_handle_status_msg(priv, response, HA_SCK_BUFFER_SIZE);
|
||||
+ } else if (strcmp((const char*)buffer, "clock source") == 0) {
|
||||
+ if (priv->master) {
|
||||
+ cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "%s",
|
||||
+ priv->master->device);
|
||||
+ } else {
|
||||
+ cnt = snprintf((char*)buffer, HA_SCK_BUFFER_SIZE, "None");
|
||||
+ }
|
||||
+ } else if (strcmp((const char*)buffer, "forced lock") == 0) {
|
||||
+ cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "%s",
|
||||
+ priv->forced_source_clock ? "True" : "False");
|
||||
+ } else {
|
||||
+ cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "error: invalid command");
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "ha_com_socket: response: \n%s", (char*)response);
|
||||
+
|
||||
+ res = ha_com_socket_send(pollfd[0].fd, &sender, response, cnt);
|
||||
+ }
|
||||
+
|
||||
+ free(buffer);
|
||||
+ free(response);
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscriptions)
|
||||
{
|
||||
struct timespec interval;
|
||||
@@ -1223,6 +1410,8 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
}
|
||||
|
||||
if (ha_enabled) {
|
||||
+ ha_com_socket_handle_msg(priv);
|
||||
+
|
||||
if (priv->forced_source_clock) {
|
||||
/* HA automatic clock selection is disabled */
|
||||
if (priv->clock_state_changed) {
|
||||
@@ -1312,6 +1501,7 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
update_clock(priv, clock, offset, ts, delay);
|
||||
}
|
||||
}
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1597,6 +1787,7 @@ int main(int argc, char *argv[])
|
||||
.better = NULL,
|
||||
.stability_timer.tv_sec = 0,
|
||||
.forced_source_clock = 0,
|
||||
+ .ha_socket_fd = -1,
|
||||
};
|
||||
struct pmc_agent *node = NULL;
|
||||
unsigned int i, src_cnt = 0;
|
||||
@@ -1861,7 +2052,7 @@ int main(int argc, char *argv[])
|
||||
ha_enabled = config_get_int(cfg, NULL, "ha_enabled");
|
||||
if (!ha_enabled && src_cnt > 1) {
|
||||
fprintf(stderr, "too many source clocks\n");
|
||||
- fprintf(stderr, "Use 'ha_enabled 1' to accept more than one source clocks\n");
|
||||
+ fprintf(stderr, "Use 'ha_enabled 1' to accept more than one source clock\n");
|
||||
goto bad_usage;
|
||||
}
|
||||
|
||||
@@ -1877,6 +2068,9 @@ int main(int argc, char *argv[])
|
||||
if (priv.master == NULL) {
|
||||
priv.master = src;
|
||||
}
|
||||
+ if (ha_enabled) {
|
||||
+ src->ha_priority = config_get_int(cfg, src->device, "ha_priority");
|
||||
+ }
|
||||
}
|
||||
|
||||
dst = clock_add(&priv, dst_name ? dst_name : "CLOCK_REALTIME");
|
||||
@@ -1966,6 +2160,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
+ if (ha_enabled) {
|
||||
+ ha_com_socket_open(&priv.ha_socket_fd, cfg);
|
||||
+ }
|
||||
+
|
||||
if (pps_fd >= 0) {
|
||||
/* only one destination clock allowed with PPS until we
|
||||
* implement a mean to specify PTP port to PPS mapping */
|
||||
@@ -1976,6 +2174,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
end:
|
||||
+ ha_com_socket_close(priv.ha_socket_fd);
|
||||
pmc_agent_cleanup(&priv);
|
||||
clock_cleanup(&priv);
|
||||
port_cleanup(&priv);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,193 @@
|
||||
From e77783a9873baeeda277cfa59059021ce121a693 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Fri, 4 Aug 2023 15:44:12 -0300
|
||||
Subject: [PATCH 42/47] Commands 'enable lock' and 'disable lock.
|
||||
|
||||
The 'enable lock' command is used to lock to a single clock
|
||||
source and disable the HA clock selection algorithm. The
|
||||
interface of the clock source must be specified in the
|
||||
command. For example:
|
||||
|
||||
'enable lock <interface-name>'
|
||||
|
||||
It returns "Success" or an error message. The error message
|
||||
"Error: Usage 'enable lock <interface>'" is returned when
|
||||
no interface was provided in the command. The error message
|
||||
"Error: Interface not found!" is returned when the interface
|
||||
provided is not found in the phc2sys configuration.
|
||||
|
||||
The command 'disable lock' is used to unlock the clock source
|
||||
and re-enable the HA clock selection algorithm. It returns
|
||||
"Success" even when the clock source was not locked.
|
||||
|
||||
Test plan: enable lock and disable lock commands
|
||||
PASS: Verify the enable lock changes the clock source to the given
|
||||
interface.
|
||||
PASS: Verify that regardless the interface state, the clock source
|
||||
remains locked.
|
||||
PASS: Verify that disable lock command makes the better available
|
||||
clock to be selected again.
|
||||
|
||||
[commit 704d9ed2e22b89308c7f0149d7fde86d456bc4e3 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 110 +++++++++++++++++++++++++++++++++++++++++++++---------
|
||||
1 file changed, 93 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 0bc3709..f89dc23 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -259,13 +259,21 @@ static void clock_cleanup(struct phc2sys_private *priv)
|
||||
}
|
||||
}
|
||||
|
||||
-static struct clock *clock_get(struct phc2sys_private *priv, struct pmc_agent *node)
|
||||
+static struct clock * clock_get_by_device(struct phc2sys_private *priv,
|
||||
+ const char * device)
|
||||
{
|
||||
struct clock * clock = NULL;
|
||||
LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
- if (clock->node == node) {
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER)
|
||||
+ continue;
|
||||
+
|
||||
+ /* sanity check */
|
||||
+ if (!clock->device)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strcmp(device, clock->device) == 0)
|
||||
break;
|
||||
- }
|
||||
}
|
||||
return clock;
|
||||
}
|
||||
@@ -508,18 +516,6 @@ static struct port *port_get(struct phc2sys_private *priv, unsigned int number)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct port *port_get_by_clock(struct phc2sys_private *priv, struct clock * clock)
|
||||
-{
|
||||
- struct port *p, *port = NULL;
|
||||
- LIST_FOREACH(p, &priv->ports, list) {
|
||||
- if (p->clock == clock) {
|
||||
- port = p;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- return port;
|
||||
-}
|
||||
-
|
||||
static struct port *port_add(struct phc2sys_private *priv, unsigned int number,
|
||||
char *device)
|
||||
{
|
||||
@@ -1287,7 +1283,82 @@ static int ha_handle_status_msg(struct phc2sys_private *priv, char *response,
|
||||
return curlen;
|
||||
}
|
||||
|
||||
-static int ha_com_socket_handle_msg(struct phc2sys_private *priv)
|
||||
+static bool startsWith(const char *prefix, const char *str)
|
||||
+{
|
||||
+ return 0 == strncmp(prefix, str, strlen(prefix) - 1);
|
||||
+}
|
||||
+
|
||||
+static char * strAtColumn(char *msg, size_t column)
|
||||
+{
|
||||
+ int i;
|
||||
+ char * str = NULL;
|
||||
+
|
||||
+ /* split and walk over the columns */
|
||||
+ strtok(msg, " ");
|
||||
+ for (i = 1; i < column; i++) {
|
||||
+ str = strtok(NULL, " ");
|
||||
+ }
|
||||
+
|
||||
+ return str;
|
||||
+}
|
||||
+
|
||||
+static int ha_handle_enable_lock_msg(struct phc2sys_private *priv, char *msg,
|
||||
+ char *response, size_t resplen)
|
||||
+{
|
||||
+ size_t curlen = 0;
|
||||
+ char *interface = NULL;
|
||||
+ struct clock *clock = NULL;
|
||||
+
|
||||
+ interface = strAtColumn(msg, 3);
|
||||
+ if (strlen(interface) == 0) {
|
||||
+ return snprintf(response, resplen, "Error: Usage 'enable lock <interface>'");
|
||||
+ }
|
||||
+
|
||||
+ clock = clock_get_by_device(priv, interface);
|
||||
+ if (!clock) {
|
||||
+ return snprintf(response, resplen, "Error: Interface not found!");
|
||||
+ }
|
||||
+
|
||||
+ pr_info("HA automatic source selection is disabled by command");
|
||||
+ pr_info("Only interface %s will be used as source clock", clock->device);
|
||||
+
|
||||
+ priv->master = clock;
|
||||
+ priv->better = NULL;
|
||||
+ priv->stability_timer.tv_sec = 0;
|
||||
+ priv->stability_timer.tv_nsec = 0;
|
||||
+
|
||||
+ priv->forced_source_clock = 1;
|
||||
+
|
||||
+ curlen = snprintf(response, resplen, "Success");
|
||||
+
|
||||
+ return curlen;
|
||||
+}
|
||||
+
|
||||
+static int ha_handle_disable_lock_msg(struct phc2sys_private *priv,
|
||||
+ struct config *cfg, char *response, size_t resplen)
|
||||
+{
|
||||
+ size_t curlen = 0;
|
||||
+ struct clock *clock = NULL;
|
||||
+
|
||||
+ if (priv->forced_source_clock) {
|
||||
+ pr_info("HA automatic source selection is enabled by command");
|
||||
+ /* re-enable HA source selection algorithm */
|
||||
+ priv->forced_source_clock = 0;
|
||||
+ /* select the best clock available */
|
||||
+ clock = ha_select_clock(priv, cfg);
|
||||
+ if (clock && clock != priv->master) {
|
||||
+ priv->master = clock;
|
||||
+ pr_notice("new source clock selected %s", clock->device);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ curlen = snprintf(response, resplen, "Success");
|
||||
+
|
||||
+ return curlen;
|
||||
+}
|
||||
+
|
||||
+static int ha_com_socket_handle_msg(struct phc2sys_private *priv,
|
||||
+ struct config *cfg)
|
||||
{
|
||||
struct pollfd pollfd[HA_SCK_N_FD];
|
||||
struct address sender;
|
||||
@@ -1348,6 +1419,11 @@ static int ha_com_socket_handle_msg(struct phc2sys_private *priv)
|
||||
} else if (strcmp((const char*)buffer, "forced lock") == 0) {
|
||||
cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "%s",
|
||||
priv->forced_source_clock ? "True" : "False");
|
||||
+ } else if (startsWith("enable lock", buffer)) {
|
||||
+ cnt = ha_handle_enable_lock_msg(priv, buffer, response,
|
||||
+ HA_SCK_BUFFER_SIZE);
|
||||
+ } else if (strcmp((const char*)buffer, "disable lock") == 0) {
|
||||
+ cnt = ha_handle_disable_lock_msg(priv, cfg, response, HA_SCK_BUFFER_SIZE);
|
||||
} else {
|
||||
cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "error: invalid command");
|
||||
}
|
||||
@@ -1410,7 +1486,7 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
}
|
||||
|
||||
if (ha_enabled) {
|
||||
- ha_com_socket_handle_msg(priv);
|
||||
+ ha_com_socket_handle_msg(priv, cfg);
|
||||
|
||||
if (priv->forced_source_clock) {
|
||||
/* HA automatic clock selection is disabled */
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,288 @@
|
||||
From 27b5c6afff470053b30ade14537be43f1c1c376d Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Fri, 4 Aug 2023 19:01:57 -0300
|
||||
Subject: [PATCH 43/47] Commands 'enable source' and 'disable source'.
|
||||
|
||||
These commands controls the list of clocks available to clock
|
||||
selection algorithm.
|
||||
|
||||
At startup all sources are enabled and can be selected as clock
|
||||
source. The 'disable source' command removes a given interface
|
||||
from the available list and it can't be selected any more. The
|
||||
'enable source' command re-enables the interface.
|
||||
|
||||
The last interface can't be disable. The disable command fails and
|
||||
returns an error indicating the given interface is the last one.
|
||||
|
||||
If the active clock source interface is disabled than a new one
|
||||
will be selected.
|
||||
|
||||
Every time the enable command is executed the clock selection
|
||||
algorithm is executed and the best available clock is selected.
|
||||
|
||||
The enable and disable source commands won't affect the active
|
||||
clock if one interface is forced lock as active.
|
||||
|
||||
The disabled interface is market with 'x' sign in the status
|
||||
command.
|
||||
|
||||
Test plan: enable source and disable source commands
|
||||
PASS: Verify a new interface is selected when the active one
|
||||
is disabled.
|
||||
PASS: Verify the primary interface is re-selected active after
|
||||
it is enabled back.
|
||||
PASS: Verify the disable source command fails when attempt to
|
||||
disable the last enabled interface.
|
||||
PASS: Verify the active interface don't change while one of them
|
||||
are forced lock as active.
|
||||
PASS: Verify the active interface dont't change after enabling
|
||||
an interface while in forced lock mode.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek
|
||||
<andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 55ac3f4131aaa999b1b7b9eec50b7cb7cebbf0d4 upstream]
|
||||
[commit c77de0acd3641833d2705e3929be2152bd5fb519 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 127 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index f89dc23..035ee21 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -98,6 +98,7 @@ struct clock {
|
||||
struct clockcheck *sanity_check;
|
||||
struct pmc_agent *node;
|
||||
int ha_priority;
|
||||
+ int enabled;
|
||||
};
|
||||
typedef LIST_HEAD(head, clock) clock_list_head_t;
|
||||
|
||||
@@ -228,6 +229,8 @@ static struct clock *clock_add(struct phc2sys_private *priv, char *device)
|
||||
c->sysoff_method = sysoff_probe(CLOCKID_TO_FD(clkid),
|
||||
priv->phc_readings);
|
||||
|
||||
+ c->enabled = 1;
|
||||
+
|
||||
LIST_INSERT_HEAD(&priv->clocks, c, list);
|
||||
return c;
|
||||
}
|
||||
@@ -278,6 +281,28 @@ static struct clock * clock_get_by_device(struct phc2sys_private *priv,
|
||||
return clock;
|
||||
}
|
||||
|
||||
+static size_t clock_count_enabled_sources(struct phc2sys_private *priv,
|
||||
+ struct clock *ignore)
|
||||
+{
|
||||
+ size_t count = 0;
|
||||
+ struct clock * clock = NULL;
|
||||
+
|
||||
+ LIST_FOREACH(clock, &priv->clocks, list) {
|
||||
+ /* ignore the dst clock */
|
||||
+ if (clock->state == PS_MASTER)
|
||||
+ continue;
|
||||
+
|
||||
+ if (clock == ignore)
|
||||
+ continue;
|
||||
+
|
||||
+ if (!clock->enabled)
|
||||
+ continue;
|
||||
+
|
||||
+ count++;
|
||||
+ }
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
static bool clock_match_ha_dds_requirements(struct clock *clock, struct config *cfg)
|
||||
{
|
||||
/* get requirements */
|
||||
@@ -404,6 +429,11 @@ static int clock_available_ha_src_clocks(struct phc2sys_private *priv, struct co
|
||||
continue;
|
||||
}
|
||||
|
||||
+ if (!clock->enabled) {
|
||||
+ pr_debug("clock %s is disabled", clock->device);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
/* get Default Data Set */
|
||||
if (!clock->node->dds_valid) {
|
||||
retries = 0;
|
||||
@@ -1267,7 +1297,8 @@ static int ha_handle_status_msg(struct phc2sys_private *priv, char *response,
|
||||
curlen += snprintf(response + curlen, resplen - curlen,
|
||||
" %c %9s %8d %10d 0x%2x 0x%4x %s %s %d\n",
|
||||
(priv->master == clock) ? '*' :
|
||||
- (priv->better == clock) ? '-' : ' ',
|
||||
+ (priv->better == clock) ? '-' :
|
||||
+ (!clock->enabled) ? 'x' : ' ',
|
||||
clock->device, clock->ha_priority,
|
||||
clock->node->dds.clockQuality.clockClass,
|
||||
clock->node->dds.clockQuality.clockAccuracy,
|
||||
@@ -1302,6 +1333,16 @@ static char * strAtColumn(char *msg, size_t column)
|
||||
return str;
|
||||
}
|
||||
|
||||
+static void ha_set_clock_source(struct phc2sys_private *priv, struct clock *clock)
|
||||
+{
|
||||
+ pr_notice("new clock source selected %s", clock->device);
|
||||
+
|
||||
+ priv->master = clock;
|
||||
+ priv->better = NULL;
|
||||
+ priv->stability_timer.tv_sec = 0;
|
||||
+ priv->stability_timer.tv_nsec = 0;
|
||||
+}
|
||||
+
|
||||
static int ha_handle_enable_lock_msg(struct phc2sys_private *priv, char *msg,
|
||||
char *response, size_t resplen)
|
||||
{
|
||||
@@ -1316,16 +1357,13 @@ static int ha_handle_enable_lock_msg(struct phc2sys_private *priv, char *msg,
|
||||
|
||||
clock = clock_get_by_device(priv, interface);
|
||||
if (!clock) {
|
||||
- return snprintf(response, resplen, "Error: Interface not found!");
|
||||
+ return snprintf(response, resplen, "Error: Interface not found");
|
||||
}
|
||||
|
||||
pr_info("HA automatic source selection is disabled by command");
|
||||
pr_info("Only interface %s will be used as source clock", clock->device);
|
||||
|
||||
- priv->master = clock;
|
||||
- priv->better = NULL;
|
||||
- priv->stability_timer.tv_sec = 0;
|
||||
- priv->stability_timer.tv_nsec = 0;
|
||||
+ ha_set_clock_source(priv, clock);
|
||||
|
||||
priv->forced_source_clock = 1;
|
||||
|
||||
@@ -1347,8 +1385,77 @@ static int ha_handle_disable_lock_msg(struct phc2sys_private *priv,
|
||||
/* select the best clock available */
|
||||
clock = ha_select_clock(priv, cfg);
|
||||
if (clock && clock != priv->master) {
|
||||
- priv->master = clock;
|
||||
- pr_notice("new source clock selected %s", clock->device);
|
||||
+ ha_set_clock_source(priv, clock);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ curlen = snprintf(response, resplen, "Success");
|
||||
+
|
||||
+ return curlen;
|
||||
+}
|
||||
+
|
||||
+static int ha_handle_enable_source_msg(struct phc2sys_private *priv,
|
||||
+ struct config *cfg, char *msg, char *response, size_t resplen)
|
||||
+{
|
||||
+ size_t curlen;
|
||||
+ char *interface = NULL;
|
||||
+ struct clock *clock = NULL;
|
||||
+
|
||||
+ interface = strAtColumn(msg, 3);
|
||||
+ if (strlen(interface) == 0) {
|
||||
+ return snprintf(response, resplen, "Error: Usage 'enable source <interface>'");
|
||||
+ }
|
||||
+
|
||||
+ clock = clock_get_by_device(priv, interface);
|
||||
+ if (!clock) {
|
||||
+ return snprintf(response, resplen, "Error: Interface not found");
|
||||
+ }
|
||||
+
|
||||
+ clock->enabled = 1;
|
||||
+
|
||||
+ if (!priv->forced_source_clock) {
|
||||
+ /* select the best clock available */
|
||||
+ clock = ha_select_clock(priv, cfg);
|
||||
+ if (clock && clock != priv->master) {
|
||||
+ ha_set_clock_source(priv, clock);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ curlen = snprintf(response, resplen, "Success");
|
||||
+
|
||||
+ return curlen;
|
||||
+}
|
||||
+
|
||||
+static int ha_handle_disable_source_msg(struct phc2sys_private *priv,
|
||||
+ struct config *cfg, char *msg, char *response, size_t resplen)
|
||||
+{
|
||||
+ size_t curlen;
|
||||
+ char *interface = NULL;
|
||||
+ struct clock *clock = NULL;
|
||||
+
|
||||
+ interface = strAtColumn(msg, 3);
|
||||
+ if (strlen(interface) == 0) {
|
||||
+ return snprintf(response, resplen, "Error: Usage 'disable source <interface>'");
|
||||
+ }
|
||||
+
|
||||
+ clock = clock_get_by_device(priv, interface);
|
||||
+ if (!clock) {
|
||||
+ return snprintf(response, resplen, "Error: Interface not found");
|
||||
+ }
|
||||
+
|
||||
+ /* check if is the last clock enabled */
|
||||
+ if (clock_count_enabled_sources(priv, clock) == 0) {
|
||||
+ return snprintf(response, resplen, "Error: Last interface enabled");
|
||||
+ }
|
||||
+
|
||||
+ clock->enabled = 0;
|
||||
+
|
||||
+ /* disabling clock source */
|
||||
+ if (clock == priv->master && !priv->forced_source_clock) {
|
||||
+ /* select the best clock available */
|
||||
+ clock = ha_select_clock(priv, cfg);
|
||||
+ if (clock && clock != priv->master) {
|
||||
+ ha_set_clock_source(priv, clock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,9 +1530,17 @@ static int ha_com_socket_handle_msg(struct phc2sys_private *priv,
|
||||
cnt = ha_handle_enable_lock_msg(priv, buffer, response,
|
||||
HA_SCK_BUFFER_SIZE);
|
||||
} else if (strcmp((const char*)buffer, "disable lock") == 0) {
|
||||
- cnt = ha_handle_disable_lock_msg(priv, cfg, response, HA_SCK_BUFFER_SIZE);
|
||||
+ cnt = ha_handle_disable_lock_msg(priv, cfg, response,
|
||||
+ HA_SCK_BUFFER_SIZE);
|
||||
+ } else if (startsWith("enable source", buffer)) {
|
||||
+ cnt = ha_handle_enable_source_msg(priv, cfg, buffer, response,
|
||||
+ HA_SCK_BUFFER_SIZE);
|
||||
+ } else if (startsWith("disable source", buffer)) {
|
||||
+ cnt = ha_handle_disable_source_msg(priv, cfg, buffer, response,
|
||||
+ HA_SCK_BUFFER_SIZE);
|
||||
} else {
|
||||
- cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "error: invalid command");
|
||||
+ cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE,
|
||||
+ "Error: Invalid command");
|
||||
}
|
||||
|
||||
fprintf(stderr, "ha_com_socket: response: \n%s", (char*)response);
|
||||
@@ -1498,10 +1613,7 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
if (priv->clock_state_changed) {
|
||||
clock = check_and_select_clock(priv, cfg);
|
||||
if (clock && clock != priv->master) {
|
||||
- priv->master = clock;
|
||||
- priv->better = NULL;
|
||||
- priv->stability_timer.tv_sec = 0;
|
||||
- priv->stability_timer.tv_nsec = 0;
|
||||
+ ha_set_clock_source(priv, clock);
|
||||
}
|
||||
|
||||
priv->clock_state_changed = 0;
|
||||
@@ -1514,11 +1626,7 @@ static int do_loop(struct phc2sys_private *priv, struct config *cfg, int subscri
|
||||
if ((now.tv_sec > priv->stability_timer.tv_sec) ||
|
||||
(now.tv_sec == priv->stability_timer.tv_sec &&
|
||||
now.tv_nsec > priv->stability_timer.tv_nsec)) {
|
||||
- pr_notice("new source clock selected %s", priv->better->device);
|
||||
- priv->master = priv->better;
|
||||
- priv->better = NULL;
|
||||
- priv->stability_timer.tv_sec = 0;
|
||||
- priv->stability_timer.tv_nsec = 0;
|
||||
+ ha_set_clock_source(priv, priv->better);
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,201 @@
|
||||
From 2d40cc7cf52bbf054856c34902e4bda9f13ebb79 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 7 Aug 2023 14:55:12 -0300
|
||||
Subject: [PATCH 44/47] Stream type phc2sys com socket
|
||||
|
||||
The type of the socket was changed from datagram to stream.
|
||||
|
||||
Test plan: status/show commands
|
||||
PASS: Verify status command response
|
||||
PASS: Verify forced lock command response
|
||||
PASS: Verify clock source command response
|
||||
|
||||
Test plan: enable lock and disable lock commands
|
||||
PASS: Verify the enable lock changes the clock source to the given
|
||||
interface.
|
||||
PASS: Verify that disable lock command makes the better available
|
||||
clock to be selected again.
|
||||
|
||||
Test plan: disable source and enable source commands
|
||||
PASS: Verify a new interface is selected when the active one
|
||||
is disabled.
|
||||
PASS: Verify the primary interface is re-selected active after
|
||||
it is enabled back.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek
|
||||
<andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit b4f79cb626d6e40cf1d5aa2c5d5fba89e2c2e340 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 76 +++++++++++++++++++++++++++----------------------------
|
||||
1 file changed, 38 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 035ee21..a597014 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -1203,14 +1203,12 @@ static int ha_com_socket_close(int fd)
|
||||
struct sockaddr_un sa;
|
||||
socklen_t len = sizeof(sa);
|
||||
|
||||
- // if (fd < 0)
|
||||
- // return -1;
|
||||
-
|
||||
if (!getsockname(fd, (struct sockaddr *) &sa, &len) &&
|
||||
sa.sun_family == AF_LOCAL) {
|
||||
unlink(sa.sun_path);
|
||||
}
|
||||
|
||||
+ shutdown(fd, SHUT_RDWR);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -1219,9 +1217,10 @@ static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
{
|
||||
int fd, err;
|
||||
struct sockaddr_un sa;
|
||||
+ const int backlog = 50;
|
||||
const char *name = config_get_string(cfg, NULL, "ha_phc2sys_com_socket");
|
||||
|
||||
- fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
|
||||
+ fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if (fd < 0) {
|
||||
pr_err("ha_com_socket: failed to create socket: %m");
|
||||
return -1;
|
||||
@@ -1238,22 +1237,27 @@ static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ err = listen(fd, backlog);
|
||||
+ if (err < 0) {
|
||||
+ pr_err("ha_com_socket: listen failed: %m");
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
*fd_out = fd;
|
||||
chmod(name, HA_SCK_FILEMODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int ha_com_socket_recv(int fd, void *buf, size_t buflen,
|
||||
- struct address *addr)
|
||||
+static int ha_com_socket_recv(int fd, void *buf, size_t buflen)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
- addr->len = sizeof(addr->sun);
|
||||
- cnt = recvfrom(fd, buf, buflen, 0, &addr->sa, &addr->len);
|
||||
+ cnt = read(fd, buf, buflen);
|
||||
if (cnt <= 0) {
|
||||
- pr_err("ha_com_socket: recvfrom failed: %m");
|
||||
- return cnt;
|
||||
+ pr_err("ha_com_socket: read failed: %m");
|
||||
+ return -errno;
|
||||
}
|
||||
|
||||
((char*)buf)[cnt] = '\0';
|
||||
@@ -1261,13 +1265,13 @@ static int ha_com_socket_recv(int fd, void *buf, size_t buflen,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int ha_com_socket_send(int fd, struct address *addr, void *buf,
|
||||
- size_t buflen)
|
||||
+static int ha_com_socket_send(int fd, void *buf, size_t buflen)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
- cnt = sendto(fd, buf, buflen, 0, &addr->sa, addr->len);
|
||||
- if (cnt < 1) {
|
||||
+ cnt = send(fd, buf, buflen, 0);
|
||||
+ if (cnt < 0) {
|
||||
+ pr_err("ha_com_socket: send failed: %m");
|
||||
return -errno;
|
||||
}
|
||||
return cnt;
|
||||
@@ -1467,48 +1471,42 @@ static int ha_handle_disable_source_msg(struct phc2sys_private *priv,
|
||||
static int ha_com_socket_handle_msg(struct phc2sys_private *priv,
|
||||
struct config *cfg)
|
||||
{
|
||||
- struct pollfd pollfd[HA_SCK_N_FD];
|
||||
- struct address sender;
|
||||
- int cnt, res = 0;
|
||||
- int timeout = 0;
|
||||
+ int cnt, res = 0, fd;
|
||||
void * buffer = NULL;
|
||||
void * response = NULL;
|
||||
|
||||
while(1) {
|
||||
- pollfd[0].fd = priv->ha_socket_fd;
|
||||
- pollfd[0].events = POLLIN|POLLPRI;
|
||||
-
|
||||
- cnt = poll(pollfd, HA_SCK_N_FD, timeout);
|
||||
- if (cnt < 0) {
|
||||
- pr_err("ha_com_socket: poll failed: %m");
|
||||
- res = -1;
|
||||
- break;
|
||||
- }
|
||||
- if (!cnt) {
|
||||
- /* timeout and fd wasn't ready */
|
||||
+ fd = accept(priv->ha_socket_fd, NULL, NULL);
|
||||
+ if (fd < 0) {
|
||||
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
+ /* no msg available */
|
||||
+ } else {
|
||||
+ pr_err("ha_com_socket: accept failed: %m");
|
||||
+ res = -1;
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!(pollfd[0].revents & (POLLIN|POLLPRI)))
|
||||
- break;
|
||||
-
|
||||
buffer = malloc(HA_SCK_BUFFER_SIZE);
|
||||
if (!buffer) {
|
||||
pr_err("ha_com_socket: failed to allocate memory for message");
|
||||
+ close(fd);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
- res = ha_com_socket_recv(pollfd[0].fd, buffer, HA_SCK_BUFFER_SIZE, &sender);
|
||||
- if (res < 0)
|
||||
+ res = ha_com_socket_recv(fd, buffer, HA_SCK_BUFFER_SIZE);
|
||||
+ if (res < 0) {
|
||||
+ close(fd);
|
||||
break;
|
||||
+ }
|
||||
|
||||
- fprintf(stderr, "ha_com_socket: received: %s\n", (char*)buffer);
|
||||
- fprintf(stderr, "ha_com_socket: recvd from: %s\n", ((struct sockaddr_un*)&sender.sa)->sun_path);
|
||||
+ pr_debug("ha_com_socket: command received: %s", (char*)buffer);
|
||||
|
||||
response = malloc(HA_SCK_BUFFER_SIZE);
|
||||
if (!response) {
|
||||
pr_err("ha_com_socket: failed to allocate memory for response message");
|
||||
+ close(fd);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1543,9 +1541,11 @@ static int ha_com_socket_handle_msg(struct phc2sys_private *priv,
|
||||
"Error: Invalid command");
|
||||
}
|
||||
|
||||
- fprintf(stderr, "ha_com_socket: response: \n%s", (char*)response);
|
||||
+ pr_debug("ha_com_socket: response: %s", (char*)response);
|
||||
|
||||
- res = ha_com_socket_send(pollfd[0].fd, &sender, response, cnt);
|
||||
+ res = ha_com_socket_send(fd, response, cnt);
|
||||
+
|
||||
+ close(fd);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,92 @@
|
||||
From 2896553d6dfa975102cba4cc45105b000ec0ae52 Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Tue, 8 Aug 2023 13:10:50 -0300
|
||||
Subject: [PATCH 45/47] Functions starts_with and str_at_column
|
||||
|
||||
Renaming starts_with and str_at_column functions to match ptp4l code
|
||||
style.
|
||||
|
||||
Test plan: commands
|
||||
PASS: Verify 'enable lock <interface>', 'disabel source <interface>' and
|
||||
'enable source <interface>' still work.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek
|
||||
<andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit f43f86eab5f8f5d2c9895d290d4bdfd6f60853f8 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index a597014..6965162 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -1318,12 +1318,12 @@ static int ha_handle_status_msg(struct phc2sys_private *priv, char *response,
|
||||
return curlen;
|
||||
}
|
||||
|
||||
-static bool startsWith(const char *prefix, const char *str)
|
||||
+static bool starts_with(const char *prefix, const char *str)
|
||||
{
|
||||
return 0 == strncmp(prefix, str, strlen(prefix) - 1);
|
||||
}
|
||||
|
||||
-static char * strAtColumn(char *msg, size_t column)
|
||||
+static char * str_at_column(char *msg, size_t column)
|
||||
{
|
||||
int i;
|
||||
char * str = NULL;
|
||||
@@ -1354,7 +1354,7 @@ static int ha_handle_enable_lock_msg(struct phc2sys_private *priv, char *msg,
|
||||
char *interface = NULL;
|
||||
struct clock *clock = NULL;
|
||||
|
||||
- interface = strAtColumn(msg, 3);
|
||||
+ interface = str_at_column(msg, 3);
|
||||
if (strlen(interface) == 0) {
|
||||
return snprintf(response, resplen, "Error: Usage 'enable lock <interface>'");
|
||||
}
|
||||
@@ -1405,7 +1405,7 @@ static int ha_handle_enable_source_msg(struct phc2sys_private *priv,
|
||||
char *interface = NULL;
|
||||
struct clock *clock = NULL;
|
||||
|
||||
- interface = strAtColumn(msg, 3);
|
||||
+ interface = str_at_column(msg, 3);
|
||||
if (strlen(interface) == 0) {
|
||||
return snprintf(response, resplen, "Error: Usage 'enable source <interface>'");
|
||||
}
|
||||
@@ -1437,7 +1437,7 @@ static int ha_handle_disable_source_msg(struct phc2sys_private *priv,
|
||||
char *interface = NULL;
|
||||
struct clock *clock = NULL;
|
||||
|
||||
- interface = strAtColumn(msg, 3);
|
||||
+ interface = str_at_column(msg, 3);
|
||||
if (strlen(interface) == 0) {
|
||||
return snprintf(response, resplen, "Error: Usage 'disable source <interface>'");
|
||||
}
|
||||
@@ -1524,16 +1524,16 @@ static int ha_com_socket_handle_msg(struct phc2sys_private *priv,
|
||||
} else if (strcmp((const char*)buffer, "forced lock") == 0) {
|
||||
cnt = snprintf((char*)response, HA_SCK_BUFFER_SIZE, "%s",
|
||||
priv->forced_source_clock ? "True" : "False");
|
||||
- } else if (startsWith("enable lock", buffer)) {
|
||||
+ } else if (starts_with("enable lock", buffer)) {
|
||||
cnt = ha_handle_enable_lock_msg(priv, buffer, response,
|
||||
HA_SCK_BUFFER_SIZE);
|
||||
} else if (strcmp((const char*)buffer, "disable lock") == 0) {
|
||||
cnt = ha_handle_disable_lock_msg(priv, cfg, response,
|
||||
HA_SCK_BUFFER_SIZE);
|
||||
- } else if (startsWith("enable source", buffer)) {
|
||||
+ } else if (starts_with("enable source", buffer)) {
|
||||
cnt = ha_handle_enable_source_msg(priv, cfg, buffer, response,
|
||||
HA_SCK_BUFFER_SIZE);
|
||||
- } else if (startsWith("disable source", buffer)) {
|
||||
+ } else if (starts_with("disable source", buffer)) {
|
||||
cnt = ha_handle_disable_source_msg(priv, cfg, buffer, response,
|
||||
HA_SCK_BUFFER_SIZE);
|
||||
} else {
|
||||
--
|
||||
2.25.1
|
||||
|
@ -0,0 +1,78 @@
|
||||
From f480fb54182da36baeb35bac90154abafcaf854a Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Tue, 8 Aug 2023 14:06:55 -0300
|
||||
Subject: [PATCH 46/47] Robustness improvements to phc2sys socket
|
||||
|
||||
When phc2sys abnormally exits the socket file might remain created.
|
||||
To avoid error when phc2sys is relaunched, the exixting file is
|
||||
deleted before recriating the socket.
|
||||
|
||||
If the peer application closes the socket before sending the
|
||||
response completely, it will cause a broken pipe error. The
|
||||
send function generates a SIGPIPE on broken pipe errors,
|
||||
killing the phc2sys process unless MSG_NOSIGNAL flag is set.
|
||||
|
||||
Test plan: socket file
|
||||
PASS: Verify that phc2sys can restart normally after killing it.
|
||||
|
||||
Test plan: SIGPIPE
|
||||
PASS: Verify the phc2sys application don't exit when client socket
|
||||
is closed before the respose is sent.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek
|
||||
<andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 8b3765b3f104a90a487fbcb0f61074c7677c215e upstream]
|
||||
[commit 50ad1c6f81a706b8be6689bea2ba2db215cf3dc3 upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index 6965162..edc626f 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -1218,7 +1218,9 @@ static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
int fd, err;
|
||||
struct sockaddr_un sa;
|
||||
const int backlog = 50;
|
||||
- const char *name = config_get_string(cfg, NULL, "ha_phc2sys_com_socket");
|
||||
+ const char *path = config_get_string(cfg, NULL, "ha_phc2sys_com_socket");
|
||||
+
|
||||
+ unlink(path);
|
||||
|
||||
fd = socket(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if (fd < 0) {
|
||||
@@ -1228,7 +1230,7 @@ static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_LOCAL;
|
||||
- strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1);
|
||||
+ strncpy(sa.sun_path, path, sizeof(sa.sun_path) - 1);
|
||||
|
||||
err = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
|
||||
if (err < 0) {
|
||||
@@ -1245,7 +1247,7 @@ static int ha_com_socket_open(int *fd_out, struct config *cfg)
|
||||
}
|
||||
|
||||
*fd_out = fd;
|
||||
- chmod(name, HA_SCK_FILEMODE);
|
||||
+ chmod(path, HA_SCK_FILEMODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1269,7 +1271,7 @@ static int ha_com_socket_send(int fd, void *buf, size_t buflen)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
- cnt = send(fd, buf, buflen, 0);
|
||||
+ cnt = send(fd, buf, buflen, MSG_NOSIGNAL);
|
||||
if (cnt < 0) {
|
||||
pr_err("ha_com_socket: send failed: %m");
|
||||
return -errno;
|
||||
--
|
||||
2.25.1
|
||||
|
110
base/linuxptp/debian/patches/0047-phc2sys-without-w-option.patch
Normal file
110
base/linuxptp/debian/patches/0047-phc2sys-without-w-option.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From c5e1599748877f16bfd1dea6910f6b8b57be7ddd Mon Sep 17 00:00:00 2001
|
||||
From: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
Date: Mon, 7 Aug 2023 18:19:37 -0300
|
||||
Subject: [PATCH 47/47] phc2sys without -w option.
|
||||
|
||||
Fix bad clock and pmc initialization when -w command argument
|
||||
is not provided.
|
||||
|
||||
The pmc agent must be created and mapped to a clock source even
|
||||
in cases the -w (wait for ptp4l) option is not used.
|
||||
|
||||
Test plan:
|
||||
PASS: Verify phc2sys initializes without -w argument.
|
||||
PASS: Verify phc2sys initializes with two ptp4l interfaces
|
||||
configured.
|
||||
|
||||
Reviewed-by: Cole Walker <cole.walker@windriver.com>
|
||||
Reviewed-by: Andre Fernando Zanella Kantek
|
||||
<andrefernandozanella.kantek@windriver.com>
|
||||
|
||||
[commit 10fa27f5829787c15e9ae59c45703328ca4e644f upstream]
|
||||
|
||||
Signed-off-by: Andre Mauricio Zelak <andre.zelak@windriver.com>
|
||||
---
|
||||
phc2sys.c | 34 ++++++++++++++--------------------
|
||||
1 file changed, 14 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/phc2sys.c b/phc2sys.c
|
||||
index edc626f..065b7f0 100644
|
||||
--- a/phc2sys.c
|
||||
+++ b/phc2sys.c
|
||||
@@ -2254,6 +2254,15 @@ int main(int argc, char *argv[])
|
||||
if (priv.master == NULL) {
|
||||
priv.master = src;
|
||||
}
|
||||
+ if (i > 0) {
|
||||
+ node = pmc_agent_add(&priv, i);
|
||||
+ if (!node)
|
||||
+ goto end;
|
||||
+ }
|
||||
+ /* map clock to pmc agent node */
|
||||
+ src->node = node;
|
||||
+ pr_debug("pmc node index %d assigned to source interface %s",
|
||||
+ node->index, src->device);
|
||||
if (ha_enabled) {
|
||||
src->ha_priority = config_get_int(cfg, src->device, "ha_priority");
|
||||
}
|
||||
@@ -2286,35 +2295,22 @@ int main(int argc, char *argv[])
|
||||
r = -1;
|
||||
|
||||
if (wait_sync) {
|
||||
- i = 0;
|
||||
LIST_FOREACH(src, &priv.clocks, list) {
|
||||
|
||||
/* skip dst clock */
|
||||
- if (src == dst) {
|
||||
+ if (src->state == PS_MASTER)
|
||||
continue;
|
||||
- }
|
||||
-
|
||||
- if (i > 0) {
|
||||
- node = pmc_agent_add(&priv, i);
|
||||
- if (!node)
|
||||
- goto end;
|
||||
- }
|
||||
|
||||
/* uds local is formated '/var/run/phc2sys.<pid>.<source_interface>' */
|
||||
snprintf(uds_local, sizeof(uds_local), "/var/run/phc2sys.%d.%s",
|
||||
getpid(), src->device);
|
||||
|
||||
- if (init_pmc_node(cfg, node, uds_local,
|
||||
+ if (init_pmc_node(cfg, src->node, uds_local,
|
||||
phc2sys_recv_subscribed, &priv))
|
||||
goto end;
|
||||
|
||||
- /* map clock to pmc agent node */
|
||||
- src->node = node;
|
||||
- pr_debug("pmc node index %d source clock %s initialized",
|
||||
- node->index, src->device);
|
||||
-
|
||||
while (is_running()) {
|
||||
- r = run_pmc_wait_sync(node, 1000);
|
||||
+ r = run_pmc_wait_sync(src->node, 1000);
|
||||
if (r < 0)
|
||||
goto end;
|
||||
if (r > 0)
|
||||
@@ -2324,7 +2320,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!priv.forced_sync_offset) {
|
||||
- r = pmc_agent_query_utc_offset(node, 1000);
|
||||
+ r = pmc_agent_query_utc_offset(src->node, 1000);
|
||||
if (r) {
|
||||
pr_err("failed to get UTC offset");
|
||||
goto end;
|
||||
@@ -2334,10 +2330,8 @@ int main(int argc, char *argv[])
|
||||
if (priv.forced_sync_offset ||
|
||||
(src->clkid != CLOCK_REALTIME && dst->clkid != CLOCK_REALTIME) ||
|
||||
src->clkid == CLOCK_INVALID) {
|
||||
- pmc_agent_disable(node);
|
||||
+ pmc_agent_disable(src->node);
|
||||
}
|
||||
-
|
||||
- ++i;
|
||||
}
|
||||
|
||||
if (ha_enabled && !priv.forced_source_clock) {
|
||||
--
|
||||
2.25.1
|
||||
|
@ -8,3 +8,40 @@
|
||||
0008-sysoff-Change-log-level-of-ioctl-error-messages.patch
|
||||
0009-sysoff-Retry-on-EBUSY-when-probing-supported-ioctls.patch
|
||||
0010-phc2sys-Don-t-exit-when-reading-of-PHC-fails-with-EB.patch
|
||||
0011-phc2sys-extract-PMC-functionality-into-a-smaller-str.patch
|
||||
0012-phc2sys-make-PMC-functions-non-static.patch
|
||||
0013-phc2sys-break-out-pmc-code-into-pmc_common.c.patch
|
||||
0014-Introduce-the-PMC-agent-module.patch
|
||||
0015-pmc_agent-Rename-pmc_node-to-something-more-descript.patch
|
||||
0016-pmc_agent-Hide-the-implementation.patch
|
||||
0017-Find-a-better-home-for-the-management-TLV-ID-helper-.patch
|
||||
0018-Find-a-better-home-for-the-management-TLV-data-helpe.patch
|
||||
0019-Introduce-error-codes-for-the-run_pmc-method.patch
|
||||
0020-pmc_agent-Convert-the-subscribe-method-into-the-cano.patch
|
||||
0021-pmc_agent-Simplify-the-update-method.patch
|
||||
0022-pmc_agent-Simplify-logic-in-update-method.patch
|
||||
0023-pmc_agent-Remove-bogus-comparison-between-last-updat.patch
|
||||
0024-pmc_agent-Perform-time-comparison-using-positive-log.patch
|
||||
0025-pmc_agent-Rename-the-update-method-and-attempt-to-do.patch
|
||||
0026-phc2sys-Fix-null-pointer-de-reference-in-manual-mode.patch
|
||||
0027-pmc_agent-Convert-the-method-that-queries-TAI-UTC-of.patch
|
||||
0028-pmc_agent-Convert-the-method-that-queries-the-port-p.patch
|
||||
0029-pmc_agent-Generalize-the-method-that-queries-the-loc.patch
|
||||
0030-pmc_agent-Simplify-the-method-that-gets-of-the-numbe.patch
|
||||
0031-pmc_agent-Let-the-update-method-poll-for-push-events.patch
|
||||
0032-phc2sys-Fix-regression-in-the-automatic-mode.patch
|
||||
0033-Implement-push-notification-for-TIME_STATUS_NP.patch
|
||||
0034-clock-Rename-UDS-variables-to-read-write.patch
|
||||
0035-clock-Add-read-only-UDS-port-for-monitoring.patch
|
||||
0036-Rename-management-ID-macros.patch
|
||||
0037-Enhance-phc2sys-to-accept-multiple-ptp4l-inputs.patch
|
||||
0038-Best-source-selection-algorithm.patch
|
||||
0039-Select-best-source-clock-after-state-changes.patch
|
||||
0040-Forced-lock-a-clock-source-in-configuration.patch
|
||||
0041-HA-phc2sys-com-socket.patch
|
||||
0042-Commands-enable-lock-and-disable-lock.patch
|
||||
0043-Commands-enable-source-and-disable-source.patch
|
||||
0044-Stream-type-phc2sys-com-socket.patch
|
||||
0045-Functions-starts_with-and-str_at_column.patch
|
||||
0046-Robustness-improvements-to-phc2sys-socket.patch
|
||||
0047-phc2sys-without-w-option.patch
|
Loading…
Reference in New Issue
Block a user