Re: [Linuxptp-devel] [PATCH v6 0/2] don't report random errno on timeout

2023-08-18 Thread Jacob Keller



On 7/26/2023 3:07 PM, Lukasz Plachno wrote:
> Improve error reporting in case of timeout while reading tx timestamp,
> extend documentation with information about increasing kthread priority.
> 
> v6:
>  - Manual: unify style for commands, indent shell examples and error log
>  - Manual: use SCHED_FIFO instead of SCHED_RR in example for bumping
>kthreads priority
> v5:
>  - Use ptp4l man in a subject as the commit does not change code
> v4:
>  - added generic example for setting priority for PTP kworkers
>  - simplified both example commands (generic and ICE) for setting
>priority
> v3:
>  - v2 resent by accident
> v2:
>  - added documentation for increasing kthread priority
> 
> ---
> 

This version looks good to me.

Reviewed-by: Jacob Keller 

> Lukasz Plachno (1):
>   ptp4l man: Add description for setting kthreads priorities
> 
> Przemek Kitszel (1):
>   sk: don't report random errno on timeout
> 
>  ptp4l.8 | 36 
>  sk.c| 14 +-
>  2 files changed, 45 insertions(+), 5 deletions(-)
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 0/2 v4] sk: don't report random errno on timeout

2023-07-21 Thread Jacob Keller



On 7/21/2023 2:10 AM, Lukasz Plachno wrote:
> Improve error reporting in case of timeout while reading tx timestamp,
> extend documentation with information about increasing kthread priority.
> 
> v4:
>  - added generic example for setting priority for PTP kworkers
>  - simplified both example commands (generic and ICE) for setting
>priority
> v3:
>  - v2 resent by accident
> v2:
>  - added documentation for increasing kthread priority
> 
> ---
> 
> Lukasz Plachno (1):
>   ptp4l: Add description for setting kthreads priorities
> 
> Przemek Kitszel (1):
>   sk: don't report random errno on timeout
> 
>  ptp4l.8 | 32 
>  sk.c| 14 +-
>  2 files changed, 41 insertions(+), 5 deletions(-)
> 

This version looks good to me.

Reviewed-by: Jacob Keller 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v1 1/4] phc2sys: Rename phc2sys_private to domain.

2023-07-21 Thread Jacob Keller



On 7/20/2023 7:33 AM, Miroslav Lichvar wrote:
> Rename the phc2sys_private structure to domain in preparation for
> support of multiple domains.
> 
> While touching the lines of code, also rename master to source clock.
> 
> Signed-off-by: Miroslav Lichvar 

Reviewed-by: Jacob Keller 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v1 2/4] phc2sys: Create pmc agent after processing options.

2023-07-21 Thread Jacob Keller



On 7/20/2023 7:33 AM, Miroslav Lichvar wrote:
> Keep configuration settings in a separate domain and copy them to the
> actual domain just before creating the pmc agent. This will be needed to
> share the settings between multiple domains.
> 
> Signed-off-by: Miroslav Lichvar 
> ---


Reviewed-by: Jacob Keller 



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v1 3/4] phc2sys: Shallow do_loop().

2023-07-21 Thread Jacob Keller



On 7/20/2023 7:33 AM, Miroslav Lichvar wrote:
> Move the measurements and updates of clocks from do_loop() to separate
> function.
> 
> Signed-off-by: Miroslav Lichvar 
> ---


Reviewed-by: Jacob Keller 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] sk: don't report random errno on timeout

2023-07-17 Thread Jacob Keller



On 7/16/2023 1:27 PM, Richard Cochran wrote:
> On Fri, Jul 14, 2023 at 08:43:30PM +, Keller, Jacob E wrote:
> 
>>> With this patch applied, one will get proper error in last line,
>>> "Timer expired", and more modern suggestion about how to approach fixing it
>>>
>>
>>
>> I think changing the message about what might be causing timeout is
>> unnecessary. It may be helpful purely in the context of some
>> devices, but it is not a good general message as not all hardware
>> and drivers have the same design. In the *general* case if this
>> timeout is hit then it is usually a bug in the driver for that
>> hardware. In the specific case for ice hardware, the mention of
>> thread starvation is accurate, but that is unlikely to be general
>> across all hardware.
> 
> But the point about kthread priority is a good hint.  How about
> keeping the part about possible driver bug (since we have had many,
> Many, MANY questions on this list when somebody is developing a new
> driver) and adding a hint about kworker scheduling priority?
> 

Sounds good to me. It might help us reduce our own support burden when
users say "I get this message that says its a driver bug, and I already
tried , but still see timeouts", and then
we need to educate them on priority to ensure that they aren't starving
the thread which processes timestamps.

But I agree keeping the message about it possibly being a bug is
important because it has been caused by drivers a lot in the past.

Maybe something like:

timed out while polling for tx timestamp
increasing tx_timestamp_timeout or increasing priority of relevant
kworker threads may correct this issue, but it is likely caused by a
driver bug

Thanks,
Jake

>> Thus, I think we should leave the error message alone and just fix
>> the errno value. Improving the errno value is important since it
>> would be less confusing than seeing arbitrary error values which are
>> unrelated to the actual error.
> 
> Yeah, errno fix is needed>
> Thanks,
> Richard


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 1/6] Add doubly attached clock support

2023-07-05 Thread Jacob Keller



On 7/4/2023 3:30 AM, Stephan Wurm wrote:
> Standard IEC 21439-3:2016 Appendix A extends the PTPv2 standard by the
> definition of doubly attached clocks (DAC) via redundant ports (either
> connected by HSR or PRP). Therefore, the state machine is extended by
> state PASSIVE_SLAVE and transition PSLAVE.
> 
> In order to take advantage of the DAC feature, two interfaces need to
> be configured as redundant port by explicitly selecting the respective
> other interface via the `paired_interface` configuration option.
> 
> The new state is reported as PASSIVE via the management interface,
> remaining compatible with the PTPv2 standard.
> 
> Signed-off-by: Stephan Wurm 
> ---
>  bmc.c | 10 
>  clock.c   |  4 
>  config.c  |  1 +
>  e2e_tc.c  |  1 +
>  fsm.c | 71 
> +++
>  fsm.h |  2 ++
>  p2p_tc.c  |  2 ++
>  port.c| 52 
>  port.h| 17 +
>  port_private.h|  4 
>  port_signaling.c  |  1 +
>  tc.c  |  2 ++
>  unicast_service.c |  1 +
>  util.c|  4 +++-
>  14 files changed, 167 insertions(+), 5 deletions(-)
> 
> diff --git a/bmc.c b/bmc.c
> index ebc0789..1e1d83f 100644
> --- a/bmc.c
> +++ b/bmc.c
> @@ -130,12 +130,14 @@ enum port_state bmc_state_decision(struct clock *c, 
> struct port *r,
>  int (*compare)(struct dataset *a, struct 
> dataset *b))
>  {
>   struct dataset *clock_ds, *clock_best, *port_best;
> + struct port *paired_port;
>   enum port_state ps;
>  
>   clock_ds = clock_default_ds(c);
>   clock_best = clock_best_foreign(c);
>   port_best = port_best_foreign(r);
>   ps = port_state(r);
> + paired_port = port_paired_port(r);
>  
>   /*
>* This scenario is particularly important in the designated_slave_fsm
> @@ -167,6 +169,14 @@ enum port_state bmc_state_decision(struct clock *c, 
> struct port *r,
>   return PS_SLAVE; /*S1*/
>   }
>  
> + /*
> +  * This scenario handles the PASSIVE_SLAVE transition according to
> +  * IEC 62439-3 standard in case of a doubly attached clock.
> +  */
> + if (paired_port && (clock_best_port(c) == paired_port)) {
> + return PS_PASSIVE_SLAVE;
> + }
> +
>   if (compare(clock_best, port_best) == A_BETTER_TOPO) {
>   return PS_PASSIVE; /*P2*/
>   } else {
> diff --git a/clock.c b/clock.c
> index 5a64613..cff2475 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -1009,6 +1009,7 @@ static int clock_add_port(struct clock *c, const char 
> *phc_device,
>   return -1;
>   }
>   LIST_FOREACH(piter, >ports, list) {
> + port_pair(piter, p);
>   lastp = piter;
>   }
>   if (lastp) {
> @@ -2242,6 +2243,9 @@ static void handle_state_decision_event(struct clock *c)
>   clock_update_slave(c);
>   event = EV_RS_SLAVE;
>   break;
> + case PS_PASSIVE_SLAVE:
> + event = EV_RS_PSLAVE;
> + break;
>   default:
>   event = EV_FAULT_DETECTED;
>   break;
> diff --git a/config.c b/config.c
> index b104f1b..aadd3d9 100644
> --- a/config.c
> +++ b/config.c
> @@ -298,6 +298,7 @@ struct config_item config_tab[] = {
>   GLOB_ITEM_INT("offsetScaledLogVariance", 0x, 0, UINT16_MAX),
>   PORT_ITEM_INT("operLogPdelayReqInterval", 0, INT8_MIN, INT8_MAX),
>   PORT_ITEM_INT("operLogSyncInterval", 0, INT8_MIN, INT8_MAX),
> + PORT_ITEM_STR("paired_interface", ""),
>   PORT_ITEM_INT("path_trace_enabled", 0, 0, 1),
>   PORT_ITEM_INT("phc_index", -1, -1, INT_MAX),
>   GLOB_ITEM_DBL("pi_integral_const", 0.0, 0.0, DBL_MAX),
> diff --git a/e2e_tc.c b/e2e_tc.c
> index 2f8e821..94099eb 100644
> --- a/e2e_tc.c
> +++ b/e2e_tc.c
> @@ -69,6 +69,7 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
> mdiff)
>   flush_delay_req(p);
>   /* fall through */
>   case PS_SLAVE:
> + case PS_PASSIVE_SLAVE:
>   port_set_announce_tmo(p);
>   break;
>   };
> diff --git a/fsm.c b/fsm.c
> index ce6efad..9679fea 100644
> --- a/fsm.c
> +++ b/fsm.c
> @@ -80,6 +80,9 @@ enum port_state ptp_fsm(enum port_state state, enum 
> fsm_event event, int mdiff)
>   case EV_RS_PASSIVE:
>   next = PS_PASSIVE;
>   break;
> + case EV_RS_PSLAVE:
> + next = PS_PASSIVE_SLAVE;
> + break;
>   default:
>   break;
>   }
> @@ -102,6 +105,9 @@ enum port_state ptp_fsm(enum port_state state, enum 
> fsm_event event, int mdiff)
>   case EV_RS_PASSIVE:
>   next = PS_PASSIVE;
>   

Re: [Linuxptp-devel] [PATCH v1] servo: Implement offset statistics

2023-07-05 Thread Jacob Keller



On 7/3/2023 7:18 AM, Maciek Machnikowski wrote:
> Currently running servo reports current offsets in numerous tools, but lacks
> statistical data. Having the basic statistical data makes it easier to monitor
> running servo (especially on long runs) and determine servo performance.
> 
> This patch reuses existing statistics implemented for tracking clock 
> parameters
> and prints basic offset min/avg/max/stddev/rms stats on servo destroy call
> (when the tool is treminated).
> 

Only printing the stats on removal seems a bit odd. I wonder if it would
make sense to have a (configurable?) periodic reporting rate that would
print the servo stats maybe every N servo updates, or at intervals?

I like the idea overall, as seeing the status is useful. Alternatively,
it could be something exposed via a non portable operation on the
management port if we don't think it makes sense to log it.

> Signed-off-by: Maciek Machnikowski 
> ---
>  makefile|  2 +-
>  servo.c | 42 ++
>  servo_private.h |  6 ++
>  3 files changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/makefile b/makefile
> index 3e3b8b3..a1dea07 100644
> --- a/makefile
> +++ b/makefile
> @@ -24,7 +24,7 @@ CFLAGS  = -Wall $(VER) $(incdefs) $(DEBUG) 
> $(EXTRA_CFLAGS)
>  LDLIBS   = -lm -lrt -pthread $(EXTRA_LDFLAGS)
>  PRG  = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc tz2alt
>  FILTERS  = filter.o mave.o mmedian.o
> -SERVOS   = linreg.o ntpshm.o nullf.o pi.o refclock_sock.o servo.o
> +SERVOS   = linreg.o ntpshm.o nullf.o pi.o refclock_sock.o stats.o servo.o
>  TRANSP   = raw.o transport.o udp.o udp6.o uds.o
>  TS2PHC   = ts2phc.o lstab.o nmea.o serial.o sock.o 
> ts2phc_generic_pps_source.o \
>   ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o 
> ts2phc_pps_source.o
> diff --git a/servo.c b/servo.c
> index ea171cd..24713dc 100644
> --- a/servo.c
> +++ b/servo.c
> @@ -26,11 +26,45 @@
>  #include "pi.h"
>  #include "refclock_sock.h"
>  #include "servo_private.h"
> +#include "stats.h"
>  
>  #include "print.h"
>  
>  #define NSEC_PER_SEC 10
>  
> +static void servo_stats_create(struct servo *servo)
> +{
> + struct servo_stats *stats = >stats;
> +
> + stats->offset = stats_create();
> +}
> +
> +static void servo_stats_destroy(struct servo *servo)
> +{
> + struct servo_stats *stats = >stats;
> +
> + stats_destroy(stats->offset);
> +}
> +
> +void servo_stats_report(struct servo *servo)
> +{
> + struct servo_stats *stats = >stats;
> + struct stats_result os;
> +
> + if (stats_get_result(stats->offset, ))
> + return;
> +
> + pr_info("offset min/avg/max/stddev/rms %2.0f/%2.0f/%2.0f/%2.0f/%2.0f",
> + os.min, os.mean, os.max, os.stddev, os.rms);
> +}
> +
> +static void servo_stats_add_sample(struct servo *servo, int64_t offset)
> +{
> + struct servo_stats *stats = >stats;
> +
> + stats_add_value(stats->offset, offset);
> +}
> +
>  struct servo *servo_create(struct config *cfg, enum servo_type type,
>  double fadj, int max_ppb, int sw_ts)
>  {
> @@ -90,11 +124,15 @@ struct servo *servo_create(struct config *cfg, enum 
> servo_type type,
>   servo->num_offset_values = config_get_int(cfg, NULL, 
> "servo_num_offset_values");
>   servo->curr_offset_values = servo->num_offset_values;
>  
> + servo_stats_create(servo);
> +
>   return servo;
>  }
>  
>  void servo_destroy(struct servo *servo)
>  {
> + servo_stats_report(servo);
> + servo_stats_destroy(servo);
>   servo->destroy(servo);
>  }
>  
> @@ -124,6 +162,8 @@ double servo_sample(struct servo *servo,
>  
>   r = servo->sample(servo, offset, local_ts, weight, state);
>  
> + servo_stats_add_sample(servo, offset);
> +
>   switch (*state) {
>   case SERVO_UNLOCKED:
>   servo->curr_offset_values = servo->num_offset_values;
> @@ -158,6 +198,8 @@ void servo_sync_interval(struct servo *servo, double 
> interval)
>  void servo_reset(struct servo *servo)
>  {
>   servo->reset(servo);
> + servo_stats_destroy(servo);
> + servo_stats_create(servo);
>  }
>  
>  double servo_rate_ratio(struct servo *servo)
> diff --git a/servo_private.h b/servo_private.h
> index 4d74ca2..1c1aa9e 100644
> --- a/servo_private.h
> +++ b/servo_private.h
> @@ -23,8 +23,14 @@
>  
>  #include "contain.h"
>  #include "servo.h"
> +#include "stats.h"
> +
> +struct servo_stats {
> + struct stats *offset;
> +};
>  
>  struct servo {
> + struct servo_stats stats;
>   double max_frequency;
>   double step_threshold;
>   double first_step_threshold;


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v4 4/4] phc_ctl: add get_pins_cfg command to display pin functions

2023-06-27 Thread Jacob Keller



On 6/26/2023 11:54 PM, Erez wrote:
> On Mon, 26 Jun 2023 at 21:04, Jacob Keller  wrote:
>> +static int do_get_pins_cfg(clockid_t clkid, int cmdc, char *cmdv[])
>> +{
>> +   struct ptp_pin_desc pin_desc;
>> +   unsigned int index;
>> +   int n_pins;
>> +
>> +   if (clkid >= 0) {
>> +   pr_warning("The provided clock is not a PHC device.");
>> +   return 0;
>> +   }
>> +
>> +   n_pins = phc_number_pins(clkid);
>> +   if (n_pins == 0) {
>> +   pr_notice("device has no configurable pins");
>> +   return (0);
>>
> 
> For the record, it is not that important.
> Richard can fix it before applying.
> I just like consistency.
> Above you return "0"
> And here "(0)"
> 
> Erez
> 

Honestly not even sure where the difference came from..

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 2/4] phc_ctl: use phc_get_caps instead of direct ioctl invocation

2023-06-26 Thread Jacob Keller
The phc.c file already has phc_get_caps to obtain the capabilities for a
PHC clock. Expose this and use it in phc_ctl.c instead of re-implementing
it.

Signed-off-by: Jacob Keller 
---
 phc.c |  4 +---
 phc.h | 11 +++
 phc_ctl.c |  3 +--
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/phc.c b/phc.c
index c121c64f9177..4491a91d55f0 100644
--- a/phc.c
+++ b/phc.c
@@ -37,8 +37,6 @@
 #define BITS_PER_LONG  (sizeof(long)*8)
 #define MAX_PPB_32 32767999/* 2^31 - 1 / 65.536 */
 
-static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
-
 clockid_t phc_open(const char *phc)
 {
clockid_t clkid;
@@ -74,7 +72,7 @@ void phc_close(clockid_t clkid)
close(CLOCKID_TO_FD(clkid));
 }
 
-static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps)
+int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps)
 {
int fd = CLOCKID_TO_FD(clkid), err;
 
diff --git a/phc.h b/phc.h
index c48f906b84f5..830e002a8690 100644
--- a/phc.h
+++ b/phc.h
@@ -37,6 +37,17 @@ clockid_t phc_open(const char *phc);
  */
 void phc_close(clockid_t clkid);
 
+/**
+ * Get PTP hardware clock capabilities.
+ *
+ * @param clkid A clock ID obtained using phc_open().
+ * @param caps  Pointer to a PTP clock capabilities structure. On success,
+ *  this structure is filled with the clock capabilities.
+ *
+ * @return Zero on success, non-zero otherwise.
+ */
+int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
+
 /**
  * Query the maximum frequency adjustment of a PTP hardware clock device.
  *
diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..4344184c364b 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -29,7 +29,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -288,7 +287,7 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
}
 
-   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   if (phc_get_caps(clkid, )) {
pr_err("get capabilities failed: %s",
strerror(errno));
return -1;
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 4/4] phc_ctl: add get_pins_cfg command to display pin functions

2023-06-26 Thread Jacob Keller
Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
 missing.h |  5 +
 phc.c |  8 +++
 phc.h | 13 +++
 phc_ctl.c | 66 +++
 4 files changed, 92 insertions(+)

diff --git a/missing.h b/missing.h
index 9b37dc258c0f..4a71307169ad 100644
--- a/missing.h
+++ b/missing.h
@@ -240,10 +240,15 @@ struct ptp_pin_desc {
unsigned int rsv[5];
 };
 
+#define PTP_PIN_GETFUNC_IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
 #define PTP_PIN_SETFUNC_IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
 
 #endif /*!PTP_PIN_SETFUNC*/
 
+#ifndef PTP_PIN_GETFUNC2
+#define PTP_PIN_GETFUNC2   _IOWR(PTP_CLK_MAGIC, 15, struct ptp_pin_desc)
+#endif
+
 #ifndef PTP_PIN_SETFUNC2
 #define PTP_PIN_SETFUNC2   _IOW(PTP_CLK_MAGIC, 16, struct ptp_pin_desc)
 #endif
diff --git a/phc.c b/phc.c
index 4491a91d55f0..11ca23a46cec 100644
--- a/phc.c
+++ b/phc.c
@@ -108,6 +108,14 @@ int phc_number_pins(clockid_t clkid)
return caps.n_pins;
 }
 
+int phc_pin_getfunc(clockid_t clkid, struct ptp_pin_desc *desc)
+{
+   int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, desc);
+   if (err)
+   fprintf(stderr, "failed to set pin configuration, error: %m\n");
+   return err;
+}
+
 int phc_pin_setfunc(clockid_t clkid, struct ptp_pin_desc *desc)
 {
int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC, desc);
diff --git a/phc.h b/phc.h
index 830e002a8690..064d29bf36e0 100644
--- a/phc.h
+++ b/phc.h
@@ -66,6 +66,19 @@ int phc_max_adj(clockid_t clkid);
  */
 int phc_number_pins(clockid_t clkid);
 
+/**
+ * Reads configuration of a pin of a PTP hardware clock device.
+ *
+ * @param clkid  A clock ID obtained using phc_open().
+ *
+ * @param desc   Pointer to a pin descriptor with the 'index' field set. On
+ *   success, the rest of the structure is updated with the
+ *   current pin configuration.
+ *
+ * @return Zero on success, non-zero otherwise.
+ */
+int phc_pin_getfunc(clockid_t clkid, struct ptp_pin_desc *desc);
+
 /**
  * Configures a pin of a PTP hardware clock device.
  *
diff --git a/phc_ctl.c b/phc_ctl.c
index d61d27d8f632..bb5337c14de7 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -113,6 +113,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns 
current offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  get_pins_cfgdisplay device pins configuration\n"
"  wait   pause between commands\n"
"\n",
progname);
@@ -319,6 +320,70 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
 }
 
+static const char *pin_func_string(unsigned int func)
+{
+   switch (func) {
+   /* PTP_PF_NONE is already checked by the caller */
+   case PTP_PF_EXTTS:
+   return "external timestamping";
+   case PTP_PF_PEROUT:
+   return "periodic output";
+   case PTP_PF_PHYSYNC:
+   return "phy sync";
+   default:
+   return "unknown function";
+   }
+}
+
+static int do_get_pins_cfg(clockid_t clkid, int cmdc, char *cmdv[])
+{
+   struct ptp_pin_desc pin_desc;
+   unsigned int index;
+   int n_pins;
+
+   if (clkid >= 0) {
+   pr_warning("The provided clock is not a PHC device.");
+   return 0;
+   }
+
+   n_pins = phc_number_pins(clkid);
+   if (n_pins == 0) {
+   pr_notice("device has no configurable pins");
+   return (0);
+   }
+
+   pr_notice("device has %d configurable input/output pins",
+ n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (phc_pin_getfunc(clkid, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+  index,
+  strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] not configured",
+ pin_desc.index,
+ pin_desc.name);
+   } else {
+   pr_notice("pin %d [%s] %s on chan

[Linuxptp-devel] [PATCH v4 0/4] add get_pins_cfg command to display pin functions

2023-06-26 Thread Jacob Keller
Extend phc_ctl with a new get_pins_cfg command which calls the
PTP_PIN_GETFUNC ioctl on a PHC clock and prints the pin configuration for
each pin.

Changes since v3:
* remove use of PTP_PIN_SETFUNC2 and PTP_PIN_GETFUNC2 at Erez's request
* avoid converting PTP_PF_NONE in pin_func_string()
* check clkid >= 0 instead of clkid == CLOCK_REALTIME
* add a patch to do the same clkid check in do_caps()

Jacob Keller (4):
  phc: always use PTP_PIN_SETFUNC instead of depending on kernel headers
  phc_ctl: use phc_get_caps instead of direct ioctl invocation
  phc_ctl: check clkid >= 0 instead of just CLOCK_REALTIME
  phc_ctl: add get_pins_cfg command to display pin functions

 missing.h | 12 +
 phc.c | 19 +--
 phc.h | 24 ++
 phc_ctl.c | 73 ---
 4 files changed, 112 insertions(+), 16 deletions(-)

-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 3/4] phc_ctl: check clkid >= 0 instead of just CLOCK_REALTIME

2023-06-26 Thread Jacob Keller
All PHC have a negative clkid, while the variations of the system clock use
positive values. The do_caps() function hard codes a check against
CLOCK_REALTIME to avoid executing the PTP_CLOCK_GETCAPS ioctl on a non-PHC
clock.

Extend this to avoid operating on any system clock, allowing for the
potential future use of other variations of the system clock.

Reported-by: Erez 
Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/phc_ctl.c b/phc_ctl.c
index 4344184c364b..d61d27d8f632 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -282,8 +282,8 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
 {
struct ptp_clock_caps caps;
 
-   if (clkid == CLOCK_REALTIME) {
-   pr_warning("CLOCK_REALTIME is not a PHC device.");
+   if (clkid >= 0) {
+   pr_warning("The provided clock is not a PHC device.");
return 0;
}
 
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v4 1/4] phc: always use PTP_PIN_SETFUNC instead of depending on kernel headers

2023-06-26 Thread Jacob Keller
The phc_pin_setfunc() call uses PTP_PIN_SETFUNC2, attempting to hew the
newer PTP_PIN_SETFUNC2 ioctl. This would break on older kernels which lack
this ioctl. However, missing.h then provides a PTP_PIN_SETFUNC2 definition
which re-defines the macro to use the original ioctl PTP_PIN_SETFUNC.

This is confusing as it makes the function behavior differ based on whether
we compiled against updated header files. This will also make it
challenging to later support dynamic checking of PTP_PIN_SETFUNC2 if we
ever have a need to enable use of the newer ioctl. For now, these two
ioctls behave identically for the purposes of non-reserved fields.

Update missing.h to always define PTP_PIN_SETFUNC2 in terms of the actual
ioctl value. Avoid using PTP_PIN_SETFUNC2 at all in phc_pin_setfunc(),
instead just using the original PTP_PIN_SETFUNC.

In the future this can be modified to dynamically check and use
PTP_PIN_SETFUNC2 if necessary. However, there is no useful behavior
difference today. For this reason continue using the older ioctl to
maintain maximum compatibility with the supported kernels.

Note that PTP_PIN_SETFUNC2 is kept in missing.h even though we don't yet
have a user in the codebase. This is intentional to ensure that we do not
accidentally restore the anti-pattern of falling back at compile time
instead of run time if we need PTP_PIN_SETFUNC2 in the future.

Signed-off-by: Jacob Keller 
---
 missing.h | 7 ++-
 phc.c | 7 +++
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/missing.h b/missing.h
index 79a87d425993..9b37dc258c0f 100644
--- a/missing.h
+++ b/missing.h
@@ -244,11 +244,8 @@ struct ptp_pin_desc {
 
 #endif /*!PTP_PIN_SETFUNC*/
 
-#ifdef PTP_PIN_SETFUNC2
-#define PTP_PIN_SETFUNC_FAILED "PTP_PIN_SETFUNC2 failed: %m"
-#else
-#define PTP_PIN_SETFUNC_FAILED "PTP_PIN_SETFUNC failed: %m"
-#define PTP_PIN_SETFUNC2 PTP_PIN_SETFUNC
+#ifndef PTP_PIN_SETFUNC2
+#define PTP_PIN_SETFUNC2   _IOW(PTP_CLK_MAGIC, 16, struct ptp_pin_desc)
 #endif
 
 #ifndef LIST_FOREACH_SAFE
diff --git a/phc.c b/phc.c
index 37f6b9f6db3c..c121c64f9177 100644
--- a/phc.c
+++ b/phc.c
@@ -112,10 +112,9 @@ int phc_number_pins(clockid_t clkid)
 
 int phc_pin_setfunc(clockid_t clkid, struct ptp_pin_desc *desc)
 {
-   int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC2, desc);
-   if (err) {
-   fprintf(stderr, PTP_PIN_SETFUNC_FAILED "\n");
-   }
+   int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC, desc);
+   if (err)
+   fprintf(stderr, "failed to set pin configuration, error: %m\n");
return err;
 }
 
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v3 3/3] phc_ctl: add get_pins_cfg command to display pin functions

2023-06-23 Thread Jacob Keller



On 6/23/2023 2:08 AM, Erez wrote:
> On Fri, 23 Jun 2023 at 09:07, Jacob Keller  wrote:
> 
>> Add a new function to phc_ctl to display the devices pin configuration
>> data. First, obtain the device capabilities to determine the number of
>> pins. Then, for each pin, print the name, function, and channel
>> information.
>>
>> Signed-off-by: Jacob Keller 
>> ---
>>  missing.h |  5 +
>>  phc.c | 10 +
>>  phc.h | 13 +++
>>  phc_ctl.c | 67 +++
>>  4 files changed, 95 insertions(+)
>>
>> diff --git a/missing.h b/missing.h
>> index 9b37dc258c0f..4a71307169ad 100644
>> --- a/missing.h
>> +++ b/missing.h
>> @@ -240,10 +240,15 @@ struct ptp_pin_desc {
>> unsigned int rsv[5];
>>  };
>>
>> +#define PTP_PIN_GETFUNC_IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
>>  #define PTP_PIN_SETFUNC_IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
>>
>>  #endif /*!PTP_PIN_SETFUNC*/
>>
>> +#ifndef PTP_PIN_GETFUNC2
>> +#define PTP_PIN_GETFUNC2   _IOWR(PTP_CLK_MAGIC, 15, struct ptp_pin_desc)
>> +#endif
>> +
>>  #ifndef PTP_PIN_SETFUNC2
>>  #define PTP_PIN_SETFUNC2   _IOW(PTP_CLK_MAGIC, 16, struct ptp_pin_desc)
>>  #endif
>> diff --git a/phc.c b/phc.c
>> index fe8c5eccabda..879a008bd392 100644
>> --- a/phc.c
>> +++ b/phc.c
>> @@ -108,6 +108,16 @@ int phc_number_pins(clockid_t clkid)
>> return caps.n_pins;
>>  }
>>
>> +int phc_pin_getfunc(clockid_t clkid, struct ptp_pin_desc *desc)
>> +{
>> +   int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC2, desc);
>>
> 
> At the moment PTP_PIN_GETFUNC2 do not provide any additional information,
> We can skip it
> 
> 

Using PTP_PIN_GETFUNC2 enforces that we get zeros for reserved fields
where as using PTP_PIN_GETFUNC would give us potential garbage data in
the reserved fields. I think its worth using PTP_PIN_GETFUNC2 now for
that reason alone, even if we don't rely on this.

We will fall back to using PTP_PIN_GETFUNC on older kernels at a slight
increase on cost here but that should be negligible.

Yes right now the two behave (mostly) identically with PTP_PIN_GETFUNC2
enforcing reserved fields are zero, so it would cause an error if we
didn't already memset the desc structure, where as PTP_PIN_GETFUNC would
silently zero out those fields for us automatically.

I can drop this part if everyone agrees that its not worth it, but I
felt that enabling this now would make it easier to use the new versions
in the future when necessary.

>>
>> +static const char *pin_func_string(unsigned int func)
>> +{
>> +   switch (func) {
>> +   case PTP_PF_NONE:
>> +   return "no function";
>>
> 
> We already filter PTP_PF_NONE in do_get_pins_cfg().
> As it is a static function, you can skip it here.
> The default tag will catch missing values for the compiler. So no
> compilation warnings.
> Simply leave a note here, that we already filter it.
> 

I guess no one else uses this function so thats reasonable.

> 
>> +   case PTP_PF_EXTTS:
>> +   return "external timestamping";
>> +   case PTP_PF_PEROUT:
>> +   return "periodic output";
>> +   case PTP_PF_PHYSYNC:
>> +   return "phy sync";
>> +   default:
>> +   return "unknown function";
>> +   }
>> +}
>> +
>> +static int do_get_pins_cfg(clockid_t clkid, int cmdc, char *cmdv[])
>> +{
>> +   struct ptp_pin_desc pin_desc;
>> +   unsigned int index;
>> +   int n_pins;
>> +
>> +   if (clkid == CLOCK_REALTIME) {
>>
> 
> All PHC are negative values, while the system clock uses positive values
> (for the different variations).
> It is better to check "(clkid >= 0)".
> As the file description to clock ID formula is a public formula, this will
> not change.
> We might use other system clock variants in the future.
> 
> 

Fair.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v3 1/3] phc: dynamically try PTP_PIN_SETFUNC2 and fallback to PTP_PIN_SETFUNC

2023-06-23 Thread Jacob Keller



On 6/23/2023 1:44 AM, Erez wrote:
> On Fri, 23 Jun 2023 at 09:07, Jacob Keller  wrote:
> 
>> The phc library currently selects whether to use PTP_PIN_SETFUNC2 over
>> PTP_PIN_SETFUNC based on whether the kernel headers it is compiled against
>> have the PTP_PIN_SETFUNC2 defined.
>>
>> This means that the use of PTP_PIN_SETFUNC vs PTP_PIN_SETFUNC2 depends on
>> whether the headers we compiled against have the appropriate definition,
>> but not whether the running kernel supports the new ioctl.
>>
>> Fix this to use dynamic fallback. If PTP_PIN_SETFUNC2 returns -ENOTTY, then
>> try PTP_PIN_SETFUNC. This approach will work on a wider range of kernels
>> and doesn't need the headers to be up to date.
>>
> 
> 
> I look in the kernel
> https://elixir.bootlin.com/linux/v6.4-rc7/source/drivers/ptp/ptp_chardev.c#L399
> Using PTP_PIN_SETFUNC2 at the moment does not add anything.
> 
> Perhaps in the future.
> It is better to checkthe ptp_pin_desc structure
> https://elixir.bootlin.com/linux/v6.4-rc7/source/include/uapi/linux/ptp_clock.h#L174
> Once we have new properties there.
> Then we can use PTP_PIN_SETFUNC2.
> 
> Erez
> 

The reason to use PTP_PIN_SETFUNC2 is that if it *does* exist we *know*
the kernel sanitized the data structures and returned zeros in the
reserved fields.

Obviously currently we aren't using any reserved fields so the behavior
should be identical.

If we use the old command the kernel sanitizes the reserved fields from
user space as zero and forwards that to the drivers:

See:

>   if ((pd.rsv[0] || pd.rsv[1] || pd.rsv[2]
>   || pd.rsv[3] || pd.rsv[4])
>   && cmd == PTP_PIN_SETFUNC2) {
>   err = -EINVAL;
>   break;
>   } else if (cmd == PTP_PIN_SETFUNC) {
>   pd.rsv[0] = 0;
>   pd.rsv[1] = 0;
>   pd.rsv[2] = 0;
>   pd.rsv[3] = 0;
>   pd.rsv[4] = 0;
>   }

and note the checks for PTP_PIN_SETFUNC2 and PTP_PIN_SETFUNC.

This *is* a behavioral difference and I think we should prefer the
PTP_PIN_SETFUNC2 operation where its available.

Unlike PTP_GETCAPS which is EXACTLY the same as PTP_GETCAPS2 I think its
important to use these variants.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 1/3] phc: dynamically try PTP_PIN_SETFUNC2 and fallback to PTP_PIN_SETFUNC

2023-06-23 Thread Jacob Keller
The phc library currently selects whether to use PTP_PIN_SETFUNC2 over
PTP_PIN_SETFUNC based on whether the kernel headers it is compiled against
have the PTP_PIN_SETFUNC2 defined.

This means that the use of PTP_PIN_SETFUNC vs PTP_PIN_SETFUNC2 depends on
whether the headers we compiled against have the appropriate definition,
but not whether the running kernel supports the new ioctl.

Fix this to use dynamic fallback. If PTP_PIN_SETFUNC2 returns -ENOTTY, then
try PTP_PIN_SETFUNC. This approach will work on a wider range of kernels
and doesn't need the headers to be up to date.

Signed-off-by: Jacob Keller 
---
 missing.h | 7 ++-
 phc.c | 7 ---
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/missing.h b/missing.h
index 79a87d425993..9b37dc258c0f 100644
--- a/missing.h
+++ b/missing.h
@@ -244,11 +244,8 @@ struct ptp_pin_desc {
 
 #endif /*!PTP_PIN_SETFUNC*/
 
-#ifdef PTP_PIN_SETFUNC2
-#define PTP_PIN_SETFUNC_FAILED "PTP_PIN_SETFUNC2 failed: %m"
-#else
-#define PTP_PIN_SETFUNC_FAILED "PTP_PIN_SETFUNC failed: %m"
-#define PTP_PIN_SETFUNC2 PTP_PIN_SETFUNC
+#ifndef PTP_PIN_SETFUNC2
+#define PTP_PIN_SETFUNC2   _IOW(PTP_CLK_MAGIC, 16, struct ptp_pin_desc)
 #endif
 
 #ifndef LIST_FOREACH_SAFE
diff --git a/phc.c b/phc.c
index 37f6b9f6db3c..49e44d1aad65 100644
--- a/phc.c
+++ b/phc.c
@@ -113,9 +113,10 @@ int phc_number_pins(clockid_t clkid)
 int phc_pin_setfunc(clockid_t clkid, struct ptp_pin_desc *desc)
 {
int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC2, desc);
-   if (err) {
-   fprintf(stderr, PTP_PIN_SETFUNC_FAILED "\n");
-   }
+   if (err == -ENOTTY)
+   err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC, desc);
+   if (err)
+   fprintf(stderr, "failed to set pin configuration, error: %m\n");
return err;
 }
 
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 2/3] phc_ctl: use phc_get_caps instead of direct ioctl invocation

2023-06-23 Thread Jacob Keller
The phc.c file already has phc_get_caps to obtain the capabilities for a
PHC clock. Expose this and use it in phc_ctl.c instead of re-implementing
it.

Signed-off-by: Jacob Keller 
---
 phc.c |  4 +---
 phc.h | 11 +++
 phc_ctl.c |  3 +--
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/phc.c b/phc.c
index 49e44d1aad65..fe8c5eccabda 100644
--- a/phc.c
+++ b/phc.c
@@ -37,8 +37,6 @@
 #define BITS_PER_LONG  (sizeof(long)*8)
 #define MAX_PPB_32 32767999/* 2^31 - 1 / 65.536 */
 
-static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
-
 clockid_t phc_open(const char *phc)
 {
clockid_t clkid;
@@ -74,7 +72,7 @@ void phc_close(clockid_t clkid)
close(CLOCKID_TO_FD(clkid));
 }
 
-static int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps)
+int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps)
 {
int fd = CLOCKID_TO_FD(clkid), err;
 
diff --git a/phc.h b/phc.h
index c48f906b84f5..830e002a8690 100644
--- a/phc.h
+++ b/phc.h
@@ -37,6 +37,17 @@ clockid_t phc_open(const char *phc);
  */
 void phc_close(clockid_t clkid);
 
+/**
+ * Get PTP hardware clock capabilities.
+ *
+ * @param clkid A clock ID obtained using phc_open().
+ * @param caps  Pointer to a PTP clock capabilities structure. On success,
+ *  this structure is filled with the clock capabilities.
+ *
+ * @return Zero on success, non-zero otherwise.
+ */
+int phc_get_caps(clockid_t clkid, struct ptp_clock_caps *caps);
+
 /**
  * Query the maximum frequency adjustment of a PTP hardware clock device.
  *
diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..4344184c364b 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -29,7 +29,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -288,7 +287,7 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
}
 
-   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   if (phc_get_caps(clkid, )) {
pr_err("get capabilities failed: %s",
strerror(errno));
return -1;
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 0/3] add get_pins_cfg command to display pin functions

2023-06-23 Thread Jacob Keller
Modify the phc_ctl utility to add a helpful get_pins_cfg command to display
the current pin configuration.

This is a follow up of a previous v2 I sent a long time ago at [1], but
includes a couple of additional cleanups. First, I modified phc.c to
dynamically check and use PTP_PIN_SETFUNC2 if available, falling back to
PTP_PIN_SETFUNC if its not supported (-ENOTTY return value).

Second, I expose phc_get_caps and use this instead of re-inventing this
again in phc_ctl.c

Finally, the actual implementation is in the 3rd patch. In a similar way to
PTP_PIN_SETFUNC2, I use PTP_PIN_GETFUNC2 and fallback to PTP_PIN_GETFUNC in
the case of -ENOTTY return value, and use the phc.c helper file instead of
open coding equivalent functions.

This version should fix the issues with missing values and also dynamically
supports the newer ioctls when available rather than relying on compiler
time checks.

Jacob Keller (3):
  phc: dynamically try PTP_PIN_SETFUNC2 and fallback to PTP_PIN_SETFUNC
  phc_ctl: use phc_get_caps instead of direct ioctl invocation
  phc_ctl: add get_pins_cfg command to display pin functions

 missing.h | 12 ++
 phc.c | 21 -
 phc.h | 24 +++
 phc_ctl.c | 70 +--
 4 files changed, 114 insertions(+), 13 deletions(-)

-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 3/3] phc_ctl: add get_pins_cfg command to display pin functions

2023-06-23 Thread Jacob Keller
Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
 missing.h |  5 +
 phc.c | 10 +
 phc.h | 13 +++
 phc_ctl.c | 67 +++
 4 files changed, 95 insertions(+)

diff --git a/missing.h b/missing.h
index 9b37dc258c0f..4a71307169ad 100644
--- a/missing.h
+++ b/missing.h
@@ -240,10 +240,15 @@ struct ptp_pin_desc {
unsigned int rsv[5];
 };
 
+#define PTP_PIN_GETFUNC_IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
 #define PTP_PIN_SETFUNC_IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
 
 #endif /*!PTP_PIN_SETFUNC*/
 
+#ifndef PTP_PIN_GETFUNC2
+#define PTP_PIN_GETFUNC2   _IOWR(PTP_CLK_MAGIC, 15, struct ptp_pin_desc)
+#endif
+
 #ifndef PTP_PIN_SETFUNC2
 #define PTP_PIN_SETFUNC2   _IOW(PTP_CLK_MAGIC, 16, struct ptp_pin_desc)
 #endif
diff --git a/phc.c b/phc.c
index fe8c5eccabda..879a008bd392 100644
--- a/phc.c
+++ b/phc.c
@@ -108,6 +108,16 @@ int phc_number_pins(clockid_t clkid)
return caps.n_pins;
 }
 
+int phc_pin_getfunc(clockid_t clkid, struct ptp_pin_desc *desc)
+{
+   int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC2, desc);
+   if (err == -ENOTTY)
+   err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, desc);
+   if (err)
+   fprintf(stderr, "failed to set pin configuration, error: %m\n");
+   return err;
+}
+
 int phc_pin_setfunc(clockid_t clkid, struct ptp_pin_desc *desc)
 {
int err = ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_SETFUNC2, desc);
diff --git a/phc.h b/phc.h
index 830e002a8690..064d29bf36e0 100644
--- a/phc.h
+++ b/phc.h
@@ -66,6 +66,19 @@ int phc_max_adj(clockid_t clkid);
  */
 int phc_number_pins(clockid_t clkid);
 
+/**
+ * Reads configuration of a pin of a PTP hardware clock device.
+ *
+ * @param clkid  A clock ID obtained using phc_open().
+ *
+ * @param desc   Pointer to a pin descriptor with the 'index' field set. On
+ *   success, the rest of the structure is updated with the
+ *   current pin configuration.
+ *
+ * @return Zero on success, non-zero otherwise.
+ */
+int phc_pin_getfunc(clockid_t clkid, struct ptp_pin_desc *desc);
+
 /**
  * Configures a pin of a PTP hardware clock device.
  *
diff --git a/phc_ctl.c b/phc_ctl.c
index 4344184c364b..e5076f511813 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -113,6 +113,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns 
current offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  get_pins_cfgdisplay device pins configuration\n"
"  wait   pause between commands\n"
"\n",
progname);
@@ -319,6 +320,71 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
 }
 
+static const char *pin_func_string(unsigned int func)
+{
+   switch (func) {
+   case PTP_PF_NONE:
+   return "no function";
+   case PTP_PF_EXTTS:
+   return "external timestamping";
+   case PTP_PF_PEROUT:
+   return "periodic output";
+   case PTP_PF_PHYSYNC:
+   return "phy sync";
+   default:
+   return "unknown function";
+   }
+}
+
+static int do_get_pins_cfg(clockid_t clkid, int cmdc, char *cmdv[])
+{
+   struct ptp_pin_desc pin_desc;
+   unsigned int index;
+   int n_pins;
+
+   if (clkid == CLOCK_REALTIME) {
+   pr_warning("CLOCK_REALTIME is not a PHC device.");
+   return 0;
+   }
+
+   n_pins = phc_number_pins(clkid);
+   if (n_pins == 0) {
+   pr_notice("device has no configurable pins");
+   return (0);
+   }
+
+   pr_notice("device has %d configurable input/output pins",
+ n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (phc_pin_getfunc(clkid, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+  index,
+  strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] not configured",
+ pin_desc.index,
+   

[Linuxptp-devel] [PATCH v2] phc_ctl: explicitly check for adjust_phase definition

2023-06-23 Thread Jacob Keller
The PTP_CLOCK_GETCAPS ioctl call in phc_ctl has a conditional check for
whether to report the caps.adjust_phase bit. This is always set for both
PTP_CLOCK_GETCAPS and PTP_CLOCK_GETCAPS2, and was always zero before the
bit was moved from being reserved to indicate the adjust_phase.

In some sense if we lack PTP_CLOCK_GETCAPS2 we know the kernel won't report
adjust_phase, but in reality such kernel versions did not have
adjust_phase at all.

There's no reason to make this check against PTP_CLOCK_GETCAPS2. Instead,
scan the ptp_clock.h header file and check if we have adjust_phase support.
Use this new flag instead of PTP_CLOCK_GETCAPS2.

Signed-off-by: Jacob Keller 
---

 incdefs.sh | 5 +
 phc_ctl.c  | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/incdefs.sh b/incdefs.sh
index 21333e5109e9..a9e94f777f6b 100755
--- a/incdefs.sh
+++ b/incdefs.sh
@@ -63,6 +63,7 @@ kernel_flags()
 {
prefix=""
tstamp=/usr/include/linux/net_tstamp.h
+   ptp_clock=/usr/include/linux/ptp_clock.h
 
if [ "x$KBUILD_OUTPUT" != "x" ]; then
# With KBUILD_OUTPUT set, we are building against
@@ -90,6 +91,10 @@ kernel_flags()
if grep -q SOF_TIMESTAMPING_BIND_PHC ${prefix}${tstamp}; then
printf " -DHAVE_VCLOCKS"
fi
+
+   if grep -q adjust_phase ${prefix}${ptp_clock}; then
+   printf " -DHAVE_PTP_CAPS_ADJUST_PHASE"
+   fi
 }
 
 flags="$(user_flags)$(kernel_flags)"
diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..6a5c2f43d7c9 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -311,7 +311,7 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
caps.n_pins,
caps.pps ? "has" : "doesn't have",
caps.cross_timestamping ? "has" : "doesn't have",
-   #ifdef PTP_CLOCK_GETCAPS2
+   #ifdef HAVE_PTP_CAPS_ADJUST_PHASE
caps.adjust_phase ? "has" : "doesn't have"
#else
"no information regarding"
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] phc_ctl: use PTP_CLOCK_GETCAPS2 ioctl if available

2023-06-22 Thread Jacob Keller


On 12/8/2022 1:20 PM, Geva, Erez wrote:
> On Wed, 2022-12-07 at 06:59 -0800, Richard Cochran wrote:
>> On Thu, Nov 17, 2022 at 02:15:23PM -0800, Jacob Keller wrote:
>>> On 11/17/2022 1:34 PM, Geva, Erez wrote:
>>
>>>> The problem is the fallback works only on build.
>>>> But if the build system is newer than the running system, the
>>>> fallback
>>>> will fail, as you will use the PTP_CLOCK_GETCAPS2 which does not
>>>> exist
>>>> on the running old system.
>>>>
>>>
>>> Fair. We likely have the same problem with some of the other "2"
>>> ioctls,
>>> since they're handled in a similar way. I think we do the Right(TM)
>>> thing
>>> for the sysoff.c where we probe the kernel at run-time. This could
>>> be done
>>> here but is probably not really worth it considering that
>>> PTP_CLOCK_GETCAPS
>>> functions the same way as PTP_CLOCK_GETCAPS2 for all kernels I
>>> checked... So
>>> I guess this is somewhat less likely.
>>
>> Jacob, do you want to have phc_ctl fall back to PTP_CLOCK_GETCAPS at
>> run time if PTP_CLOCK_GETCAPS2 fails?
> 
> We can use run-time fallback.
> But personalty, I do not think it worth it.
> Using PTP_CLOCK_GETCAPS2 is only done for one new field in a debug
> tool.
> We can simply wait till PTP_CLOCK_GETCAPS become obsolete or we have a
> new PTP_CLOCK_GETCAPS3 to handle.
> 
>>
>>> I'm not sure if our other PTP ioctls are checked properly like this
>>> at run
>>> time...
>>
>> Maybe, but only because of sloppiness.  Better to support older
>> kernels at run time, as this is more user friendly.
>>
>> Working on embedded systems over the years, I've have often been that
>> user, and, believe me, it is super annoying when the latest greatest
>> App isn't backwards compatible.
> 
> My view too :-)
> 
>>
>> Thanks,
>> Richard
> 
> 
> Erez

Agreed. Since there's no difference to using PTP_CLOCK_GETCAPS2 at least
currently, it makes sense to just keep using PTP_CLOCK_GETCAPS.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2] remove C99 style loop variable declarations

2023-06-22 Thread Jacob Keller
When building the tlv.c file, the following warning may occur when
operating in C89 mode:

  $make EXTRA_CFLAGS=-std=gnu89
  tlv.c: In function ‘mgt_post_recv’:
  tlv.c:374:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
374 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~
  tlv.c:374:17: note: use option ‘-std=c99’, ‘-std=gnu99’, ‘-std=c11’ or 
‘-std=gnu11’ to compile your code
  tlv.c: In function ‘mgt_pre_send’:
  tlv.c:551:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
551 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~
  make: *** [: tlv.o] Error 1
  make: *** Waiting for unfinished jobs
  pmc.c: In function ‘pmc_show’:
  pmc.c:559:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
559 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~

This occurs because initial loop declarations are only supported in C99 or
newer. LinuxPTP source still prefers to keep with the GNU C89 convention of
variables being at the top of the function. Newer versions of GCC have
begun defaulting to a newer C standard, which explains how these slipped
in. Note that directly enforcing "-std=c89" does not work because we rely
on some GNU extensions of C89.

For the tlv.c file it turns out that the case statements which declare the
variables in loops already have suitable iterator variables bound at the
top of the function. For the iterator in pmc_show, we need to add the
declaration at the top of the function.

Reported-by: Jakub Raczyński 
Signed-off-by: Jacob Keller 
---

 pmc.c | 4 ++--
 tlv.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/pmc.c b/pmc.c
index 00e691f0c244..bc870585960e 100644
--- a/pmc.c
+++ b/pmc.c
@@ -181,8 +181,8 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
uint64_t next_jump;
struct portDS *p;
struct TLV *tlv;
+   int action, i;
uint8_t *buf;
-   int action;
 
if (msg_type(msg) == SIGNALING) {
pmc_show_signaling(msg, fp);
@@ -591,7 +591,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
"BM", "identity", "address", "state",
"clockClass", "clockQuality", "offsetScaledLogVariance",
"p1", "p2");
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
ume = (struct unicast_master_entry *) buf;
pmc_show_unicast_master_entry(ume, fp);
buf += sizeof(*ume) + ume->address.addressLength;
diff --git a/tlv.c b/tlv.c
index 79400126cbc4..9b82bd9d3fb2 100644
--- a/tlv.c
+++ b/tlv.c
@@ -444,7 +444,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t 
data_len,
umtn->actual_table_size =
ntohs(umtn->actual_table_size);
buf = (uint8_t *) umtn->unicast_masters;
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
len += sizeof(struct unicast_master_entry);
if (data_len < len)
goto bad_length;
@@ -643,7 +643,7 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
case MID_UNICAST_MASTER_TABLE_NP:
umtn = (struct unicast_master_table_np *)m->data;
buf = (uint8_t *) umtn->unicast_masters;
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
ume = (struct unicast_master_entry *) buf;
// update pointer before the conversion
buf += sizeof(*ume) + ume->address.addressLength;
-- 
2.41.0.1.g9857a21e0017.dirty



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] remove C99 style loop variable declarations

2023-06-22 Thread Jacob Keller


On 6/22/2023 8:49 PM, Richard Cochran wrote:
> On Mon, Jun 12, 2023 at 10:18:07AM +0200, Jakub Raczyński wrote:
>> In master version and 4.0 this patch was not applied. Please apply this when 
>> possible.
> 
> That patch does not apply (as I said back on 07 Dec 2022)
> 
> If you want to have it, then please clean it up and re-submit.
> 
> Thanks,
> Richard

Apologies I must have missed that message. Anyways, I will propose an
updated version that applies now.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] remove C99 style loop variable declarations

2023-06-22 Thread Jacob Keller



On 12/7/2022 6:43 AM, Richard Cochran wrote:
> On Wed, Nov 16, 2022 at 11:48:32AM -0800, Jacob Keller wrote:
>> When building the tlv.c file, the following warning may occur when
>> operating in C89 mode:
> 
> Jacob, this patch doesn't apply any more.  Can you rebase it please?
> 
> Thanks,
> Richard


I will rebase this.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] Resolve false hybrid_e2e warning

2023-06-20 Thread Jacob Keller



On 5/1/2023 4:22 AM, Eyal Itkin via Linuxptp-devel wrote:
> When delay_mechanism is set to "E2E" mode in the [global] section,
> it is applied only to non-UDS ports as UDS ports will override the
> delay_mechanism with "DM_AUTO". Still the UDS ports will be checked
> for hybrid_e2e and generate a false warning of: "hybrid_e2e only
> works with E2E".
> 
> Update the check so it would only cover non-UDS ports.
> 
> Signed-off-by: Eyal Itkin 
> Reviewed-by: Rahul Rameshbabu 

I saw this recently too, and I think the fix is good.

Reviewed-by: Jacob Keller 

> ---
>  port.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/port.c b/port.c
> index 8b2eb04..502cbf3 100644
> --- a/port.c
> +++ b/port.c
> @@ -3422,7 +3422,7 @@ struct port *port_open(const char *phc_device,
>   pr_err("%s: E2E TC needs E2E ports", p->log_name);
>   goto err_uc_service;
>   }
> - if (p->hybrid_e2e && p->delayMechanism != DM_E2E) {
> + if (!port_is_uds(p) && p->hybrid_e2e && p->delayMechanism != DM_E2E) {
>   pr_warning("%s: hybrid_e2e only works with E2E", p->log_name);
>   }
>   if (p->net_sync_monitor && !p->hybrid_e2e) {


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] Is intel i350 ptp driver broken?

2023-05-26 Thread Jacob Keller



On 5/26/2023 7:36 AM, egg car wrote:
> Dear Richard,
> 
> Ah yes I have figured out that the problem is not ts2phc, it should be
> fixed in igb_extts() at igb_main.c
> 
>   if (hw->mac .type
> == e1000_82580 
> ||
>>  hw->mac 
>> .type == e1000_i354 
>>  ||
>>  hw->mac 
>> .type == e1000_i350 
>> ) {
>>  s64  ns 
>>  = rd32 
>> (auxstmpl);
>>
>>  ns  += 
>> ((s64 )(rd32 
>> (auxstmph) & 0xFF)) 
>> << 32;
>>  ts  = 
>> ns_to_timespec64 
>> (ns 
>> );
>>  } else {
>>  ts 
>> .tv_nsec 
>>  = rd32 
>> (auxstmpl);
>>  ts 
>> .tv_sec 
>>   = rd32 
>> (auxstmph);
>>  }
>>
>> here the driver does treat the AUXSTMPH resolution and valid bits in the
> right way, but forgot to convert the raw circle counter value to
> valid time stamp value.
> 
> I'll test the patch next week
> 
> Thanks for your attention
> 

Hello,

I don't work directly on this driver much these days, but if you send a
patch feel free to Cc me. I can review it and do my best to encourage
the current maintainers to merge it.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] Fix power profile config option range to UINT32_MAX

2023-04-24 Thread Jacob Keller
The power profile configuration options added in commit 7059a05a3fb2
("Introduce the power profile.") specify their maximum range as INT_MAX.
The values are stored as UInteger32 values and the default value is
0x. On most platforms, a signed integer cannot hold 0x, and
on these platforms ptp4l is unable to read the default configuration file:

  $ ./ptp4l -f configs/default.cfg -i eno0
  0x is an out of range value for option 
power_profile.2011.grandmasterTimeInaccuracy at line 44
  failed to parse configuration file configs/default.cfg

Fix this by modifying the configuration code to store the integer values
internally as long longs, which are required by the C standard, and all
platforms that Linux supports, to be at least 64bits long.

To avoid casting issues, also introduce config_get_uint to obtain these
UInteger32 values from the configuration code properly as unsigned values.

Signed-off-by: Jacob Keller 
---
 config.c | 40 +++-
 config.h |  3 +++
 port.c   |  6 +++---
 util.c   | 15 +++
 util.h   | 16 
 5 files changed, 68 insertions(+), 12 deletions(-)

diff --git a/config.c b/config.c
index cb4421f572c7..b3ba4e8bb7aa 100644
--- a/config.c
+++ b/config.c
@@ -62,7 +62,7 @@ struct config_enum {
 };
 
 typedef union {
-   int i;
+   long long i;
double d;
char *s;
 } any_t;
@@ -309,9 +309,9 @@ struct config_item config_tab[] = {
GLOB_ITEM_DBL("pi_proportional_norm_max", 0.7, DBL_MIN, 1.0),
GLOB_ITEM_DBL("pi_proportional_scale", 0.0, 0.0, DBL_MAX),
PORT_ITEM_ENU("power_profile.version", IEEE_C37_238_VERSION_NONE, 
ieee_c37_238_enu),
-   PORT_ITEM_INT("power_profile.2011.grandmasterTimeInaccuracy", 
0x, 0, INT_MAX),
-   PORT_ITEM_INT("power_profile.2011.networkTimeInaccuracy", 0, 0, 
INT_MAX),
-   PORT_ITEM_INT("power_profile.2017.totalTimeInaccuracy", 0x, 0, 
INT_MAX),
+   PORT_ITEM_INT("power_profile.2011.grandmasterTimeInaccuracy", 
0x, 0, UINT32_MAX),
+   PORT_ITEM_INT("power_profile.2011.networkTimeInaccuracy", 0, 0, 
UINT32_MAX),
+   PORT_ITEM_INT("power_profile.2017.totalTimeInaccuracy", 0x, 0, 
UINT32_MAX),
PORT_ITEM_INT("power_profile.grandmasterID", 0, 0, 0x),
GLOB_ITEM_INT("priority1", 128, 0, UINT8_MAX),
GLOB_ITEM_INT("priority2", 128, 0, UINT8_MAX),
@@ -559,8 +559,8 @@ static enum parser_result parse_item(struct config *cfg,
enum parser_result r;
struct config_item *cgi, *dst;
struct config_enum *cte;
+   long long val;
double df;
-   int val;
 
r = parse_fault_interval(cfg, section, option, value);
if (r != NOT_PARSED)
@@ -576,7 +576,7 @@ static enum parser_result parse_item(struct config *cfg,
 
switch (cgi->type) {
case CFG_TYPE_INT:
-   r = get_ranged_int(value, , cgi->min.i, cgi->max.i);
+   r = get_ranged_ll(value, , cgi->min.i, cgi->max.i);
break;
case CFG_TYPE_DOUBLE:
r = get_ranged_double(value, , cgi->min.d, cgi->max.d);
@@ -1021,10 +1021,32 @@ int config_get_int(struct config *cfg, const char 
*section, const char *option)
case CFG_TYPE_ENUM:
break;
}
-   pr_debug("config item %s.%s is %d", section, option, ci->val.i);
+   pr_debug("config item %s.%s is %lld", section, option, ci->val.i);
return ci->val.i;
 }
 
+unsigned int
+config_get_uint(struct config *cfg, const char *section, const char *option)
+{
+   struct config_item *ci = config_find_item(cfg, section, option);
+
+   if (!ci) {
+   pr_err("bug: config option %s missing!", option);
+   exit(-1);
+   }
+   switch (ci->type) {
+   case CFG_TYPE_DOUBLE:
+   case CFG_TYPE_STRING:
+   pr_err("bug: config option %s type mismatch!", option);
+   exit(-1);
+   case CFG_TYPE_INT:
+   case CFG_TYPE_ENUM:
+   break;
+   }
+   pr_debug("config item %s.%s is %lld", section, option, ci->val.i);
+   return (unsigned int)ci->val.i;
+}
+
 char *config_get_string(struct config *cfg, const char *section,
const char *option)
 {
@@ -1141,7 +1163,7 @@ int config_set_section_int(struct config *cfg, const char 
*section,
if (!section) {
cgi->flags |= CFG_ITEM_LOCKED;
cgi->val.i = val;
-   pr_debug("locked item global.%s as %d", option, cgi->val.i);
+   pr_debug("locked item global.%s as %lld", option, cgi->val.i);
return 0;
}
/* Create or update this port specific item. */
@@ 

Re: [Linuxptp-devel] [PATCH] Fix power profile config option range to UINT32_MAX

2023-04-13 Thread Jacob Keller



On 3/29/2023 1:42 PM, Erez wrote:
> On Wed, 29 Mar 2023 at 20:36, Jacob Keller  wrote:
> 
>> The power profile configuration options added in commit 7059a05a3fb2
>> ("Introduce the power profile.") specify their maximum range as INT_MAX.
>> The values are stored in UInteger32 values, and the default 0x is
>> outside the range of a 32-bit integer. Because of this, on platforms which
>> have 32-bit integers, ptp4l is unable to read the default configuration:
>>
> 
> Just thinking.
> Why not move to unsigned 64 bits?
> It can solve future limitations.
> I would also change the int to signed 64,
>  but I can understand it may require too many changes in the code.
> 
> Erez
> 

I have no idea of the values being stored need to be 32bit or not.
However, I think we can migrate our internal "config value storage" to a
signed 64bit to allow us to keep track of all the possible unsigned
32bit values. We could make CFG_TYPE_INT be a s64 and then just have the
range check limit to 32bits without needing to add an extra unsigned
type. (unless we ever want to have a full 64bit unsigned value..)

That's probably better than this patch.

Thanks,
Jake

>>
>>   0x is an out of range value for option
>> power_profile.2011.grandmasterTimeInaccuracy at line 44
>>   failed to parse configuration file configs/default.cfg
> 
> 
>> These values are unsigned and stored as fixed width values of 32 bits.
>> Correct the configuration specification to allow the true maximum of an
>> unsigned 32 bit integer.
>>
>> Signed-off-by: Jacob Keller 
>> ---
>> I'm not sure if there is a simpler or better way to fix this. We could just
>> update the range of CFG_TYPE_INT to be long (or long long) instead, which
>> would give it a range big enough to cover all our current values...
>>
>>  config.c | 54 +++---
>>  config.h |  3 +++
>>  port.c   |  6 +++---
>>  3 files changed, 57 insertions(+), 6 deletions(-)
>>
>> diff --git a/config.c b/config.c
>> index cb4421f572c7..baf8352538ea 100644
>> --- a/config.c
>> +++ b/config.c
>> @@ -51,6 +51,7 @@ enum config_section {
>>
>>  enum config_type {
>> CFG_TYPE_INT,
>> +   CFG_TYPE_UINT,
>> CFG_TYPE_DOUBLE,
>> CFG_TYPE_ENUM,
>> CFG_TYPE_STRING,
>> @@ -63,6 +64,7 @@ struct config_enum {
>>
>>  typedef union {
>> int i;
>> +   unsigned int u;
>> double d;
>> char *s;
>>  } any_t;
>> @@ -109,6 +111,14 @@ struct config_item {
>> .min.i  = _min, \
>> .max.i  = _max, \
>>  }
>> +#define CONFIG_ITEM_UINT(_label, _port, _default, _min, _max) {\
>> +   .label  = _label,   \
>> +   .type   = CFG_TYPE_UINT,\
>> +   .flags  = _port ? CFG_ITEM_PORT : 0,\
>> +   .val.u  = _default, \
>> +   .min.u  = _min, \
>> +   .max.u  = _max, \
>> +}
>>  #define CONFIG_ITEM_STRING(_label, _port, _default) {  \
>> .label  = _label,   \
>> .type   = CFG_TYPE_STRING,  \
>> @@ -125,6 +135,9 @@ struct config_item {
>>  #define GLOB_ITEM_INT(label, _default, min, max) \
>> CONFIG_ITEM_INT(label, 0, _default, min, max)
>>
>> +#define GLOB_ITEM_UINT(label, _default, min, max) \
>> +   CONFIG_ITEM_UINT(label, 0, _default, min, max)
>> +
>>  #define GLOB_ITEM_STR(label, _default) \
>> CONFIG_ITEM_STRING(label, 0, _default)
>>
>> @@ -137,6 +150,9 @@ struct config_item {
>>  #define PORT_ITEM_INT(label, _default, min, max) \
>> CONFIG_ITEM_INT(label, 1, _default, min, max)
>>
>> +#define PORT_ITEM_UINT(label, _default, min, max) \
>> +   CONFIG_ITEM_UINT(label, 1, _default, min, max)
>> +
>>  #define PORT_ITEM_STR(label, _default) \
>> CONFIG_ITEM_STRING(label, 1, _default)
>>
>> @@ -309,9 +325,9 @@ struct config_item config_tab[] = {
>> GLOB_ITEM_DBL("pi_proportional_norm_max", 0.7, DBL_MIN, 1.0),
>> GLOB_ITEM_DBL("pi_proportional_scale", 0.0, 0.0, DBL_MAX),
>> PORT_ITEM_ENU("power_profile.version", IEEE_C37_238_VERSION_NONE,
>> ieee_c37_238_enu),
>> -   PORT_ITEM_INT("power_profile.2011.grandmasterTimeInaccuracy"

[Linuxptp-devel] [PATCH] Fix power profile config option range to UINT32_MAX

2023-03-29 Thread Jacob Keller
The power profile configuration options added in commit 7059a05a3fb2
("Introduce the power profile.") specify their maximum range as INT_MAX.
The values are stored in UInteger32 values, and the default 0x is
outside the range of a 32-bit integer. Because of this, on platforms which
have 32-bit integers, ptp4l is unable to read the default configuration:

  0x is an out of range value for option 
power_profile.2011.grandmasterTimeInaccuracy at line 44
  failed to parse configuration file configs/default.cfg

These values are unsigned and stored as fixed width values of 32 bits.
Correct the configuration specification to allow the true maximum of an
unsigned 32 bit integer.

Signed-off-by: Jacob Keller 
---
I'm not sure if there is a simpler or better way to fix this. We could just
update the range of CFG_TYPE_INT to be long (or long long) instead, which
would give it a range big enough to cover all our current values...

 config.c | 54 +++---
 config.h |  3 +++
 port.c   |  6 +++---
 3 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/config.c b/config.c
index cb4421f572c7..baf8352538ea 100644
--- a/config.c
+++ b/config.c
@@ -51,6 +51,7 @@ enum config_section {
 
 enum config_type {
CFG_TYPE_INT,
+   CFG_TYPE_UINT,
CFG_TYPE_DOUBLE,
CFG_TYPE_ENUM,
CFG_TYPE_STRING,
@@ -63,6 +64,7 @@ struct config_enum {
 
 typedef union {
int i;
+   unsigned int u;
double d;
char *s;
 } any_t;
@@ -109,6 +111,14 @@ struct config_item {
.min.i  = _min, \
.max.i  = _max, \
 }
+#define CONFIG_ITEM_UINT(_label, _port, _default, _min, _max) {\
+   .label  = _label,   \
+   .type   = CFG_TYPE_UINT,\
+   .flags  = _port ? CFG_ITEM_PORT : 0,\
+   .val.u  = _default, \
+   .min.u  = _min, \
+   .max.u  = _max, \
+}
 #define CONFIG_ITEM_STRING(_label, _port, _default) {  \
.label  = _label,   \
.type   = CFG_TYPE_STRING,  \
@@ -125,6 +135,9 @@ struct config_item {
 #define GLOB_ITEM_INT(label, _default, min, max) \
CONFIG_ITEM_INT(label, 0, _default, min, max)
 
+#define GLOB_ITEM_UINT(label, _default, min, max) \
+   CONFIG_ITEM_UINT(label, 0, _default, min, max)
+
 #define GLOB_ITEM_STR(label, _default) \
CONFIG_ITEM_STRING(label, 0, _default)
 
@@ -137,6 +150,9 @@ struct config_item {
 #define PORT_ITEM_INT(label, _default, min, max) \
CONFIG_ITEM_INT(label, 1, _default, min, max)
 
+#define PORT_ITEM_UINT(label, _default, min, max) \
+   CONFIG_ITEM_UINT(label, 1, _default, min, max)
+
 #define PORT_ITEM_STR(label, _default) \
CONFIG_ITEM_STRING(label, 1, _default)
 
@@ -309,9 +325,9 @@ struct config_item config_tab[] = {
GLOB_ITEM_DBL("pi_proportional_norm_max", 0.7, DBL_MIN, 1.0),
GLOB_ITEM_DBL("pi_proportional_scale", 0.0, 0.0, DBL_MAX),
PORT_ITEM_ENU("power_profile.version", IEEE_C37_238_VERSION_NONE, 
ieee_c37_238_enu),
-   PORT_ITEM_INT("power_profile.2011.grandmasterTimeInaccuracy", 
0x, 0, INT_MAX),
-   PORT_ITEM_INT("power_profile.2011.networkTimeInaccuracy", 0, 0, 
INT_MAX),
-   PORT_ITEM_INT("power_profile.2017.totalTimeInaccuracy", 0x, 0, 
INT_MAX),
+   PORT_ITEM_UINT("power_profile.2011.grandmasterTimeInaccuracy", 
0x, 0, UINT32_MAX),
+   PORT_ITEM_UINT("power_profile.2011.networkTimeInaccuracy", 0, 0, 
UINT32_MAX),
+   PORT_ITEM_UINT("power_profile.2017.totalTimeInaccuracy", 0x, 0, 
UINT32_MAX),
PORT_ITEM_INT("power_profile.grandmasterID", 0, 0, 0x),
GLOB_ITEM_INT("priority1", 128, 0, UINT8_MAX),
GLOB_ITEM_INT("priority2", 128, 0, UINT8_MAX),
@@ -559,6 +575,7 @@ static enum parser_result parse_item(struct config *cfg,
enum parser_result r;
struct config_item *cgi, *dst;
struct config_enum *cte;
+   unsigned int uval;
double df;
int val;
 
@@ -578,6 +595,9 @@ static enum parser_result parse_item(struct config *cfg,
case CFG_TYPE_INT:
r = get_ranged_int(value, , cgi->min.i, cgi->max.i);
break;
+   case CFG_TYPE_UINT:
+   r = get_ranged_uint(value, , cgi->min.u, cgi->max.u);
+   break;
case CFG_TYPE_DOUBLE:
r = get_ranged_double(value, , cgi->min.d, cgi->max.d);
break;
@@ -623,6 +643,9 @@ static enum parser_result parse_item(struct config *cfg,
case CFG_TYPE_ENUM:
dst->val.i = val;
   

[Linuxptp-devel] bugs when reading ptp4l configuration files

2023-03-29 Thread Jacob Keller
Hi,

I recently discovered a couple of bugs with ptp4l's config reading code:

First, the default configuration specifies values for two of the power
profile options which are out of INT_MAX range:

power_profile.2011.grandmasterTimeInaccuracy and
power_profile.2017.totalTimeInaccuracy

On systems with 32-bit integers, the 0x value is out of range,
and is not allowed.

> 0x is an out of range value for option 
> power_profile.2011.grandmasterTimeInaccuracy at line 44

It seems like fixing this will require adding unsigned support to the
config.c

I started looking into this but I must have missed something as the
initial code I wrote to support this didn't work and it still reported
those values as out-of-range...

Second, a user reported to me that they had typo'd sanity_freq_limit as:

sanity_freq_limit   02

Then the program interprets this as an octal number with the unexpected
value of:

ptp4l[6627255.634]: config item (null).sanity_freq_limit is 33554432

This appears to be caused by using a base of 0 to strtol which then
interprets leading 0 numbers as octal. This is probably done in order to
get handling of '0x' prefixed numbers as well, but the leading 0 ->
octal interpretation is much less common.

The manual page does use several '0x' prefixed values but does not seem
to call out octal values or the implicit conversions.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2] servo: stop rounding initial frequency to nearest ppb

2022-11-28 Thread Jacob Keller
The interface to the Linux kernel for adjusting clock frequencies is
specified in scaled parts per million, where the frequency field is parts
per million with a 16 bit binary fractional field. (Equivalently it is
parts per ~65 billion).

The frequency adjustment is stored internally as a double, even though when
displaying we always display only a whole number adjustment. Thus ptp4l and
phc2sys already use the full range of frequency adjustments that can be
specified using a double type.

However, when initializing the servo we read the current clock frequency
and cast it to an integer, discarding the fractional part below a part per
billion.

Refactor the servo_create API to take a double value instead of an integer
value. Fix the clockadj_get_freq and clockadj_set_freq initialization to
avoid casting to an integer and thus rounding the value.

Signed-off-by: Jacob Keller 
---
Changes since v1:
* rebased to fix conflicts since Miroslav's patch was applied

 clock.c  | 10 ++
 linreg.c |  2 +-
 linreg.h |  2 +-
 pi.c |  2 +-
 pi.h |  2 +-
 servo.c  |  2 +-
 servo.h  |  2 +-
 ts2phc.c |  5 +++--
 8 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/clock.c b/clock.c
index 8177e77bc1ec..518601021051 100644
--- a/clock.c
+++ b/clock.c
@@ -897,10 +897,11 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
enum servo_type servo = config_get_int(config, NULL, "clock_servo");
char ts_label[IF_NAMESIZE], phc[32], *tmp;
enum timestamp_type timestamping;
-   int fadj = 0, max_adj = 0, sw_ts;
int phc_index, conf_phc_index, required_modes = 0;
struct clock *c = _clock;
+   int max_adj = 0, sw_ts;
const char *uds_ifname;
+   double fadj = 0.0;
struct port *p;
unsigned char oui[OUI_LEN];
struct interface *iface;
@@ -1143,7 +1144,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
c->time_flags = c->utc_timescale ? 0 : PTP_TIMESCALE;
 
if (c->clkid != CLOCK_INVALID) {
-   fadj = (int) clockadj_get_freq(c->clkid);
+   fadj = clockadj_get_freq(c->clkid);
/* Disable write phase mode if not implemented by driver */
if (c->write_phase_mode && !phc_has_writephase(c->clkid)) {
pr_err("clock does not support write phase mode");
@@ -1732,9 +1733,10 @@ struct tsproc *clock_get_tsproc(struct clock *c)
 int clock_switch_phc(struct clock *c, int phc_index)
 {
struct servo *servo;
-   int fadj, max_adj;
clockid_t clkid;
char phc[32];
+   double fadj;
+   int max_adj;
 
snprintf(phc, sizeof(phc), "/dev/ptp%d", phc_index);
clkid = phc_open(phc);
@@ -1748,7 +1750,7 @@ int clock_switch_phc(struct clock *c, int phc_index)
phc_close(clkid);
return -1;
}
-   fadj = (int) clockadj_get_freq(clkid);
+   fadj = clockadj_get_freq(clkid);
servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
if (!servo) {
pr_err("Switching PHC, failed to create clock servo");
diff --git a/linreg.c b/linreg.c
index 8f354f4b0d0b..363636e16937 100644
--- a/linreg.c
+++ b/linreg.c
@@ -330,7 +330,7 @@ static void linreg_leap(struct servo *servo, int leap)
s->leap = leap;
 }
 
-struct servo *linreg_servo_create(int fadj)
+struct servo *linreg_servo_create(double fadj)
 {
struct linreg_servo *s;
 
diff --git a/linreg.h b/linreg.h
index 5c86ea76ebf2..3c48ce5d465a 100644
--- a/linreg.h
+++ b/linreg.h
@@ -21,6 +21,6 @@
 
 #include "servo.h"
 
-struct servo *linreg_servo_create(int fadj);
+struct servo *linreg_servo_create(double fadj);
 
 #endif
diff --git a/pi.c b/pi.c
index bfe50223d96a..4a96a5b1913b 100644
--- a/pi.c
+++ b/pi.c
@@ -177,7 +177,7 @@ static void pi_reset(struct servo *servo)
s->count = 0;
 }
 
-struct servo *pi_servo_create(struct config *cfg, int fadj, int sw_ts)
+struct servo *pi_servo_create(struct config *cfg, double fadj, int sw_ts)
 {
struct pi_servo *s;
 
diff --git a/pi.h b/pi.h
index feb3ebeb25b9..1e7eb4f3fd51 100644
--- a/pi.h
+++ b/pi.h
@@ -21,6 +21,6 @@
 
 #include "servo.h"
 
-struct servo *pi_servo_create(struct config *cfg, int fadj, int sw_ts);
+struct servo *pi_servo_create(struct config *cfg, double fadj, int sw_ts);
 
 #endif
diff --git a/servo.c b/servo.c
index 46042aa176d9..6ba7cb42c71e 100644
--- a/servo.c
+++ b/servo.c
@@ -31,7 +31,7 @@
 #define NSEC_PER_SEC 10
 
 struct servo *servo_create(struct config *cfg, enum servo_type type,
-  int fadj, int max_ppb, int sw_ts)
+  double fadj, int max_ppb, int sw_ts)
 {
double servo_first_step_threshold;
double servo_step_threshold;
diff --git a/servo.h b/servo.h
index 6c30d3341fa6..6cedb66ada03 1

Re: [Linuxptp-devel] [PATCH 2/2] phc_ctl: use PTP_CLOCK_GETCAPS2 ioctl if available

2022-11-17 Thread Jacob Keller

On 11/17/2022 1:34 PM, Geva, Erez wrote:

On Thu, 2022-11-17 at 18:27 +, Keller, Jacob E wrote:




-Original Message-
From: Geva, Erez 
Sent: Thursday, November 17, 2022 9:13 AM
To: Keller, Jacob E ; linuxptp-
de...@lists.sourceforge.net
Subject: Re: [Linuxptp-devel] [PATCH 2/2] phc_ctl: use
PTP_CLOCK_GETCAPS2
ioctl if available

On Tue, 2022-11-15 at 16:43 -0800, Jacob Keller wrote:

The PTP_CLOCK_GETCAPS2 ioctl is provided by kernel as a
replacement
for the
original PTP_CLOCK_GETCAPS ioctl. This was done in order to
provide
ioctls
which guarantee reserved fields are properly initialized. In
practice
the
PTP_CLOCK_GETCAPS2 and PTP_CLOCK_GETCAPS both behave identically
since


Exactly, that is why I send a patch to add the new 'adjust_phase'
in
do_caps(), without changing the ioctl itself :-)




The reason PTP_CLOCK_GETCAPS2 was created was around the same time as
the other ioctls were fixed to properly a) validate reserved fields
and b) ensure that all reported reserved fields were zeroed.

Functionally its 100% identical to PTP_CLOCK_GETCAPS because this
ioctl already did the right thing.

The reason I propose switching to PTP_CLOCK_GETCAPS2 over
PTP_CLOCK_GETCAPS is because it reduces cognitive burden to REMEMBER
that the old PTP_CLOCK_GETCAPS is ok. All I remembered was "the non-2
ioctls might be broken and not receive new features".


PTP_CLOCK_GETCAPS always zeroed the caps structure. However, it
is
good
practice to use the newer version consistently.


But, it can also breaks when using the new linuxptp version build
on
new  machine, but used with old kernel.
It may be reasonable in few years, when these old kernels becomes
obsolete.


This uses a fallback to PTP_CLOCK_GETCAPS if PTP_CLOCK_GETCAPS2 is
not found.


The problem is the fallback works only on build.
But if the build system is newer than the running system, the fallback
will fail, as you will use the PTP_CLOCK_GETCAPS2 which does not exist
on the running old system.



Fair. We likely have the same problem with some of the other "2" ioctls, 
since they're handled in a similar way. I think we do the Right(TM) 
thing for the sysoff.c where we probe the kernel at run-time. This could 
be done here but is probably not really worth it considering that 
PTP_CLOCK_GETCAPS functions the same way as PTP_CLOCK_GETCAPS2 for all 
kernels I checked... So I guess this is somewhat less likely.


I'm not sure if our other PTP ioctls are checked properly like this at 
run time...



If I may, this is the classic gap, Hardware companies fail to
understand.





___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] remove C99 style loop variable declarations

2022-11-16 Thread Jacob Keller
When building the tlv.c file, the following warning may occur when
operating in C89 mode:

  $make EXTRA_CFLAGS=-std=gnu89
  tlv.c: In function ‘mgt_post_recv’:
  tlv.c:374:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
374 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~
  tlv.c:374:17: note: use option ‘-std=c99’, ‘-std=gnu99’, ‘-std=c11’ or 
‘-std=gnu11’ to compile your code
  tlv.c: In function ‘mgt_pre_send’:
  tlv.c:551:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
551 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~
  make: *** [: tlv.o] Error 1
  make: *** Waiting for unfinished jobs
  pmc.c: In function ‘pmc_show’:
  pmc.c:559:17: error: ‘for’ loop initial declarations are only allowed in C99 
or C11 mode
559 | for (int i = 0; i < umtn->actual_table_size; i++) {
| ^~~

This occurs because initial loop declarations are only supported in C99 or
newer. LinuxPTP source still prefers to keep with the GNU C89 convention of
variables being at the top of the function. Newer versions of GCC have
begun defaulting to a newer C standard, which explains how these slipped
in. Note that directly enforcing "-std=c89" does not work because we rely
on some GNU extensions of C89.

For the tlv.c file it turns out that the case statements which declare the
variables in loops already have suitable iterator variables bound at the
top of the function. For the iterator in pmc_show, we need to add the
declaration at the top of the function.

Reported-by: Jakub Raczyński 
Signed-off-by: Jacob Keller 
---
 pmc.c | 4 ++--
 tlv.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/pmc.c b/pmc.c
index e218ca478c38..4640a64ca8ea 100644
--- a/pmc.c
+++ b/pmc.c
@@ -177,8 +177,8 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
struct parentDS *pds;
struct portDS *p;
struct TLV *tlv;
+   int action, i;
uint8_t *buf;
-   int action;
 
if (msg_type(msg) == SIGNALING) {
pmc_show_signaling(msg, fp);
@@ -556,7 +556,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
"BM", "identity", "address", "state",
"clockClass", "clockQuality", "offsetScaledLogVariance",
"p1", "p2");
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
ume = (struct unicast_master_entry *) buf;
pmc_show_unicast_master_entry(ume, fp);
buf += sizeof(*ume) + ume->address.addressLength;
diff --git a/tlv.c b/tlv.c
index 1c13460796e5..240e7df01545 100644
--- a/tlv.c
+++ b/tlv.c
@@ -371,7 +371,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t 
data_len,
umtn->actual_table_size =
ntohs(umtn->actual_table_size);
buf = (uint8_t *) umtn->unicast_masters;
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
len += sizeof(struct unicast_master_entry);
if (data_len < len)
goto bad_length;
@@ -548,7 +548,7 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
case MID_UNICAST_MASTER_TABLE_NP:
umtn = (struct unicast_master_table_np *)m->data;
buf = (uint8_t *) umtn->unicast_masters;
-   for (int i = 0; i < umtn->actual_table_size; i++) {
+   for (i = 0; i < umtn->actual_table_size; i++) {
ume = (struct unicast_master_entry *) buf;
// update pointer before the conversion
buf += sizeof(*ume) + ume->address.addressLength;
-- 
2.38.1.420.g319605f8f00e



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 1/2] phc_ctl: explicitly check for adjust_phase definition

2022-11-15 Thread Jacob Keller
The PTP_CLOCK_GETCAPS ioctl call in phc_ctl has a conditional check for
whether to report the caps.adjust_phase bit. This is always set for both
PTP_CLOCK_GETCAPS and PTP_CLOCK_GETCAPS2, and was always zero before the
bit was moved from being reserved to indicate the adjust_phase.

In some sense if we lack PTP_CLOCK_GETCAPS2 we know the kernel won't report
adjust_phase, but in reality such kernel versions did not have
adjust_phase at all.

There's no reason to make this check against PTP_CLOCK_GETCAPS2. Instead,
scan the ptp_clock.h header file and check if we have adjust_phase support.
Use this new flag instead of PTP_CLOCK_GETCAPS2.

Signed-off-by: Jacob Keller 
---
Checking against PTP_CLOCK_GETCAPS2 is wrong because this is not when the
adjust_phase was actually introduced. A direct check against whats in the
header is more accurate.

 incdefs.sh | 5 +
 phc_ctl.c  | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/incdefs.sh b/incdefs.sh
index 21333e5109e9..a9e94f777f6b 100755
--- a/incdefs.sh
+++ b/incdefs.sh
@@ -63,6 +63,7 @@ kernel_flags()
 {
prefix=""
tstamp=/usr/include/linux/net_tstamp.h
+   ptp_clock=/usr/include/linux/ptp_clock.h
 
if [ "x$KBUILD_OUTPUT" != "x" ]; then
# With KBUILD_OUTPUT set, we are building against
@@ -90,6 +91,10 @@ kernel_flags()
if grep -q SOF_TIMESTAMPING_BIND_PHC ${prefix}${tstamp}; then
printf " -DHAVE_VCLOCKS"
fi
+
+   if grep -q adjust_phase ${prefix}${ptp_clock}; then
+   printf " -DHAVE_PTP_CAPS_ADJUST_PHASE"
+   fi
 }
 
 flags="$(user_flags)$(kernel_flags)"
diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..6a5c2f43d7c9 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -311,7 +311,7 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
caps.n_pins,
caps.pps ? "has" : "doesn't have",
caps.cross_timestamping ? "has" : "doesn't have",
-   #ifdef PTP_CLOCK_GETCAPS2
+   #ifdef HAVE_PTP_CAPS_ADJUST_PHASE
caps.adjust_phase ? "has" : "doesn't have"
#else
"no information regarding"
-- 
2.38.1.420.g319605f8f00e



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 2/2] phc_ctl: use PTP_CLOCK_GETCAPS2 ioctl if available

2022-11-15 Thread Jacob Keller
The PTP_CLOCK_GETCAPS2 ioctl is provided by kernel as a replacement for the
original PTP_CLOCK_GETCAPS ioctl. This was done in order to provide ioctls
which guarantee reserved fields are properly initialized. In practice the
PTP_CLOCK_GETCAPS2 and PTP_CLOCK_GETCAPS both behave identically since
PTP_CLOCK_GETCAPS always zeroed the caps structure. However, it is good
practice to use the newer version consistently.

Signed-off-by: Jacob Keller 
---
Technically this is identical in current kernels, both ioctls return exactly
the same conent.. I still think its better to use the '2' variants in
principle that developer doesn't have to remember "is this variant ok to get
all the new features going forward?"

 missing.h | 7 +++
 phc_ctl.c | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/missing.h b/missing.h
index 79a87d425993..41427d3a38b2 100644
--- a/missing.h
+++ b/missing.h
@@ -98,6 +98,13 @@ enum {
 #define PTP_PEROUT_REQUEST2 PTP_PEROUT_REQUEST
 #endif
 
+#ifdef PTP_CLOCK_GETCAPS2
+#define PTP_CLOCK_GETCAPS_REQUEST_FAILED "PTP_CLOCK_GETCAPS2 failed: %m"
+#else
+#define PTP_CLOCK_GETCAPS_REQUEST_FAILED "PTP_CLOCK_GETCAPS failed: %m"
+#define PTP_CLOCK_GETCAPS2 PTP_CLOCK_GETCAPS
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0)
 
 /* from upcoming Linux kernel version 5.8 */
diff --git a/phc_ctl.c b/phc_ctl.c
index 6a5c2f43d7c9..17a615f8aae6 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -288,7 +288,7 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
}
 
-   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS2, )) {
pr_err("get capabilities failed: %s",
strerror(errno));
return -1;
-- 
2.38.1.420.g319605f8f00e



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] servo: stop rounding initial frequency to nearest ppb

2022-11-15 Thread Jacob Keller
The interface to the Linux kernel for adjusting clock frequencies is
specified in scaled parts per million, where the frequency field is parts
per million with a 16 bit binary fractional field. (Equivalently it is
parts per ~65 billion).

The frequency adjustment is stored internally as a double, even though when
displaying we always display only a whole number adjustment. Thus ptp4l and
phc2sys already use the full range of frequency adjustments that can be
specified using a double type.

However, when initializing the servo we read the current clock frequency
and cast it to an integer, discarding the fractional part below a part per
billion.

Refactor the servo_create API to take a double value instead of an integer
value. Fix the clockadj_get_freq and clockadj_set_freq initialization to
avoid casting to an integer and thus rounding the value.

Signed-off-by: Jacob Keller 
---
Noticed this while investigating whether we supported the full range of the
frequency adjustment.


 clock.c  | 10 ++
 linreg.c |  2 +-
 linreg.h |  2 +-
 pi.c |  2 +-
 pi.h |  2 +-
 servo.c  |  2 +-
 servo.h  |  2 +-
 ts2phc.c |  5 +++--
 8 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/clock.c b/clock.c
index d37bb87b6c03..7decd836feda 100644
--- a/clock.c
+++ b/clock.c
@@ -897,10 +897,11 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
enum servo_type servo = config_get_int(config, NULL, "clock_servo");
char ts_label[IF_NAMESIZE], phc[32], *tmp;
enum timestamp_type timestamping;
-   int fadj = 0, max_adj = 0, sw_ts;
int phc_index, conf_phc_index, required_modes = 0;
struct clock *c = _clock;
+   int max_adj = 0, sw_ts;
const char *uds_ifname;
+   double fadj = 0.0;
struct port *p;
unsigned char oui[OUI_LEN];
struct interface *iface;
@@ -1143,7 +1144,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
c->time_flags = c->utc_timescale ? 0 : PTP_TIMESCALE;
 
if (c->clkid != CLOCK_INVALID) {
-   fadj = (int) clockadj_get_freq(c->clkid);
+   fadj = clockadj_get_freq(c->clkid);
/* Due to a bug in older kernels, the reading may silently fail
   and return 0. Set the frequency back to make sure fadj is
   the actual frequency of the clock. */
@@ -1738,9 +1739,10 @@ struct tsproc *clock_get_tsproc(struct clock *c)
 int clock_switch_phc(struct clock *c, int phc_index)
 {
struct servo *servo;
-   int fadj, max_adj;
clockid_t clkid;
char phc[32];
+   double fadj;
+   int max_adj;
 
snprintf(phc, sizeof(phc), "/dev/ptp%d", phc_index);
clkid = phc_open(phc);
@@ -1754,7 +1756,7 @@ int clock_switch_phc(struct clock *c, int phc_index)
phc_close(clkid);
return -1;
}
-   fadj = (int) clockadj_get_freq(clkid);
+   fadj = clockadj_get_freq(clkid);
clockadj_set_freq(clkid, fadj);
servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
if (!servo) {
diff --git a/linreg.c b/linreg.c
index 8f354f4b0d0b..363636e16937 100644
--- a/linreg.c
+++ b/linreg.c
@@ -330,7 +330,7 @@ static void linreg_leap(struct servo *servo, int leap)
s->leap = leap;
 }
 
-struct servo *linreg_servo_create(int fadj)
+struct servo *linreg_servo_create(double fadj)
 {
struct linreg_servo *s;
 
diff --git a/linreg.h b/linreg.h
index 5c86ea76ebf2..3c48ce5d465a 100644
--- a/linreg.h
+++ b/linreg.h
@@ -21,6 +21,6 @@
 
 #include "servo.h"
 
-struct servo *linreg_servo_create(int fadj);
+struct servo *linreg_servo_create(double fadj);
 
 #endif
diff --git a/pi.c b/pi.c
index bfe50223d96a..4a96a5b1913b 100644
--- a/pi.c
+++ b/pi.c
@@ -177,7 +177,7 @@ static void pi_reset(struct servo *servo)
s->count = 0;
 }
 
-struct servo *pi_servo_create(struct config *cfg, int fadj, int sw_ts)
+struct servo *pi_servo_create(struct config *cfg, double fadj, int sw_ts)
 {
struct pi_servo *s;
 
diff --git a/pi.h b/pi.h
index feb3ebeb25b9..1e7eb4f3fd51 100644
--- a/pi.h
+++ b/pi.h
@@ -21,6 +21,6 @@
 
 #include "servo.h"
 
-struct servo *pi_servo_create(struct config *cfg, int fadj, int sw_ts);
+struct servo *pi_servo_create(struct config *cfg, double fadj, int sw_ts);
 
 #endif
diff --git a/servo.c b/servo.c
index 46042aa176d9..6ba7cb42c71e 100644
--- a/servo.c
+++ b/servo.c
@@ -31,7 +31,7 @@
 #define NSEC_PER_SEC 10
 
 struct servo *servo_create(struct config *cfg, enum servo_type type,
-  int fadj, int max_ppb, int sw_ts)
+  double fadj, int max_ppb, int sw_ts)
 {
double servo_first_step_threshold;
double servo_step_threshold;
diff --git a/servo.h b/servo.h
index 6c30d3341fa6..6cedb66ada03 100644
--- a/servo.h
+++ b/servo.h
@@ -77,7 +77,7 @@ enum 

Re: [Linuxptp-devel] [PATCH 2/4] Add sock servo.

2022-11-10 Thread Jacob Keller




On 11/10/2022 7:19 AM, Miroslav Lichvar wrote:

Add a second servo that provides samples to other processes in order to
control the clock. The chrony SOCK refclock uses a Unix domain socket
instead of a shared memory segment.

The main advantage over the NTP SHM refclock is better security as the
socket can be located in a directory with restricted access, while the
shared memory segment (using a predictable key) can be created by
untrusted users or applications if they can run before ptp4l/phc2sys and
chronyd/ntpd. There doesn't seem to a backward-compatible fix of the
protocol as both sides are expected to be able to create the segment if
it doesn't exist yet, possibly under a non-root owner, there is no
authentication of messages, and the protocol cannot be restarted if one
side decides to remove and recreate the segment.

Signed-off-by: Miroslav Lichvar 
---
  chronysock.c| 163 
  chronysock.h|  26 +++
  config.c|   2 +
  configs/default.cfg |   1 +
  makefile|   2 +-
  phc2sys.8   |   9 ++-
  phc2sys.c   |   3 +
  ptp4l.8 |  12 ++--
  servo.c |   4 ++
  servo.h |   1 +
  10 files changed, 216 insertions(+), 7 deletions(-)
  create mode 100644 chronysock.c
  create mode 100644 chronysock.h

diff --git a/chronysock.c b/chronysock.c
new file mode 100644
index 000..a8c0033
--- /dev/null
+++ b/chronysock.c
@@ -0,0 +1,163 @@
+/**
+ * @file chronysock.c
+ * @brief Implements a servo providing samples to chronyd over socket.
+ * @note Copyright (C) 2022 Miroslav Lichvar 
+ *
+ * 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 
+#include 
+#include 
+#include 
+
+#include "chronysock.h"
+#include "config.h"
+#include "print.h"
+#include "servo_private.h"
+
+#define LEAP_NORMAL 0
+#define LEAP_INSERT 1
+#define LEAP_DELETE 2
+#define SOCK_MAGIC 0x534f434b
+
+/* Copied from chrony-3.2/refclock_sock.c */
+struct sock_sample {
+   /* Time of the measurement (system time) */
+   struct timeval tv;
+
+   /* Offset between the true time and the system time (in seconds) */
+   double offset;
+
+   /* Non-zero if the sample is from a PPS signal, i.e. another source
+  is needed to obtain seconds */
+   int pulse;
+
+   /* 0 - normal, 1 - insert leap second, 2 - delete leap second */
+   int leap;
+
+   /* Padding, ignored */
+   int _pad;
+
+   /* Protocol identifier (0x534f434b) */
+   int magic;
+};
+
+struct sock_servo {
+   struct servo servo;
+   int sock_fd;
+   int leap;
+};
+
+static void chronysock_destroy(struct servo *servo)
+{
+   struct sock_servo *s = container_of(servo, struct sock_servo, servo);
+   free(s);
+}
+
+static double chronysock_sample(struct servo *servo,
+   int64_t offset,
+   uint64_t local_ts,
+   double weight,
+   enum servo_state *state)
+{
+   struct sock_servo *s = container_of(servo, struct sock_servo, servo);
+   struct sock_sample sample;
+
+   memset(, 0, sizeof(sample));
+   sample.tv.tv_sec = local_ts / 10ULL;
+   sample.tv.tv_usec = local_ts % 10ULL / 1000U;
+   sample.offset = -offset / 1e9;
+   sample.magic = SOCK_MAGIC;
+
+   switch (s->leap) {
+   case -1:
+   sample.leap = LEAP_DELETE;
+   break;
+   case 1:
+   sample.leap = LEAP_INSERT;
+   break;
+   default:
+   sample.leap = LEAP_NORMAL;
+   }
+
+   if (send(s->sock_fd, , sizeof sample, 0) != sizeof sample) {
+   pr_err("chronysock: send failed: %m");
+   return 0;
+   }
+
+   *state = SERVO_UNLOCKED;
+   return 0.0;
+}
+
+static void chronysock_sync_interval(struct servo *servo, double interval)
+{
+}
+
+static void chronysock_reset(struct servo *servo)
+{
+}
+
+static void chronysock_leap(struct servo *servo, int leap)
+{
+   struct sock_servo *s = container_of(servo, struct sock_servo, servo);
+
+   s->leap = leap;
+}
+
+struct servo *chronysock_servo_create(struct config *cfg)
+{
+   char *addr = config_get_string(cfg, NULL, 

[Linuxptp-devel] [PATCH v2] phc_ctl: add get_pins_cfg command to display pin functions

2022-11-02 Thread Jacob Keller
Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
Changes since v2:
* made output a bit less verbose
* changed pin_cfg to get_pins_cfg

 phc_ctl.c | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..6522f8d212b4 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -114,6 +114,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns 
current offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  get_pins_cfgdisplay device pins configuration\n"
"  wait   pause between commands\n"
"\n",
progname);
@@ -320,6 +321,77 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
 }
 
+static const char *pin_func_string(unsigned int func)
+{
+   switch (func) {
+   case PTP_PF_NONE:
+   return "no function";
+   case PTP_PF_EXTTS:
+   return "external timestamping";
+   case PTP_PF_PEROUT:
+   return "periodic output";
+   case PTP_PF_PHYSYNC:
+   return "phy sync";
+   default:
+   return "unknown function";
+   }
+}
+
+static int do_get_pins_cfg(clockid_t clkid, int cmdc, char *cmdv[])
+{
+   struct ptp_clock_caps caps;
+   struct ptp_pin_desc pin_desc;
+   unsigned int index;
+
+   if (clkid == CLOCK_REALTIME) {
+   pr_warning("CLOCK_REALTIME is not a PHC device.");
+   return 0;
+   }
+
+   /* Get device capabilities first */
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   pr_err("get capabilities failed: %s",
+   strerror(errno));
+   return -1;
+   }
+
+   if (caps.n_pins == 0) {
+   pr_notice("device has no configurable pins");
+   return (0);
+   }
+
+   pr_notice("device has %d configurable input/output pins",
+   caps.n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < caps.n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+   index,
+   strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] not configured",
+   pin_desc.index,
+   pin_desc.name);
+   } else {
+   pr_notice("pin %d [%s] %s on channel %d",
+   pin_desc.index,
+   pin_desc.name,
+   pin_func_string(pin_desc.func),
+   pin_desc.chan);
+   }
+   }
+
+   return 0;
+}
+
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
int64_t sys_offset, delay;
@@ -403,6 +475,7 @@ static const struct cmd_t all_commands[] = {
{ "freq", _freq },
{ "cmp", _cmp },
{ "caps", _caps },
+   { "get_pins_cfg", _get_pins_cfg },
{ "wait", _wait },
{ 0, 0 }
 };
-- 
2.38.0.83.gd420dda05763



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] phc_ctl: add pin_cfg command to display pin functions

2022-11-01 Thread Jacob Keller




On 10/31/2022 6:20 AM, Maciek Machnikowski wrote:

On Thu, Oct 27, 2022 at 03:32:48AM -0700, Jacob Keller wrote:

Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
  phc_ctl.c | 73 +++
  1 file changed, 73 insertions(+)

diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..1d1b0ab61020 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -114,6 +114,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns current 
offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  pin_cfg display device pin configuration\n"


Can we change it to pins_get or pins_cfg_get to be able to add set in the 
future?
Also s/pin/pins/g



Yep, I'll fix that for v2.


+   pr_notice("device has %d configurable input/output pins",
+   caps.n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < caps.n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+   index,
+   strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] is not configured",
+   pin_desc.index,
+   pin_desc.name);
+   } else {
+   pr_notice("pin %d [%s] performing %s using channel %d",


Remove "performing" to avoid wordiness :)

But a very useful addition!



I'll shorten this up a little.

Thanks,
Jake


Regards
Maciek



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] phc_ctl: add pin_cfg command to display pin functions

2022-10-27 Thread Jacob Keller
Add a new function to phc_ctl to display the devices pin configuration
data. First, obtain the device capabilities to determine the number of
pins. Then, for each pin, print the name, function, and channel
information.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/phc_ctl.c b/phc_ctl.c
index 92e597c40a23..1d1b0ab61020 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -114,6 +114,7 @@ static void usage(const char *progname)
"  freq [ppb]  adjust PHC frequency (default returns 
current offset)\n"
"  cmp compare PHC offset to CLOCK_REALTIME\n"
"  capsdisplay device capabilities (default if no 
command given)\n"
+   "  pin_cfg display device pin configuration\n"
"  wait   pause between commands\n"
"\n",
progname);
@@ -320,6 +321,77 @@ static int do_caps(clockid_t clkid, int cmdc, char *cmdv[])
return 0;
 }
 
+static const char *pin_func_string(unsigned int func)
+{
+   switch (func) {
+   case PTP_PF_NONE:
+   return "no function";
+   case PTP_PF_EXTTS:
+   return "external timestamping";
+   case PTP_PF_PEROUT:
+   return "periodic output";
+   case PTP_PF_PHYSYNC:
+   return "phy sync";
+   default:
+   return "unknown function";
+   }
+}
+
+static int do_pin_cfg(clockid_t clkid, int cmdc, char *cmdv[])
+{
+   struct ptp_clock_caps caps;
+   struct ptp_pin_desc pin_desc;
+   unsigned int index;
+
+   if (clkid == CLOCK_REALTIME) {
+   pr_warning("CLOCK_REALTIME is not a PHC device.");
+   return 0;
+   }
+
+   /* Get device capabilities first */
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_CLOCK_GETCAPS, )) {
+   pr_err("get capabilities failed: %s",
+   strerror(errno));
+   return -1;
+   }
+
+   if (caps.n_pins == 0) {
+   pr_notice("device has no configurable pins");
+   return (0);
+   }
+
+   pr_notice("device has %d configurable input/output pins",
+   caps.n_pins);
+
+   /* For each pin, read its configuration */
+   for (index = 0; index < caps.n_pins; index++) {
+   memset(_desc, 0, sizeof(pin_desc));
+   pin_desc.index = index;
+
+   if (ioctl(CLOCKID_TO_FD(clkid), PTP_PIN_GETFUNC, _desc)) {
+   pr_warning("get pin configuration for pin %d failed: 
%s",
+   index,
+   strerror(errno));
+   /* keep going */
+   continue;
+   }
+
+   if (pin_desc.func == PTP_PF_NONE) {
+   pr_notice("pin %d [%s] is not configured",
+   pin_desc.index,
+   pin_desc.name);
+   } else {
+   pr_notice("pin %d [%s] performing %s using channel %d",
+   pin_desc.index,
+   pin_desc.name,
+   pin_func_string(pin_desc.func),
+   pin_desc.chan);
+   }
+   }
+
+   return 0;
+}
+
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
int64_t sys_offset, delay;
@@ -403,6 +475,7 @@ static const struct cmd_t all_commands[] = {
{ "freq", _freq },
{ "cmp", _cmp },
{ "caps", _caps },
+   { "pin_cfg", _pin_cfg },
{ "wait", _wait },
{ 0, 0 }
 };
-- 
2.38.0.83.gd420dda05763



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] config: allow fractional freq_est_interval

2022-10-27 Thread Jacob Keller
The freq_est_interval value is documented as the time interval over which
to estimate the ratio between the local and peer clock frequencies when
operating in free_running mode.

It is documented as a power of two in seconds, similar to the
summary_interval and the various intervals between packets.

The configuration forces this value to be positive, meaning that fractional
estimation intervals are not supported.A This appears to have been the case
since commit 0513c3b15b8a ("config: Apply more strict input validation to
almost all config file options").

Because of this, when operating in free_running mode it is not possible to
get an output of the estimated ratio faster than once a second, even if
your configuration has a sync rate that is higher.

The commit which enforced this positive boundary did not provide any
justification for why the freq_est_interval cannot be negative. Fix the
specification in the configuration table to correctly allow such intervals.

Fixes: 0513c3b15b8a ("config: Apply more strict input validation to almost all 
config file options")
Signed-off-by: Jacob Keller 
---
 config.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config.c b/config.c
index e454c91ff0a1..67bf6a40d5c9 100644
--- a/config.c
+++ b/config.c
@@ -254,7 +254,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_DBL("first_step_threshold", 0.2, 0.0, DBL_MAX),
PORT_ITEM_INT("follow_up_info", 0, 0, 1),
GLOB_ITEM_INT("free_running", 0, 0, 1),
-   PORT_ITEM_INT("freq_est_interval", 1, 0, INT_MAX),
+   PORT_ITEM_INT("freq_est_interval", 1, INT_MIN, INT_MAX),
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),
-- 
2.38.0.83.gd420dda05763



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v1 0/3] Fix TAI offset in generic pps source

2022-10-19 Thread Jacob Keller



On 10/18/2022 8:08 AM, Maciek Machnikowski wrote:
> Current implementation of generic pps source relies on the UTC-TAI offset read
> from system. Some OSes don't set that offset by default and return 0. In such
> case ts2phc sets PHC time to UTC timescale without notifying user.
> 

Not sure what "Some OSes" means here.. The 3rd patch spells it out that
TAI offset is not set unless an NTP daemon has set it.

> This patch series moves leapfile handling to lstab and reuses the logic that 
> was
> applied to nmea source also to the generic, when the value read from system is
> incorrect.
> 

Makes sense and is an improvement over the existing behavior.

Reviewed-by: Jacob Keller 

> Signed-off-by: Maciek Machnikowski 
> 
> Maciek Machnikowski (3):
>   lstab: Add LSTAB_EXPIRED result
>   lstab: move update_leapsecond_table function to lstab
>   ts2phc: Fix generic pps source when tai offset is not set in OS
> 
>  lstab.c | 58 +-
>  lstab.h | 14 +++
>  ts2phc_generic_pps_source.c | 83 +
>  ts2phc_nmea_pps_source.c| 58 --
>  4 files changed, 155 insertions(+), 58 deletions(-)
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v1 2/3] lstab: move update_leapsecond_table function to lstab

2022-10-19 Thread Jacob Keller



On 10/18/2022 8:08 AM, Maciek Machnikowski wrote:
> To enable handling lstab in the same way by different pps sources, move
> update_leapsecond_table function from the nmea_pps_source to the generic lstab
> file. This also required moving leapfile filename and its modification time to
> the struct lstab.
> 
> Signed-off-by: Maciek Machnikowski 

Makes sense.

Reviewed-by: Jacob Keller 

Thanks,
Jake

> ---
>  lstab.c  | 55 
>  lstab.h  |  8 ++
>  ts2phc_nmea_pps_source.c | 51 +++--
>  3 files changed, 67 insertions(+), 47 deletions(-)
> 
> diff --git a/lstab.c b/lstab.c
> index a44aead..019e2d1 100644
> --- a/lstab.c
> +++ b/lstab.c
> @@ -3,6 +3,7 @@
>   * @note Copyright (C) 2012 Richard Cochran 
>   * @note SPDX-License-Identifier: GPL-2.0+
>   */
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -45,6 +46,8 @@ struct epoch_marker {
>  struct lstab {
>   struct epoch_marker lstab[N_LEAPS];
>   uint64_t expiration_utc;
> + const char *leapfile;
> + time_t lsfile_mtime;
>   int length;
>  };
>  
> @@ -157,6 +160,8 @@ static int lstab_read(struct lstab *lstab, const char 
> *name)
>  struct lstab *lstab_create(const char *filename)
>  {
>   struct lstab *lstab = calloc(1, sizeof(*lstab));
> + struct stat statbuf;
> + int err;
>  
>   if (!lstab) {
>   return NULL;
> @@ -166,12 +171,57 @@ struct lstab *lstab_create(const char *filename)
>   free(lstab);
>   return NULL;
>   }
> + lstab->leapfile = filename;
> +
> + err = stat(lstab->leapfile, );
> + if (err) {
> + fprintf(stderr, "file status failed on %s: %m",
> + lstab->leapfile);
> + return NULL;
> + }
> +
> + lstab->lsfile_mtime = statbuf.st_mtim.tv_sec;
> +
>   } else {
>   lstab_init(lstab);
>   }
>   return lstab;
>  }
>  
> +int update_leapsecond_table(struct lstab *lstab)
> +{
> + const char* leapfile;
> + struct stat statbuf;
> + int err;
> +
> + if (!lstab) {
> + return -1;
> + }
> +
> + if (!lstab->leapfile) {
> + return 0;
> + }
> + err = stat(lstab->leapfile, );
> + if (err) {
> + fprintf(stderr, "file status failed on %s: %m",
> + lstab->leapfile);
> + return -1;
> + }
> + if (lstab->lsfile_mtime == statbuf.st_mtim.tv_sec) {
> + return 0;
> + }
> + printf("updating leap seconds file\n");
> + leapfile = lstab->leapfile;
> + lstab_destroy(lstab);
> +
> + lstab = lstab_create(leapfile);
> + if (!lstab) {
> + return -1;
> + }
> +
> + return 0;
> +}
> +
>  void lstab_destroy(struct lstab *lstab)
>  {
>   free(lstab);
> @@ -182,6 +232,11 @@ enum lstab_result lstab_utc2tai(struct lstab *lstab, 
> uint64_t utctime,
>  {
>   int epoch = -1, index, next;
>  
> + if (update_leapsecond_table(lstab)) {
> + fprintf(stderr, "Failed to update leap seconds table");
> + return LSTAB_UNKNOWN;
> + }
> +
>   for (index = lstab->length - 1; index > -1; index--) {
>   if (utctime >= lstab->lstab[index].utc) {
>   epoch = index;
> diff --git a/lstab.h b/lstab.h
> index 3811aed..43a5ec0 100644
> --- a/lstab.h
> +++ b/lstab.h
> @@ -19,6 +19,14 @@ struct lstab;
>   */
>  struct lstab *lstab_create(const char *filename);
>  
> +/**
> + * Updates an instance of a leap second table from the associated file.
> + * @param lstab  Pointer to lstab to be updated.
> + * @return 0 if lstab is up to date, don't use a file or was successfully 
> updated.
> + * non-zero - on error
> + */
> +int update_leapsecond_table(struct lstab *lstab);
> +
>  /**
>   * Destroys a leap second table instance.
>   * @param lstab  A pointer obtained via lstab_create().
> diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
> index 8ea26bf..3a4267d 100644
> --- a/ts2phc_nmea_pps_source.c
> +++ b/ts2phc_nmea_pps_source.c
> @@ -29,8 +29,6 @@
>  struct ts2phc_nmea_pps_source {
>   struct ts2phc_pps_source pps_source;
>   struct config *config;
> - const char *leapfile;
> - time_t lsfile_mtime;
>   struct lstab *lstab;
>   pthread_t worker;
>

Re: [Linuxptp-devel] [PATCH v1 1/3] lstab: Add LSTAB_EXPIRED result

2022-10-19 Thread Jacob Keller



On 10/18/2022 8:08 AM, Maciek Machnikowski wrote:
> LSTAB_UNKNOWN is too generic, add LSTAB_EXPIRED result to return the latest
> lstab correction and indicate that the tab used to resolve it is expired.
> 
> This is useful for more precise reporting of lstab file state and will enable 
> an
> override of expired table.
> 
> Signed-off-by: Maciek Machnikowski 

Reviewed-by: Jacob Keller 

> ---
>  lstab.c  | 9 +
>  lstab.h  | 6 ++
>  ts2phc_nmea_pps_source.c | 7 ---
>  3 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/lstab.c b/lstab.c
> index 8971aaf..a44aead 100644
> --- a/lstab.c
> +++ b/lstab.c
> @@ -182,10 +182,6 @@ enum lstab_result lstab_utc2tai(struct lstab *lstab, 
> uint64_t utctime,
>  {
>   int epoch = -1, index, next;
>  
> - if (utctime > lstab->expiration_utc) {
> - return LSTAB_UNKNOWN;
> - }
> -

Ok, so now we no longer immediately fail, but instead...

>   for (index = lstab->length - 1; index > -1; index--) {
>   if (utctime >= lstab->lstab[index].utc) {
>   epoch = index;
> @@ -203,5 +199,10 @@ enum lstab_result lstab_utc2tai(struct lstab *lstab, 
> uint64_t utctime,
>   if (next < lstab->length && utctime == lstab->lstab[next].utc - 1) {
>   return LSTAB_AMBIGUOUS;
>   }
> +
> + if (utctime > lstab->expiration_utc) {
> + return LSTAB_EXPIRED;
> + }
> +

We still update the lstab but now we reported it as experted instead of
ok. Makes sense.

>   return LSTAB_OK;
>  }
> diff --git a/lstab.h b/lstab.h
> index d2393b4..3811aed 100644
> --- a/lstab.h
> +++ b/lstab.h
> @@ -41,6 +41,12 @@ enum lstab_result {
>*/
>   LSTAB_UNKNOWN,
>  
> + /**
> +  * The given lstab is past its expiry date and the tai_offset return
> +  * value may not be correct.
> +  */
> + LSTAB_EXPIRED,
> +
>   /**
>* The given UTC value is ambiguous.  The corresponding TAI time is 
> either
>*
> diff --git a/ts2phc_nmea_pps_source.c b/ts2phc_nmea_pps_source.c
> index db8b5c6..8ea26bf 100644
> --- a/ts2phc_nmea_pps_source.c
> +++ b/ts2phc_nmea_pps_source.c
> @@ -188,7 +188,7 @@ static int ts2phc_nmea_pps_source_getppstime(struct 
> ts2phc_pps_source *src,
>   struct ts2phc_nmea_pps_source *m =
>   container_of(src, struct ts2phc_nmea_pps_source, pps_source);
>   tmv_t delay_t1, delay_t2, duration_since_rmc, local_t1, local_t2, rmc;
> - int lstab_error = 0, tai_offset = 0;
> + int lstab_error = -1, tai_offset = 0;
>   enum lstab_result result;
>   struct timespec now;
>   int64_t utc_time;
> @@ -237,11 +237,12 @@ static int ts2phc_nmea_pps_source_getppstime(struct 
> ts2phc_pps_source *src,
>   break;
>   case LSTAB_UNKNOWN:
>   pr_err("nmea: unable to find utc time in leap second table");
> - lstab_error = -1;
> + break;
> + case LSTAB_EXPIRED:
> + pr_err("nmea: utc time is past leap second table expiry date");
>   break;

Much nicer error message!

>   case LSTAB_AMBIGUOUS:
>   pr_err("nmea: utc time stamp is ambiguous");
> - lstab_error = -1;
>   break;
>   }
>   ts->tv_sec += tai_offset;


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/3] Drop support for old kernels returning zero frequency.

2022-10-13 Thread Jacob Keller



On 10/13/2022 9:04 AM, Miroslav Lichvar wrote:
> On Wed, Oct 12, 2022 at 03:23:18PM -0700, Jacob Keller wrote:
>> For the record I suspect this is related to Linux kernel commit
>> 5c35bad5ffe5 ("ptp: provide the clock's adjusted frequency"). This
>> landed in v3.7, so its pretty old, and I think dropping support for it
>> is probably fine.
>>
>> Interestingly, it looks like the kernel tried to return EOPNOTSUP. I
>> don't know why this would silently fail... Any recollection?
> 
> I think it's f0dbe81f0e7c ("posix-timers: Fix clock_adjtime to always
> return timex data on success"). That was an issue with CLOCK_REALTIME,
> which caused clock_adjtime() to not return the data if the clock was
> not synchronized or had a leap second.
> 

Ok, this is v3.9, and is a possible path for returning zero without an
error.

>> I guess it doesn't "silently" fail, the function logs an error with
>> fprintf, but it doesn't have any way to report the error back to the
>> caller, so the caller sees "0" with a log message, which is the "silent"
>> failure you mentioned.
>>
>> Alternatively this could be fixed by refactoring clockadj_get_freq to
>> return its integer error code and put the value into an argument instead?
>>
>> That would catch errors related to other failures such as access or
>> permission. This would also work properly at least on the versions of
>> the kernel I checked.
>>
>> Thoughts?
> 
> Could all these be handled as a fatal error, causing the program to
> exit as there is no reasonable recovery? Or is it possible to get
> EBUSY like with clock_gettime() and the SYS_OFFSET ioctls?
> 

It looks like we can return out of ptp_clock_adjtime with the following
flows:

a) -EBUSY if ptp_clock_freerun is true

b) -EFAULT if copy_from_user or copy_to_user fails

c) -EOPNOTSUPP on kernels older than v3.7

d) -EACCESS if the fmode on the clock is not write

e) an error if get_clock_desc fails

I think a fatal error here is sufficient, and would catch everything
except the posix-timers bug that you fixed above.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 3/3] Extend clockcheck to check for changes in frequency.

2022-10-12 Thread Jacob Keller



On 10/5/2022 11:38 PM, Miroslav Lichvar wrote:
> Before setting the new frequency offset on a clock update, compare the
> current frequency with the value saved from the previous update and
> print a warning message if they are different.
> 
> This should detect misconfigurations where multiple processes are trying
> to control the clock (e.g. another ptp4l/phc2sys instance or an NTP
> client), even when they don't step the clock.
> 

Nice improvement! I recently saw an issue where this checking would have
been helpful!

> Signed-off-by: Miroslav Lichvar 
> ---
>  clock.c  | 10 --
>  clockcheck.c |  9 +
>  clockcheck.h |  8 
>  phc2sys.c|  6 +-
>  ptp4l.8  |  4 +++-
>  5 files changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index 46ac9c2..69e803b 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -1776,12 +1776,17 @@ static void clock_step_window(struct clock *c)
>  
>  static void clock_synchronize_locked(struct clock *c, double adj)
>  {
> + if (c->sanity_check) {
> + clockcheck_freq(c->sanity_check,
> + clockadj_get_freq(c->clkid));
> + }
>   clockadj_set_freq(c->clkid, -adj);
>   if (c->clkid == CLOCK_REALTIME) {
>   sysclk_set_sync();
>   }
>   if (c->sanity_check) {
> - clockcheck_set_freq(c->sanity_check, -adj);
> + clockcheck_set_freq(c->sanity_check,
> + clockadj_get_freq(c->clkid));

Hmm. Ok so now we use the value reported by clockadj_get_freq rather
than using our internal value.

Does every caller of clockcheck_set_freq and clockcheck_freq now always
use clockadj_get_freq? Could we pull that into the function?

It would simplify adjusting clockadj_get_freq refactoring to return its
error code.

>   }
>  }
>  
> @@ -1838,7 +1843,8 @@ enum servo_state clock_synchronize(struct clock *c, 
> tmv_t ingress, tmv_t origin)
>   clockadj_step(c->clkid, -tmv_to_nanoseconds(c->master_offset));
>   c->ingress_ts = tmv_zero();
>   if (c->sanity_check) {
> - clockcheck_set_freq(c->sanity_check, -adj);
> + clockcheck_set_freq(c->sanity_check,
> + clockadj_get_freq(c->clkid));
>   clockcheck_step(c->sanity_check,
>   -tmv_to_nanoseconds(c->master_offset));
>   }
> diff --git a/clockcheck.c b/clockcheck.c
> index f0141be..c174e73 100644
> --- a/clockcheck.c
> +++ b/clockcheck.c
> @@ -123,6 +123,15 @@ void clockcheck_set_freq(struct clockcheck *cc, int freq)
>   cc->freq_known = 1;
>  }
>  
> +int clockcheck_freq(struct clockcheck *cc, int freq)
> +{
> + if (cc->freq_known && cc->current_freq != freq) {
> + pr_warning("clockcheck: clock frequency changed unexpectedly!");
> + return 1;
> + }
> + return 0;
> +}
> +
>  void clockcheck_step(struct clockcheck *cc, int64_t step)
>  {
>   if (cc->last_ts)
> diff --git a/clockcheck.h b/clockcheck.h
> index 1ff86eb..4b09b98 100644
> --- a/clockcheck.h
> +++ b/clockcheck.h
> @@ -54,6 +54,14 @@ int clockcheck_sample(struct clockcheck *cc, uint64_t ts);
>   */
>  void clockcheck_set_freq(struct clockcheck *cc, int freq);
>  
> +/**
> + * Check whether the frequency correction did not change unexpectedly.
> + * @param cc   Pointer to a clock check obtained via @ref 
> clockcheck_create().
> + * @param freq Current reading of the frequency correction in ppb.
> + * @return Zero if the frequency did not change, non-zero otherwise.
> + */
> +int clockcheck_freq(struct clockcheck *cc, int freq);
> +
>  /**
>   * Inform clock check that the clock was stepped.
>   * @param cc   Pointer to a clock check obtained via @ref 
> clockcheck_create().
> diff --git a/phc2sys.c b/phc2sys.c
> index ebc43e5..afe33ec 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -561,11 +561,15 @@ static void update_clock(struct phc2sys_private *priv, 
> struct clock *clock,
>   /* Fall through. */
>   case SERVO_LOCKED:
>   case SERVO_LOCKED_STABLE:
> + if (clock->sanity_check)
> + clockcheck_freq(clock->sanity_check,
> + clockadj_get_freq(clock->clkid));
>   clockadj_set_freq(clock->clkid, -ppb);
>   if (clock->clkid == CLOCK_REALTIME)
>   sysclk_set_sync();
>   if (clock->sanity_check)
> - clockcheck_set_freq(clock->sanity_check, -ppb);
> + clockcheck_set_freq(clock->sanity_check,
> + clockadj_get_freq(clock->clkid));
>   break;
>   }
>  
> diff --git a/ptp4l.8 b/ptp4l.8
> index 1268802..220d594 100644
> --- a/ptp4l.8
> +++ b/ptp4l.8
> @@ -619,7 +619,9 @@ This option used to be called
>  The maximum allowed frequency offset between uncorrected 

Re: [Linuxptp-devel] [PATCH 2/3] Drop support for old kernels returning zero frequency.

2022-10-12 Thread Jacob Keller



On 10/5/2022 11:38 PM, Miroslav Lichvar wrote:
> Some ancient kernels had a bug in reading of the clock frequency, which
> was worked around by commit da347d7a36f2 ("ptp4l: Set clock frequency on
> start").
> 
> Drop this workaround and support for the old kernels to make
> clockadj_get_freq() useful.
> 

For the record I suspect this is related to Linux kernel commit
5c35bad5ffe5 ("ptp: provide the clock's adjusted frequency"). This
landed in v3.7, so its pretty old, and I think dropping support for it
is probably fine.

Interestingly, it looks like the kernel tried to return EOPNOTSUP. I
don't know why this would silently fail... Any recollection?

I guess it doesn't "silently" fail, the function logs an error with
fprintf, but it doesn't have any way to report the error back to the
caller, so the caller sees "0" with a log message, which is the "silent"
failure you mentioned.

Alternatively this could be fixed by refactoring clockadj_get_freq to
return its integer error code and put the value into an argument instead?

That would catch errors related to other failures such as access or
permission. This would also work properly at least on the versions of
the kernel I checked.

Thoughts?

> Signed-off-by: Miroslav Lichvar 
> ---
>  clock.c   | 7 ---
>  phc2sys.c | 4 
>  ts2phc.c  | 7 ---
>  3 files changed, 18 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index d37bb87..46ac9c2 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -1144,12 +1144,6 @@ struct clock *clock_create(enum clock_type type, 
> struct config *config,
>  
>   if (c->clkid != CLOCK_INVALID) {
>   fadj = (int) clockadj_get_freq(c->clkid);
> - /* Due to a bug in older kernels, the reading may silently fail
> -and return 0. Set the frequency back to make sure fadj is
> -the actual frequency of the clock. */
> - if (!c->free_running) {
> - clockadj_set_freq(c->clkid, fadj);
> - }
>   /* Disable write phase mode if not implemented by driver */
>   if (c->write_phase_mode && !phc_has_writephase(c->clkid)) {
>   pr_err("clock does not support write phase mode");
> @@ -1755,7 +1749,6 @@ int clock_switch_phc(struct clock *c, int phc_index)
>   return -1;
>   }
>   fadj = (int) clockadj_get_freq(clkid);
> - clockadj_set_freq(clkid, fadj);
>   servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
>   if (!servo) {
>   pr_err("Switching PHC, failed to create clock servo");
> diff --git a/phc2sys.c b/phc2sys.c
> index 8d2624f..ebc43e5 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -128,10 +128,6 @@ static struct servo *servo_add(struct phc2sys_private 
> *priv,
>  
>   clockadj_init(clock->clkid);
>   ppb = clockadj_get_freq(clock->clkid);
> - /* The reading may silently fail and return 0, reset the frequency to
> -make sure ppb is the actual frequency of the clock. */
> - if (!priv->free_running)
> - clockadj_set_freq(clock->clkid, ppb);
>   if (clock->clkid == CLOCK_REALTIME) {
>   sysclk_set_leap(0);
>   max_ppb = sysclk_max_freq();
> diff --git a/ts2phc.c b/ts2phc.c
> index f7a57e4..f345370 100644
> --- a/ts2phc.c
> +++ b/ts2phc.c
> @@ -129,13 +129,6 @@ static struct servo *ts2phc_servo_create(struct 
> ts2phc_private *priv,
>   int fadj, max_adj;
>  
>   fadj = (int) clockadj_get_freq(clock->clkid);
> - /* Due to a bug in older kernels, the reading may silently fail
> -  * and return 0. Set the frequency back to make sure fadj is
> -  * the actual frequency of the clock.
> -  */
> - if (!clock->no_adj) {
> - clockadj_set_freq(clock->clkid, fadj);
> - }
>  
>   max_adj = phc_max_adj(clock->clkid);
>  


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/3] Drop support for old kernels returning zero frequency.

2022-10-12 Thread Jacob Keller



On 10/5/2022 11:38 PM, Miroslav Lichvar wrote:
> Some ancient kernels had a bug in reading of the clock frequency, which
> was worked around by commit da347d7a36f2 ("ptp4l: Set clock frequency on
> start").

Is it worth spelling out what kernel version this was fixed in?

> 
> Drop this workaround and support for the old kernels to make
> clockadj_get_freq() useful.
> 
> Signed-off-by: Miroslav Lichvar 
> ---
>  clock.c   | 7 ---
>  phc2sys.c | 4 
>  ts2phc.c  | 7 ---
>  3 files changed, 18 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index d37bb87..46ac9c2 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -1144,12 +1144,6 @@ struct clock *clock_create(enum clock_type type, 
> struct config *config,
>  
>   if (c->clkid != CLOCK_INVALID) {
>   fadj = (int) clockadj_get_freq(c->clkid);
> - /* Due to a bug in older kernels, the reading may silently fail
> -and return 0. Set the frequency back to make sure fadj is
> -the actual frequency of the clock. */
> - if (!c->free_running) {
> - clockadj_set_freq(c->clkid, fadj);
> - }
>   /* Disable write phase mode if not implemented by driver */
>   if (c->write_phase_mode && !phc_has_writephase(c->clkid)) {
>   pr_err("clock does not support write phase mode");
> @@ -1755,7 +1749,6 @@ int clock_switch_phc(struct clock *c, int phc_index)
>   return -1;
>   }
>   fadj = (int) clockadj_get_freq(clkid);
> - clockadj_set_freq(clkid, fadj);
>   servo = servo_create(c->config, c->servo_type, -fadj, max_adj, 0);
>   if (!servo) {
>   pr_err("Switching PHC, failed to create clock servo");
> diff --git a/phc2sys.c b/phc2sys.c
> index 8d2624f..ebc43e5 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -128,10 +128,6 @@ static struct servo *servo_add(struct phc2sys_private 
> *priv,
>  
>   clockadj_init(clock->clkid);
>   ppb = clockadj_get_freq(clock->clkid);
> - /* The reading may silently fail and return 0, reset the frequency to
> -make sure ppb is the actual frequency of the clock. */
> - if (!priv->free_running)
> - clockadj_set_freq(clock->clkid, ppb);
>   if (clock->clkid == CLOCK_REALTIME) {
>   sysclk_set_leap(0);
>   max_ppb = sysclk_max_freq();
> diff --git a/ts2phc.c b/ts2phc.c
> index f7a57e4..f345370 100644
> --- a/ts2phc.c
> +++ b/ts2phc.c
> @@ -129,13 +129,6 @@ static struct servo *ts2phc_servo_create(struct 
> ts2phc_private *priv,
>   int fadj, max_adj;
>  
>   fadj = (int) clockadj_get_freq(clock->clkid);
> - /* Due to a bug in older kernels, the reading may silently fail
> -  * and return 0. Set the frequency back to make sure fadj is
> -  * the actual frequency of the clock.
> -  */
> - if (!clock->no_adj) {
> - clockadj_set_freq(clock->clkid, fadj);
> - }
>  
>   max_adj = phc_max_adj(clock->clkid);
>  


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/3] phc2sys: Add clocks after processing configuration.

2022-10-12 Thread Jacob Keller



On 10/5/2022 11:38 PM, Miroslav Lichvar wrote:
> Clocks specified by the -c option, or the default CLOCK_REALTIME, were
> added before the default values (e.g. sanity_freq_limit) were set in the
> private structure used by clock_add().

So if I understand, this allows clocks specified by -c to get all the
changes to config values, rather than being forced to get default values?

> 
> Rework the code to save the names of sink clocks from command line and
> add them only after the configuration is complete.
> 
> This also fixes the automatic mode to not add CLOCK_REALTIME twice.
> > Fixes: 33ac7d25cd92 ("phc2sys: Allow multiple sink clocks")
> 
> Signed-off-by: Miroslav Lichvar 

Looks good to me.

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.8 |  2 +-
>  phc2sys.c | 41 +++--
>  2 files changed, 24 insertions(+), 19 deletions(-)
> 
> diff --git a/phc2sys.8 b/phc2sys.8
> index 963df83..3247fb1 100644
> --- a/phc2sys.8
> +++ b/phc2sys.8
> @@ -120,7 +120,7 @@ Specify the time sink by device (e.g. /dev/ptp1) or 
> interface (e.g. eth1) or
>  by  name. The default is CLOCK_REALTIME (the system clock). Not compatible
>  with the
>  .B \-a
> -option. This option may be given multiple times.
> +option. This option may be given up to 128 times.
>  .TP
>  .BI \-E " servo"
>  Specify which clock servo should be used. Valid values are pi for a PI
> diff --git a/phc2sys.c b/phc2sys.c
> index 2c8e905..8d2624f 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -64,6 +64,8 @@
>  
>  #define PHC_PPS_OFFSET_LIMIT 1000
>  
> +#define MAX_DST_CLOCKS 128
> +
>  struct clock {
>   LIST_ENTRY(clock) list;
>   LIST_ENTRY(clock) dst_list;
> @@ -1056,9 +1058,10 @@ static void usage(char *progname)
>  
>  int main(int argc, char *argv[])
>  {
> - char *config = NULL, *last_dst_name = NULL, *progname, *src_name = NULL;
> + char *config = NULL, *progname, *src_name = NULL;
> + const char *dst_names[MAX_DST_CLOCKS];
>   char uds_local[MAX_IFNAME_SIZE + 1];
> - int autocfg = 0, c, domain_number = 0, index, ntpshm_segment, offset;
> + int i, 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, dst_cnt = 0;
>   struct config *cfg;
> @@ -1104,13 +1107,11 @@ int main(int argc, char *argv[])
>   rt++;
>   break;
>   case 'c':
> - last_dst_name = optarg;
> - r = phc2sys_static_dst_configuration(,
> -  last_dst_name);
> - if (r) {
> - goto end;
> + if (dst_cnt == MAX_DST_CLOCKS) {
> + fprintf(stderr, "too many sink clocks\n");
> + goto bad_usage;
>   }
> - dst_cnt++;
> + dst_names[dst_cnt++] = optarg;
>   break;
>   case 'd':
>   pps_fd = open(optarg, O_RDONLY);
> @@ -1261,7 +1262,11 @@ int main(int argc, char *argv[])
>   return c;
>   }
>  
> - if (autocfg && (src_name || last_dst_name || hardpps_configured(pps_fd) 
> ||
> + if (!autocfg && dst_cnt == 0) {
> + dst_names[dst_cnt++] = "CLOCK_REALTIME";
> + }
> +
> + if (autocfg && (src_name || dst_cnt > 0 || hardpps_configured(pps_fd) ||
>   wait_sync || priv.forced_sync_offset)) {
>   fprintf(stderr,
>   "autoconfiguration cannot be mixed with manual config 
> options.\n");
> @@ -1279,15 +1284,8 @@ int main(int argc, char *argv[])
>   goto bad_usage;
>   }
>  
> - if (!last_dst_name) {
> - last_dst_name = "CLOCK_REALTIME";
> - r = phc2sys_static_dst_configuration(, last_dst_name);
> - if (r) {
> - goto end;
> - }
> - }

Ok, so the fix for muiltiple clock realtime is because autocfg now had
last_dst_name still unset, so we still followed through with this block
being removed. And the above block checks !autocfg, which makes it avoid
double-adding the CLOCK_REALTIME. ok.

> - if (hardpps_configured(pps_fd) && (dst_cnt > 1 ||
> - strcmp(last_dst_name, "CLOCK_REALTIME"))) {
> + if (hardpps_configured(pps_fd) && (dst_cnt != 1 ||
> + strcmp(dst_names[0], "CLOCK_REALTIME"))) {

What 

[Linuxptp-devel] [PATCH] port: don't clear fault if link is down

2022-09-13 Thread Jacob Keller
When ptp4l detects a fault, the application stops for a short time until
the fault_reset_interval has passed.

Since commit 3b82f227ce96 ("clock: Monitor the link status using a RT
netlink socket."), the clock state machine will not try to restart a port
when link is down. This makes sense because a port without link will
obviously just immediately fault again.

However, if a user configures fault_reset_interval with ASAP this behavior
differs. The ASAP value is a special keyword to request clearing the fault
as soon as possible. In this case, the fault is cleared in port.c
immediately as its detected.

Doing so ignores the link status, and thus restarts even when link is down.
This leads to further timeouts and faults. Rather than let these faults
happen just follow the same behavior pattern as the timer-based fault
clearing. Don't clear the fault when link is down, instead wait until link
is restored.

Signed-off-by: Jacob Keller 
---
I brought this up about a year ago at [1], but Richard seemed to think the
ASAP behavior was expected.

I've had several users get confused and complain when they use ASAP and then
see timeouts.

I believe we should have the same behavior for both ASAP and timed restarts,
as it really doesn't make sense to clear the fault when we know that we'll
just fault again immediately.

 port.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/port.c b/port.c
index 871ad6818c20..756ff3a7b877 100644
--- a/port.c
+++ b/port.c
@@ -3412,7 +3412,7 @@ int port_state_update(struct port *p, enum fsm_event 
event, int mdiff)
if (PS_FAULTY == next) {
struct fault_interval i;
fault_interval(p, last_fault_type(p), );
-   if (clear_fault_asap()) {
+   if (port_link_status_get(p) && clear_fault_asap()) {
pr_notice("%s: clearing fault immediately", 
p->log_name);
next = p->state_machine(next, EV_FAULT_CLEARED, 0);
}
-- 
2.37.1.394.gc50926e1f488



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 1/2] phc2sys: move read_phc into clock_adj.c

2021-11-23 Thread Jacob Keller
The read_phc function implemented in phc2sys.c is used to perform clock
comparison between two arbitrary clocks using clock_gettime.

This support is used to allow phc2sys to work on any pair of clocks and
is implemented in a very similar manner as the kernel PTP_SYS_OFFSET
ioctls.

Make this function easier to re-use by moving it out of phc2sys.c and
into a more accessible location. clockadj.c seems like a reasonable
location as this file has many functions which deal with clockid_t
values, and this functionality is tangentially related to adjusting
clocks.

Moving this function will allow using it in the phc_ctl program in a
future change.

Notice that read_phc returned 0 on failure and 1 on success. This is
fairly non-standard, so lets update clockadj_compare to return 0 on
success and -1 on failure. Fix the call sites to check correctly and
report an error.

Signed-off-by: Jacob Keller 
---
 clockadj.c | 31 +++
 clockadj.h | 18 ++
 phc2sys.c  | 46 +-
 3 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/clockadj.c b/clockadj.c
index b5c78cd112ff..e8c5789864db 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -139,6 +139,37 @@ int clockadj_max_freq(clockid_t clkid)
return f;
 }
 
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay)
+{
+   struct timespec tdst1, tdst2, tsrc;
+   int i;
+   int64_t interval, best_interval = INT64_MAX;
+
+   /* Pick the quickest clkid reading. */
+   for (i = 0; i < readings; i++) {
+   if (clock_gettime(sysclk, ) ||
+   clock_gettime(clkid, ) ||
+   clock_gettime(sysclk, )) {
+   pr_err("failed to read clock: %m");
+   return -1;
+   }
+
+   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
+   tdst2.tv_nsec - tdst1.tv_nsec;
+
+   if (best_interval > interval) {
+   best_interval = interval;
+   *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
+   tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
+   *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
+   }
+   }
+   *delay = best_interval;
+
+   return 0;
+}
+
 void sysclk_set_leap(int leap)
 {
clockid_t clkid = CLOCK_REALTIME;
diff --git a/clockadj.h b/clockadj.h
index 43325c8d5d15..b63ae3864d34 100644
--- a/clockadj.h
+++ b/clockadj.h
@@ -63,6 +63,24 @@ void clockadj_step(clockid_t clkid, int64_t step);
  */
 int clockadj_max_freq(clockid_t clkid);
 
+/**
+ * Compare offset between two clocks
+ * @param clkid A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param sysclkA clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param readings  Number of readings to try
+ * @param offsetOn return, the nanoseconds offset between the clocks
+ * @param tsOn return, the time of sysclk in nanoseconds that was used
+ * @param delay On return, the interval between two reads of sysclk
+ * @return Zero on success and non-zero on failure.
+ *
+ * Compare the offset between two clocks in a similar manner as the
+ * PTP_SYS_OFFSET ioctls. Performs multiple reads of sysclk with a read of
+ * clkid between in order to calculate the time difference of sysclk minus
+ * clkid.
+ */
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay);
+
 /**
  * Set the system clock to insert/delete leap second at midnight.
  * @param leap  +1 to insert leap second, -1 to delete leap second,
diff --git a/phc2sys.c b/phc2sys.c
index 6815c3dee8a0..489e15bc0488 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -470,37 +470,6 @@ static void reconfigure(struct phc2sys_private *priv)
pr_info("selecting %s as the master clock", src->device);
 }
 
-static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
-   int64_t *offset, uint64_t *ts, int64_t *delay)
-{
-   struct timespec tdst1, tdst2, tsrc;
-   int i;
-   int64_t interval, best_interval = INT64_MAX;
-
-   /* Pick the quickest clkid reading. */
-   for (i = 0; i < readings; i++) {
-   if (clock_gettime(sysclk, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(sysclk, )) {
-   pr_err("failed to read clock: %m");
-   return 0;
-   }
-
-   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
-   tdst2.tv_nsec - tdst1.tv_nsec;
-
-   if (best_interval > interval) {
-   best_interval = interval;
-   *offse

[Linuxptp-devel] [PATCH v3 0/2] fix fallback clock_gettime for test_phc

2021-11-23 Thread Jacob Keller
The current implementation of test_phc cmp has a fallback flow for comparing
the PHC clock to the CLOCK_REAMTIME. This fallback flow calculates the
inverse offset compared to the offsets calculated by the PTP_SYS_OFFSET
ioctls.

Fix this by replacing its implementation with the one from phc2sys. Move
read_phc function into clockadj.c to re-use it.

Changes since v2
* Fix doxygen parameters to use @param
* Add @return for clockadj_compare
* Reword description so its clear that it is sysclk minus clkid.

Changes since v1
* Make clockadj_compare return -1 on failure and 0 on success
* Fix callsites in phc2sys to handle this change

Jacob Keller (2):
  phc2sys: move read_phc into clock_adj.c
  phc_ctl: replace calculate_offset with clockadj_compare

 clockadj.c | 31 +++
 clockadj.h | 18 ++
 phc2sys.c  | 46 +-
 phc_ctl.c  | 54 --
 4 files changed, 74 insertions(+), 75 deletions(-)

-- 
2.34.0



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v3 2/2] phc_ctl: replace calculate_offset with clockadj_compare

2021-11-23 Thread Jacob Keller
The phc_ctl program includes an implementation for comparing the PHC
with CLOCK_REALTIME when PTP_SYS_OFFSET ioctls are not supported.

This implementation produces inverted results when compared with the
implementation of the ioctl.

The PTP_SYS_OFFSET ioctls calculate the difference as "CLOCK_REALTIME -
PHC_TIME" while this function calculates "PHC_TIME - CLOCK_REALTIME".
This could produce confusing results if phc_ctl is used on a kernel
which lacks the PTP_SYS_OFFSET ioctls.

Fix this by replacing the bespoke implementation in test_phc with the
clockadj_compare function. That function mimics the interface of
sysoff_measure and correctly computes the time offset between the two
clocks in the same manner as the ioctls do. In addition, it supports
performing multiple samples to reduce inaccuracy.

With this change, the fallback implementation of measurement will match
the behavior of the ioctl based PTP_SYS_OFFSET flows.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 54 --
 1 file changed, 16 insertions(+), 38 deletions(-)

diff --git a/phc_ctl.c b/phc_ctl.c
index 673cb37e3583..e975dd803578 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -90,26 +90,6 @@ static int install_handler(int signum, void(*handler)(int))
return 0;
 }
 
-static int64_t calculate_offset(struct timespec *ts1,
- struct timespec *rt,
- struct timespec *ts2)
-{
-   int64_t interval;
-   int64_t offset;
-
-#define NSEC_PER_SEC 10ULL
-   /* calculate interval between clock realtime */
-   interval = (ts2->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   interval += ts2->tv_nsec - ts1->tv_nsec;
-
-   /* assume PHC read occured half way between CLOCK_REALTIME reads */
-
-   offset = (rt->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   offset += (rt->tv_nsec - ts1->tv_nsec) - (interval / 2);
-
-   return offset;
-}
-
 static void usage(const char *progname)
 {
fprintf(stderr,
@@ -335,34 +315,32 @@ static int do_caps(clockid_t clkid, int cmdc, char 
*cmdv[])
 
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
-   struct timespec ts, rta, rtb;
-   int64_t sys_offset, delay = 0, offset;
+   int64_t sys_offset, delay;
uint64_t sys_ts;
-   int method;
+   int method, fd;
 
-   method = sysoff_probe(CLOCKID_TO_FD(clkid), 9);
+#define N_SAMPLES 9
 
-   if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9,
+   fd = CLOCKID_TO_FD(clkid);
+
+   method = sysoff_probe(fd, N_SAMPLES);
+
+   if (method >= 0 && sysoff_measure(fd, method, N_SAMPLES,
  _offset, _ts, ) >= 0) {
-   pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n",
-   sys_offset);
+   pr_notice("offset from CLOCK_REALTIME is %"PRId64"ns\n",
+ sys_offset);
return 0;
}
 
-   memset(, 0, sizeof(ts));
-   memset(, 0, sizeof(rta));
-   memset(, 0, sizeof(rtb));
-   if (clock_gettime(CLOCK_REALTIME, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(CLOCK_REALTIME, )) {
-   pr_err("cmp: failed clock reads: %s\n",
-   strerror(errno));
+   if (clockadj_compare(clkid, CLOCK_REALTIME, N_SAMPLES,
+_offset, _ts, )) {
+   pr_err("cmp: failed to compare clocks: %s\n",
+  strerror(errno));
return -1;
}
 
-   offset = calculate_offset(, , );
-   pr_notice( "offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
-   offset);
+   pr_notice("offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
+ sys_offset);
 
return 0;
 }
-- 
2.34.0



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 0/2] fix fallback clock_gettime for test_phc

2021-10-22 Thread Jacob Keller
The current implementation of test_phc cmp has a fallback flow for comparing
the PHC clock to the CLOCK_REAMTIME. This fallback flow calculates the
inverse offset compared to the offsets calculated by the PTP_SYS_OFFSET
ioctls.

Fix this by replacing its implementation with the one from phc2sys. Move
read_phc function into clockadj.c to re-use it.

Changes since v1
* Make clockadj_compare return -1 on failure and 0 on success
* Fix callsites in phc2sys to handle this change

Jacob Keller (2):
  phc2sys: move read_phc into clock_adj.c
  phc_ctl: replace calculate_offset with clockadj_compare

 clockadj.c | 31 +++
 clockadj.h | 16 
 phc2sys.c  | 46 +-
 phc_ctl.c  | 54 --
 4 files changed, 72 insertions(+), 75 deletions(-)


base-commit: 63592effe3f3ff616a19bfff3757fd3dbd95baf5
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2 1/2] phc2sys: move read_phc into clock_adj.c

2021-10-22 Thread Jacob Keller
The read_phc function implemented in phc2sys.c is used to perform clock
comparison between two arbitrary clocks using clock_gettime.

This support is used to allow phc2sys to work on any pair of clocks and
is implemented in a very similar manner as the kernel PTP_SYS_OFFSET
ioctls.

Make this function easier to re-use by moving it out of phc2sys.c and
into a more accessible location. clockadj.c seems like a reasonable
location as this file has many functions which deal with clockid_t
values, and this functionality is tangentially related to adjusting
clocks.

Moving this function will allow using it in the phc_ctl program in a
future change.

Notice that read_phc returned 0 on failure and 1 on success. This is
fairly non-standard, so lets update clockadj_compare to return 0 on
success and -1 on failure. Fix the call sites to check correctly and
report an error.

Signed-off-by: Jacob Keller 
---
Changes since v1
* Make clockadj_compare return -1 on failure and 0 on success
* Fix callsites in phc2sys to handle this change

 clockadj.c | 31 +++
 clockadj.h | 16 
 phc2sys.c  | 46 +-
 3 files changed, 56 insertions(+), 37 deletions(-)

diff --git a/clockadj.c b/clockadj.c
index b5c78cd112ff..e8c5789864db 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -139,6 +139,37 @@ int clockadj_max_freq(clockid_t clkid)
return f;
 }
 
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay)
+{
+   struct timespec tdst1, tdst2, tsrc;
+   int i;
+   int64_t interval, best_interval = INT64_MAX;
+
+   /* Pick the quickest clkid reading. */
+   for (i = 0; i < readings; i++) {
+   if (clock_gettime(sysclk, ) ||
+   clock_gettime(clkid, ) ||
+   clock_gettime(sysclk, )) {
+   pr_err("failed to read clock: %m");
+   return -1;
+   }
+
+   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
+   tdst2.tv_nsec - tdst1.tv_nsec;
+
+   if (best_interval > interval) {
+   best_interval = interval;
+   *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
+   tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
+   *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
+   }
+   }
+   *delay = best_interval;
+
+   return 0;
+}
+
 void sysclk_set_leap(int leap)
 {
clockid_t clkid = CLOCK_REALTIME;
diff --git a/clockadj.h b/clockadj.h
index 43325c8d5d15..995b2af11894 100644
--- a/clockadj.h
+++ b/clockadj.h
@@ -63,6 +63,22 @@ void clockadj_step(clockid_t clkid, int64_t step);
  */
 int clockadj_max_freq(clockid_t clkid);
 
+/**
+ * Compare offset between two clocks
+ * @param clkid  A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param sysclk A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @readings Number of readings to try
+ * @offset   On return, the nanoseconds offset between the clocks
+ * @ts   On return, the time of sysclk in nanoseconds that was used
+ * @delayOn return, the interval between two reads of sysclk
+ *
+ * Compare the offset between two clocks in a similar manner as the
+ * PTP_SYS_OFFSET ioctls. Returns the difference between sysclk and clkid by
+ * performing multiple reads of sysclk with a read of clkid between.
+ */
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay);
+
 /**
  * Set the system clock to insert/delete leap second at midnight.
  * @param leap  +1 to insert leap second, -1 to delete leap second,
diff --git a/phc2sys.c b/phc2sys.c
index 6815c3dee8a0..489e15bc0488 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -470,37 +470,6 @@ static void reconfigure(struct phc2sys_private *priv)
pr_info("selecting %s as the master clock", src->device);
 }
 
-static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
-   int64_t *offset, uint64_t *ts, int64_t *delay)
-{
-   struct timespec tdst1, tdst2, tsrc;
-   int i;
-   int64_t interval, best_interval = INT64_MAX;
-
-   /* Pick the quickest clkid reading. */
-   for (i = 0; i < readings; i++) {
-   if (clock_gettime(sysclk, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(sysclk, )) {
-   pr_err("failed to read clock: %m");
-   return 0;
-   }
-
-   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
-   tdst2.tv_nsec - tdst1.tv_nsec;
-
-   if (best_interval > interval) {
-   best_interva

[Linuxptp-devel] [PATCH v2 2/2] phc_ctl: replace calculate_offset with clockadj_compare

2021-10-22 Thread Jacob Keller
The phc_ctl program includes an implementation for comparing the PHC
with CLOCK_REALTIME when PTP_SYS_OFFSET ioctls are not supported.

This implementation produces inverted results when compared with the
implementation of the ioctl.

The PTP_SYS_OFFSET ioctls calculate the difference as "CLOCK_REALTIME -
PHC_TIME" while this function calculates "PHC_TIME - CLOCK_REALTIME".
This could produce confusing results if phc_ctl is used on a kernel
which lacks the PTP_SYS_OFFSET ioctls.

Fix this by replacing the bespoke implementation in test_phc with the
clockadj_compare function. That function mimics the interface of
sysoff_measure and correctly computes the time offset between the two
clocks in the same manner as the ioctls do. In addition, it supports
performing multiple samples to reduce inaccuracy.

With this change, the fallback implementation of measurement will match
the behavior of the ioctl based PTP_SYS_OFFSET flows.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 54 --
 1 file changed, 16 insertions(+), 38 deletions(-)

diff --git a/phc_ctl.c b/phc_ctl.c
index 673cb37e3583..e975dd803578 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -90,26 +90,6 @@ static int install_handler(int signum, void(*handler)(int))
return 0;
 }
 
-static int64_t calculate_offset(struct timespec *ts1,
- struct timespec *rt,
- struct timespec *ts2)
-{
-   int64_t interval;
-   int64_t offset;
-
-#define NSEC_PER_SEC 10ULL
-   /* calculate interval between clock realtime */
-   interval = (ts2->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   interval += ts2->tv_nsec - ts1->tv_nsec;
-
-   /* assume PHC read occured half way between CLOCK_REALTIME reads */
-
-   offset = (rt->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   offset += (rt->tv_nsec - ts1->tv_nsec) - (interval / 2);
-
-   return offset;
-}
-
 static void usage(const char *progname)
 {
fprintf(stderr,
@@ -335,34 +315,32 @@ static int do_caps(clockid_t clkid, int cmdc, char 
*cmdv[])
 
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
-   struct timespec ts, rta, rtb;
-   int64_t sys_offset, delay = 0, offset;
+   int64_t sys_offset, delay;
uint64_t sys_ts;
-   int method;
+   int method, fd;
 
-   method = sysoff_probe(CLOCKID_TO_FD(clkid), 9);
+#define N_SAMPLES 9
 
-   if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9,
+   fd = CLOCKID_TO_FD(clkid);
+
+   method = sysoff_probe(fd, N_SAMPLES);
+
+   if (method >= 0 && sysoff_measure(fd, method, N_SAMPLES,
  _offset, _ts, ) >= 0) {
-   pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n",
-   sys_offset);
+   pr_notice("offset from CLOCK_REALTIME is %"PRId64"ns\n",
+ sys_offset);
return 0;
}
 
-   memset(, 0, sizeof(ts));
-   memset(, 0, sizeof(rta));
-   memset(, 0, sizeof(rtb));
-   if (clock_gettime(CLOCK_REALTIME, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(CLOCK_REALTIME, )) {
-   pr_err("cmp: failed clock reads: %s\n",
-   strerror(errno));
+   if (clockadj_compare(clkid, CLOCK_REALTIME, N_SAMPLES,
+_offset, _ts, )) {
+   pr_err("cmp: failed to compare clocks: %s\n",
+  strerror(errno));
return -1;
}
 
-   offset = calculate_offset(, , );
-   pr_notice( "offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
-   offset);
+   pr_notice("offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
+ sys_offset);
 
return 0;
 }
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 1/2] phc2sys: move read_phc into clock_adj.c

2021-10-22 Thread Jacob Keller
The read_phc function implemented in phc2sys.c is used to perform clock
comparison between two arbitrary clocks using clock_gettime.

This support is used to allow phc2sys to work on any pair of clocks and
is implemented in a very similar manner as the kernel PTP_SYS_OFFSET
ioctls.

Make this function easier to re-use by moving it out of phc2sys.c and
into a more accessible location. clockadj.c seems like a reasonable
location as this file has many functions which deal with clockid_t
values, and this functionality is tangentially related to adjusting
clocks.

Moving this function will allow using it in the phc_ctl program in a
future change.

Signed-off-by: Jacob Keller 
---
 clockadj.c | 31 +++
 clockadj.h | 16 
 phc2sys.c  | 44 
 3 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/clockadj.c b/clockadj.c
index b5c78cd112ff..c78017049a0e 100644
--- a/clockadj.c
+++ b/clockadj.c
@@ -139,6 +139,37 @@ int clockadj_max_freq(clockid_t clkid)
return f;
 }
 
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay)
+{
+   struct timespec tdst1, tdst2, tsrc;
+   int i;
+   int64_t interval, best_interval = INT64_MAX;
+
+   /* Pick the quickest clkid reading. */
+   for (i = 0; i < readings; i++) {
+   if (clock_gettime(sysclk, ) ||
+   clock_gettime(clkid, ) ||
+   clock_gettime(sysclk, )) {
+   pr_err("failed to read clock: %m");
+   return 0;
+   }
+
+   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
+   tdst2.tv_nsec - tdst1.tv_nsec;
+
+   if (best_interval > interval) {
+   best_interval = interval;
+   *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
+   tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
+   *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
+   }
+   }
+   *delay = best_interval;
+
+   return 1;
+}
+
 void sysclk_set_leap(int leap)
 {
clockid_t clkid = CLOCK_REALTIME;
diff --git a/clockadj.h b/clockadj.h
index 43325c8d5d15..995b2af11894 100644
--- a/clockadj.h
+++ b/clockadj.h
@@ -63,6 +63,22 @@ void clockadj_step(clockid_t clkid, int64_t step);
  */
 int clockadj_max_freq(clockid_t clkid);
 
+/**
+ * Compare offset between two clocks
+ * @param clkid  A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @param sysclk A clock ID obtained using phc_open() or CLOCK_REALTIME
+ * @readings Number of readings to try
+ * @offset   On return, the nanoseconds offset between the clocks
+ * @ts   On return, the time of sysclk in nanoseconds that was used
+ * @delayOn return, the interval between two reads of sysclk
+ *
+ * Compare the offset between two clocks in a similar manner as the
+ * PTP_SYS_OFFSET ioctls. Returns the difference between sysclk and clkid by
+ * performing multiple reads of sysclk with a read of clkid between.
+ */
+int clockadj_compare(clockid_t clkid, clockid_t sysclk, int readings,
+int64_t *offset, uint64_t *ts, int64_t *delay);
+
 /**
  * Set the system clock to insert/delete leap second at midnight.
  * @param leap  +1 to insert leap second, -1 to delete leap second,
diff --git a/phc2sys.c b/phc2sys.c
index 6815c3dee8a0..5a14b0da8786 100644
--- a/phc2sys.c
+++ b/phc2sys.c
@@ -470,37 +470,6 @@ static void reconfigure(struct phc2sys_private *priv)
pr_info("selecting %s as the master clock", src->device);
 }
 
-static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
-   int64_t *offset, uint64_t *ts, int64_t *delay)
-{
-   struct timespec tdst1, tdst2, tsrc;
-   int i;
-   int64_t interval, best_interval = INT64_MAX;
-
-   /* Pick the quickest clkid reading. */
-   for (i = 0; i < readings; i++) {
-   if (clock_gettime(sysclk, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(sysclk, )) {
-   pr_err("failed to read clock: %m");
-   return 0;
-   }
-
-   interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC +
-   tdst2.tv_nsec - tdst1.tv_nsec;
-
-   if (best_interval > interval) {
-   best_interval = interval;
-   *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC +
-   tdst1.tv_nsec - tsrc.tv_nsec + interval / 2;
-   *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec;
-   }
-   }
-   *delay = best_interval;
-
-   return 1;
-}
-
 static int64_t get_sync_offset(st

[Linuxptp-devel] [PATCH 2/2] phc_ctl: replace calculate_offset with clockadj_compare

2021-10-22 Thread Jacob Keller
The phc_ctl program includes an implementation for comparing the PHC
with CLOCK_REALTIME when PTP_SYS_OFFSET ioctls are not supported.

This implementation produces inverted results when compared with the
implementation of the ioctl.

The PTP_SYS_OFFSET ioctls calculate the difference as "CLOCK_REALTIME -
PHC_TIME" while this function calculates "PHC_TIME - CLOCK_REALTIME".
This could produce confusing results if phc_ctl is used on a kernel
which lacks the PTP_SYS_OFFSET ioctls.

Fix this by replacing the bespoke implementation in test_phc with the
clockadj_compare function. That function mimics the interface of
sysoff_measure and correctly computes the time offset between the two
clocks in the same manner as the ioctls do. In addition, it supports
performing multiple samples to reduce inaccuracy.

With this change, the fallback implementation of measurement will match
the behavior of the ioctl based PTP_SYS_OFFSET flows.

Signed-off-by: Jacob Keller 
---
 phc_ctl.c | 54 --
 1 file changed, 16 insertions(+), 38 deletions(-)

diff --git a/phc_ctl.c b/phc_ctl.c
index 673cb37e3583..e975dd803578 100644
--- a/phc_ctl.c
+++ b/phc_ctl.c
@@ -90,26 +90,6 @@ static int install_handler(int signum, void(*handler)(int))
return 0;
 }
 
-static int64_t calculate_offset(struct timespec *ts1,
- struct timespec *rt,
- struct timespec *ts2)
-{
-   int64_t interval;
-   int64_t offset;
-
-#define NSEC_PER_SEC 10ULL
-   /* calculate interval between clock realtime */
-   interval = (ts2->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   interval += ts2->tv_nsec - ts1->tv_nsec;
-
-   /* assume PHC read occured half way between CLOCK_REALTIME reads */
-
-   offset = (rt->tv_sec - ts1->tv_sec) * NSEC_PER_SEC;
-   offset += (rt->tv_nsec - ts1->tv_nsec) - (interval / 2);
-
-   return offset;
-}
-
 static void usage(const char *progname)
 {
fprintf(stderr,
@@ -335,34 +315,32 @@ static int do_caps(clockid_t clkid, int cmdc, char 
*cmdv[])
 
 static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[])
 {
-   struct timespec ts, rta, rtb;
-   int64_t sys_offset, delay = 0, offset;
+   int64_t sys_offset, delay;
uint64_t sys_ts;
-   int method;
+   int method, fd;
 
-   method = sysoff_probe(CLOCKID_TO_FD(clkid), 9);
+#define N_SAMPLES 9
 
-   if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9,
+   fd = CLOCKID_TO_FD(clkid);
+
+   method = sysoff_probe(fd, N_SAMPLES);
+
+   if (method >= 0 && sysoff_measure(fd, method, N_SAMPLES,
  _offset, _ts, ) >= 0) {
-   pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n",
-   sys_offset);
+   pr_notice("offset from CLOCK_REALTIME is %"PRId64"ns\n",
+ sys_offset);
return 0;
}
 
-   memset(, 0, sizeof(ts));
-   memset(, 0, sizeof(rta));
-   memset(, 0, sizeof(rtb));
-   if (clock_gettime(CLOCK_REALTIME, ) ||
-   clock_gettime(clkid, ) ||
-   clock_gettime(CLOCK_REALTIME, )) {
-   pr_err("cmp: failed clock reads: %s\n",
-   strerror(errno));
+   if (clockadj_compare(clkid, CLOCK_REALTIME, N_SAMPLES,
+_offset, _ts, )) {
+   pr_err("cmp: failed to compare clocks: %s\n",
+  strerror(errno));
return -1;
}
 
-   offset = calculate_offset(, , );
-   pr_notice( "offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
-   offset);
+   pr_notice("offset from CLOCK_REALTIME is approximately %"PRId64"ns\n",
+ sys_offset);
 
return 0;
 }
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH 0/2] fix fallback clock_gettime for test_phc

2021-10-22 Thread Jacob Keller
The current implementation of test_phc cmp has a fallback flow for comparing
the PHC clock to the CLOCK_REAMTIME. This fallback flow calculates the
inverse offset compared to the offsets calculated by the PTP_SYS_OFFSET
ioctls.

Fix this by replacing its implementation with the one from phc2sys. Move
read_phc function into clockadj.c to re-use it.

Jacob Keller (2):
  phc2sys: move read_phc into clock_adj.c
  phc_ctl: replace calculate_offset with clockadj_compare

 clockadj.c | 31 +++
 clockadj.h | 16 
 phc2sys.c  | 44 
 phc_ctl.c  | 54 --
 4 files changed, 71 insertions(+), 74 deletions(-)


base-commit: 63592effe3f3ff616a19bfff3757fd3dbd95baf5
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH v2] Increase the default tx_timestamp_timeout to 10

2021-07-08 Thread Jacob Keller
The tx_timestamp_timeout configuration defines the number of
milliseconds to wait for a Tx timestamp from the kernel stack. This
delay is necessary as Tx timestamps are captured after a packet is sent
and reported back via the socket error queue.

The current default is to poll for up to 1 millisecond. In practice, it
turns out that this is not always enough time for hardware and software
to capture the timestamp and report it back. Some hardware designs
require reading timestamps over registers or other slow mechanisms.

This extra delay results in the timestamp not being sent back to
userspace within the default 1 millisecond polling time. If that occurs
the following can be seen from ptp4l:

  ptp4l[4756.840]: timed out while polling for tx timestamp
  ptp4l[4756.840]: increasing tx_timestamp_timeout may correct this issue,
   but it is likely caused by a driver bug
  ptp4l[4756.840]: port 1 (p2p1): send sync failed
  ptp4l[4756.840]: port 1 (p2p1): MASTER to FAULTY on FAULT_DETECTED
   (FT_UNSPECIFIED)

This can confuse users because it implies this is a bug, when the
correct solution in many cases is to just increase the timeout to
a slightly higher value.

Since we know this is a problem for many drivers and hardware designs,
lets increase the default timeout.

Note that a longer timeout should not affect setups which return the
timestamp quickly. On modern kernels, the poll() call will return once
the timestamp is reported back to the socket error queue. (On old
kernels around the 3.x era the poll will sleep for the full duration
before reporting the timestamp, but this is now quite an old kernel
release).

Signed-off-by: Jacob Keller 
---
 config.c| 2 +-
 configs/default.cfg | 2 +-
 ptp4l.8 | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index 4472d3d9d6f9..d0f011c0e165 100644
--- a/config.c
+++ b/config.c
@@ -323,7 +323,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("ts2phc.pulsewidth", 5, 100, 99900),
PORT_ITEM_ENU("tsproc_mode", TSPROC_FILTER, tsproc_enu),
GLOB_ITEM_INT("twoStepFlag", 1, 0, 1),
-   GLOB_ITEM_INT("tx_timestamp_timeout", 1, 1, INT_MAX),
+   GLOB_ITEM_INT("tx_timestamp_timeout", 10, 1, INT_MAX),
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
diff --git a/configs/default.cfg b/configs/default.cfg
index 64ef3bd7c81d..d61561072334 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -51,7 +51,7 @@ hybrid_e2e0
 inhibit_multicast_service  0
 net_sync_monitor   0
 tc_spanning_tree   0
-tx_timestamp_timeout   1
+tx_timestamp_timeout   10
 unicast_listen 0
 unicast_master_table   0
 unicast_req_duration   3600
diff --git a/ptp4l.8 b/ptp4l.8
index fe9e1502231c..7ca3474304e6 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -496,7 +496,7 @@ switches all implement this option together with the BMCA.
 .B tx_timestamp_timeout
 The number of milliseconds to poll waiting for the tx time stamp from the 
kernel
 when a message has recently been sent.
-The default is 1.
+The default is 10.
 .TP
 .B check_fup_sync
 Because of packet reordering that can occur in the network, in the
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


[Linuxptp-devel] [PATCH] Increase the default tx_timestamp_timeout to 5

2021-07-07 Thread Jacob Keller
The tx_timestamp_timeout configuration defines the number of
milliseconds to wait for a Tx timestamp from the kernel stack. This
delay is necessary as Tx timestamps are captured after a packet is sent
and reported back via the socket error queue.

The current default is to poll for up to 1 millisecond. In practice, it
turns out that this is not always enough time for hardware and software
to capture the timestamp and report it back. Some hardware designs
require reading timestamps over registers or other slow mechanisms.

This extra delay results in the timestamp not being sent back to
userspace within the default 1 millisecond polling time. If that occurs
the following can be seen from ptp4l:

  ptp4l[4756.840]: timed out while polling for tx timestamp
  ptp4l[4756.840]: increasing tx_timestamp_timeout may correct this issue,
   but it is likely caused by a driver bug
  ptp4l[4756.840]: port 1 (p2p1): send sync failed
  ptp4l[4756.840]: port 1 (p2p1): MASTER to FAULTY on FAULT_DETECTED
   (FT_UNSPECIFIED)

This can confuse users because it implies this is a bug, when the
correct solution in many cases is to just increase the timeout to
a slightly higher value.

Since we know this is a problem for many drivers and hardware designs,
lets increase the default timeout. I chose 5 since it is a large enough
increase to avoid the issues on test systems I have. We do want to keep
this timeout small because it prevents ptp4l from doing any other
processing while we wait for the timestamp.

An alternative solution would be to refactor ptp4l so that it does not
stop and wait for a Tx timestamp, but instead handles the timestamps
asynchronously. While this could be done, it adds significant complexity
to the application with minimal or no gain. In most cases, hardware is
only capable of a single outstanding timestamp at a time, so we cannot
send another packet anyways until the first one has completed.

Signed-off-by: Jacob Keller 
---
 config.c| 2 +-
 configs/default.cfg | 2 +-
 ptp4l.8 | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index 4472d3d9d6f9..f33f177c696a 100644
--- a/config.c
+++ b/config.c
@@ -323,7 +323,7 @@ struct config_item config_tab[] = {
GLOB_ITEM_INT("ts2phc.pulsewidth", 5, 100, 99900),
PORT_ITEM_ENU("tsproc_mode", TSPROC_FILTER, tsproc_enu),
GLOB_ITEM_INT("twoStepFlag", 1, 0, 1),
-   GLOB_ITEM_INT("tx_timestamp_timeout", 1, 1, INT_MAX),
+   GLOB_ITEM_INT("tx_timestamp_timeout", 5, 1, INT_MAX),
PORT_ITEM_INT("udp_ttl", 1, 1, 255),
PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
diff --git a/configs/default.cfg b/configs/default.cfg
index 64ef3bd7c81d..5e9444da57ee 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -51,7 +51,7 @@ hybrid_e2e0
 inhibit_multicast_service  0
 net_sync_monitor   0
 tc_spanning_tree   0
-tx_timestamp_timeout   1
+tx_timestamp_timeout   5
 unicast_listen 0
 unicast_master_table   0
 unicast_req_duration   3600
diff --git a/ptp4l.8 b/ptp4l.8
index fe9e1502231c..024fad3d19b2 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -496,7 +496,7 @@ switches all implement this option together with the BMCA.
 .B tx_timestamp_timeout
 The number of milliseconds to poll waiting for the tx time stamp from the 
kernel
 when a message has recently been sent.
-The default is 1.
+The default is 5.
 .TP
 .B check_fup_sync
 Because of packet reordering that can occur in the network, in the
-- 
2.31.1.331.gb0c09ab8796f



___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] Add setting of PTP_TIMESCALE flag

2021-06-14 Thread Jacob Keller



On 6/14/2021 5:03 AM, Miklas, Marcin via Linuxptp-devel wrote:
> From: Marcin Miklas 
> 
> In gPTP PTP_TIMESCALE flag should be set to 1. It looks like the flags
> where not properly set for any of messages used in gPTP.
> 
> Some of the automotive gPTP bridges where rejecting the PDelayReq messages
> because of missing flag.
> 
> I would say that both linuxptp and the bridge doesn't conform to gPTP
> specification where it is said that the PTP_TIMESCALE should be set to 1
> and ignored on reception.
> 

If I recall, this has been discussed on the list multiple times before.

https://sourceforge.net/p/linuxptp/mailman/message/34977023/

According to the normal 1588 standard, the bit is not supposed to be set
for these messages.

Perhaps an optional configuration to set these would be acceptable
though. (Then the gPTP config file could use that flag to make sure it
is set)

> Signed-off-by: Marcin Miklas 
> ---
>  port.c   | 5 +
>  port_signaling.c | 1 +
>  2 files changed, 6 insertions(+)
> 
> diff --git a/port.c b/port.c
> index 8175f28..f906a6c 100644
> --- a/port.c
> +++ b/port.c
> @@ -1362,6 +1362,7 @@ static int port_pdelay_request(struct port *p)
>   msg->header.ver= PTP_VERSION;
>   msg->header.messageLength  = sizeof(struct pdelay_req_msg);
>   msg->header.domainNumber   = clock_domain_number(p->clock);
> + msg->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   msg->header.correction = -p->asymmetry;
>   msg->header.sourcePortIdentity = p->portIdentity;
>   msg->header.sequenceId = p->seqnum.delayreq++;
> @@ -1556,6 +1557,7 @@ int port_tx_sync(struct port *p, struct address *dst)
>   msg->header.ver= PTP_VERSION;
>   msg->header.messageLength  = sizeof(struct sync_msg);
>   msg->header.domainNumber   = clock_domain_number(p->clock);
> + msg->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   msg->header.sourcePortIdentity = p->portIdentity;
>   msg->header.sequenceId = p->seqnum.sync++;
>   msg->header.control= CTL_SYNC;
> @@ -1592,6 +1594,7 @@ int port_tx_sync(struct port *p, struct address *dst)
>   fup->header.ver= PTP_VERSION;
>   fup->header.messageLength  = sizeof(struct follow_up_msg);
>   fup->header.domainNumber   = clock_domain_number(p->clock);
> + fup->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   fup->header.sourcePortIdentity = p->portIdentity;
>   fup->header.sequenceId = p->seqnum.sync - 1;
>   fup->header.control= CTL_FOLLOW_UP;
> @@ -2123,6 +2126,7 @@ int process_pdelay_req(struct port *p, struct 
> ptp_message *m)
>   rsp->header.ver= PTP_VERSION;
>   rsp->header.messageLength  = sizeof(struct pdelay_resp_msg);
>   rsp->header.domainNumber   = m->header.domainNumber;
> + rsp->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   rsp->header.sourcePortIdentity = p->portIdentity;
>   rsp->header.sequenceId = m->header.sequenceId;
>   rsp->header.control= CTL_OTHER;
> @@ -2170,6 +2174,7 @@ int process_pdelay_req(struct port *p, struct 
> ptp_message *m)
>   fup->header.ver= PTP_VERSION;
>   fup->header.messageLength  = sizeof(struct pdelay_resp_fup_msg);
>   fup->header.domainNumber   = m->header.domainNumber;
> + fup->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   fup->header.correction = m->header.correction;
>   fup->header.sourcePortIdentity = p->portIdentity;
>   fup->header.sequenceId = m->header.sequenceId;
> diff --git a/port_signaling.c b/port_signaling.c
> index ed217c0..c76bfdf 100644
> --- a/port_signaling.c
> +++ b/port_signaling.c
> @@ -44,6 +44,7 @@ struct ptp_message *port_signaling_construct(struct port *p,
>   msg->header.ver= PTP_VERSION;
>   msg->header.messageLength  = sizeof(struct signaling_msg);
>   msg->header.domainNumber   = clock_domain_number(p->clock);
> + msg->header.flagField[1]   = clock_time_properties(p->clock).flags;
>   msg->header.sourcePortIdentity = p->portIdentity;
>   msg->header.sequenceId = p->seqnum.signaling++;
>   msg->header.control= CTL_OTHER;
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] Recover a faulty master port

2021-06-09 Thread Jacob Keller



On 6/7/2021 1:19 PM, YENDstudio wrote:
> Hello,
> 
> I have configure one of my machines as a unicast BC which is
> synchronized to the grandmaster clock via the first of it's two ports.
> The second port is used to provide sync to another local machine. This
> setup works for a few hours after which one of the ports (master port)
> is marked as faulty, and it never recovers (the second machine stops
> receiving sync) until I restart the ptp4l application. Yet, the first
> port continues sync'ing with the grandmaster clock.
> > The fault is triggered by a timeout during polling of tx timestamp
> (sk_receive function call). As I am not able to fix this issue, I would
> like to at least make the ptp application recover the port
> automatically. I had tried to close-then-open the port when it goes to a
> FAULTY state but it didn't help (the slave machine is not able to sync).
> 

Hi,

ptp4l already attempts recovery from a fault after the fault reset
timeout. This is something like 15 seconds by default.

You should see it recover, something like:


> ptp4l[1022068.490]: selected /dev/ptp2 as PTP clock
> ptp4l[1022068.510]: port 1 (enp244s0f0): INITIALIZING to LISTENING on 
> INIT_COMPLETE
> ptp4l[1022068.510]: port 0 (/var/run/ptp4l): INITIALIZING to LISTENING on 
> INIT_COMPLETE
> ptp4l[1022068.510]: port 0 (/var/run/ptp4lro): INITIALIZING to LISTENING on 
> INIT_COMPLETE
> ptp4l[1022070.454]: port 1 (enp244s0f0): new foreign master 
> 527b94.fffe.96b1f3-1
> ptp4l[1022074.454]: selected best master clock 527b94.fffe.96b1f3
> ptp4l[1022074.454]: port 1 (enp244s0f0): LISTENING to UNCALIBRATED on RS_SLAVE
> ptp4l[1022076.454]: master offset 3148999551 s0 freq  +0 path delay  
> 1466
> ptp4l[1022077.482]: master offset 3149000658 s1 freq   +1107 path delay  
> 1615
> ptp4l[1022078.029]: timed out while polling for tx timestamp
> ptp4l[1022078.029]: increasing tx_timestamp_timeout may correct this issue, 
> but it is likely caused by a driver bug
> ptp4l[1022078.029]: port 1 (enp244s0f0): send delay request failed
> ptp4l[1022078.029]: port 1 (enp244s0f0): UNCALIBRATED to FAULTY on 
> FAULT_DETECTED (FT_UNSPECIFIED)
> ptp4l[1022082.057]: port 1 (enp244s0f0): FAULTY to LISTENING on INIT_COMPLETE

^^^
Specifically here.

> ptp4l[1022082.455]: port 1 (enp244s0f0): new foreign master 
> 527b94.fffe.96b1f3-1
> ptp4l[1022086.455]: selected best master clock 527b94.fffe.96b1f3
> ptp4l[1022086.455]: port 1 (enp244s0f0): LISTENING to UNCALIBRATED on RS_SLAVE
> ptp4l[1022087.460]: master offset   -7124120 s2 freq -7123013 path delay  
> 1615
> ptp4l[1022087.460]: port 1 (enp244s0f0): UNCALIBRATED to SLAVE on 
> MASTER_CLOCK_SELECTED
> ptp4l[1022088.460]: master offset -39903 s2 freq -2176032 path delay  
> 1615
> ptp4l[1022089.460]: master offset2165416 s2 freq  +17316 path delay  
> 1466
> ptp4l[1022090.460]: master offset2161742 s2 freq +663267 path delay  
> 1615
> ptp4l[1022091.460]: master offset1503260 s2 freq +653307 path delay  
> 1615
> ptp4l[1022092.460]: master offset 850970 s2 freq +451995 path delay  
> 1764
> ptp4l[1022093.460]: master offset 398679 s2 freq +254995 path delay  
> 2160
> ptp4l[1022094.460]: master offset 143441 s2 freq +119361 path delay  
> 2556
> ptp4l[1022095.460]: master offset   2567 s2 freq  +21519 path delay 
> 24523


If you're seeing that but it fails to actually recover, (i.e.e
timestamps never begin working again), this is likely a fault of the
driver or hardware for the device.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [Linuxptp-users] phc2sys jump into huge value

2021-04-29 Thread Jacob Keller


On 4/29/2021 8:04 AM, ramesh t wrote:
> hello Jake,
> 
> Did time profiling using time ticks. 
> Under the problem condition, observing clock_gettime of interface
> connected to BC is taking more time ticks. This results in phc offset
> jumping to 4 digit value momentarily. Also i'm not sure if reading
> across numa is triggering this issue.
> 

Not sure I follow here. You mean BC as in the boundary clock you're
connected to?

> Please suggest a way to fix in the phc2sys offset code?
> 1) Should we prevent update on phc2sys value if there is momentarily jump?
> 

You could possibly filter or average the delay to remove outliers, but I
am not sure how this impacts things. Other experts on this list are
probably better to answer that.

To me, it sounds like the issue is that in some cases the DELAY_REQ
packet is actually taking longer in one case.

You might also try peer delay instead if your network setup supports it?

> Please suggest.
> 
> Thanks for your support on this issue.
> 
> Regards,
> Ramesh 
> On Thursday, April 29, 2021, 07:33:49 AM GMT+5:30, ramesh t via
> Linuxptp-users  wrote:


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 0/1] Add master only management TLV

2021-04-22 Thread Jacob Keller


On 4/22/2021 8:46 AM, Luigi 'Comio' Mantellini wrote:
> Generally speaking and in my opinion should be interesting to have the
> following features:
>  - asynchronous clock adjust: I2c is a slow bus with unpredictable
> access time, especially when you have a lot of devices. this is a true
> story.
>  - a thread for each port that handles the ptp protocol and the
> timeouts: this will make more robust the stack on issues depending on TX
> timestamping.
>  - a capability to use transport/interfaces different from linux
> interfaces, loading a custom  .so file. i.e. timestamper send back the
> TS using in band communication.
>  - ability to add/remove ports on the fly without traffic hit.
>  - ability to change all port configurable parameters on the fly.
> 
> My wishlist is from customer requirements, of course.
> 
Most of these do sound like great features to have, but many would
require significant architecture changes. As LinuxPTP is an open source
project, you (or your customers) are free to work on such improvements
and contribute them back.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] SyncE support

2021-03-30 Thread Jacob Keller



On 3/22/2021 8:40 AM, Miroslav Lichvar wrote:
> FWIW, some onboard NICs supported by the e1000e driver can
> "cross-timestamp" using the Always Running Timer (ART), which should
> avoid the asymmetry of PCIe. I have not seen any detailed description
> of how it actually works.
>

I'm not sure in the e1000e case but in general this is done via PCIe
Precision Time Measurement extension which allows an end-point device
that supports the function to setup a transaction that captures the
device clock and ART value near-simultaneously.

I think the e1000e support might be a variation of this which pre-dated
the PTM standard and works when the device is a LAN-on-motherboard.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/2] Clock Class Threshold Feature addition for PTP4L

2021-02-16 Thread Jacob Keller



On 2/14/2021 9:59 PM, Karthikkumar V wrote:
> Implemented code review comments.
> This code changes brings in the ability to program the acceptable
> clockClass threshold beyond which device will move to holdover/free-run.
> Default clockClass threshold is 248.
> Example Use-Case
> This is needed in the cases where T-SC/T-BC Slave might want to listen
> only on PRC clockCLass and anything beyond that might not be acceptible
> and would want to go to holdover (with SyncE backup or internal
> oscillator).
> 
> Signed-off-by: Karthikkumar V 
> Signed-off-by: Ramana Reddy 
> ---
>  clock.c | 4 ++--
>  config.c| 2 +-
>  configs/default.cfg | 2 +-
>  port.c  | 7 +--
>  ptp4l.8 | 5 +
>  5 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index 542f409..c40476f 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -969,7 +969,7 @@ struct clock *clock_create(enum clock_type type, struct 
> config *config,
>   c->default_dataset.localPriority =
>   config_get_int(config, NULL, "G.8275.defaultDS.localPriority");
>   c->max_steps_removed = config_get_int(config, NULL,"maxStepsRemoved");
> - c->clock_class_threshold = config_get_int(config, NULL, 
> "clockClassThreshold");
> + c->clock_class_threshold = config_get_int(config, NULL, 
> "clock_class_threshold");
>  


Why this change? It seems weird to remove this variable and introduce
another? clockClassThreshold is supposed to be the standard isn't it?

>   /* Harmonize the twoStepFlag with the time_stamping option. */
>   if (config_harmonize_onestep(config)) {
> @@ -1660,7 +1660,7 @@ UInteger8 clock_max_steps_removed(struct clock *c)
>  
>  UInteger8 clock_get_clock_class_threshold(struct clock *c)
>  {
> - if(c != NULL){
> + if (c != NULL) {
>   return c->clock_class_threshold;
>   }
>   return CLOCK_CLASS_THRESHOLD_DEFAULT; /* Return Default Value  */
> diff --git a/config.c b/config.c
> index 41735d3..c840d98 100644
> --- a/config.c
> +++ b/config.c
> @@ -231,6 +231,7 @@ struct config_item config_tab[] = {
>   GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX),
>   GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX),
>   GLOB_ITEM_STR("clockIdentity", "00..00"),
> + GLOB_ITEM_INT("clock_class_threshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 
> 6, CLOCK_CLASS_THRESHOLD_DEFAULT),
>   GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu),
>   GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu),
>   GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu),
> @@ -332,7 +333,6 @@ struct config_item config_tab[] = {
>   GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX),
>   GLOB_ITEM_INT("verbose", 0, 0, 1),
>   GLOB_ITEM_INT("write_phase_mode", 0, 0, 1),
> - GLOB_ITEM_INT("clockClassThreshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 6, 
> CLOCK_CLASS_THRESHOLD_DEFAULT),
>  };
>  
>  static struct unicast_master_table *current_uc_mtab;
> diff --git a/configs/default.cfg b/configs/default.cfg
> index 473bbb9..e863239 100644
> --- a/configs/default.cfg
> +++ b/configs/default.cfg
> @@ -29,7 +29,7 @@ logMinDelayReqInterval  0
>  logMinPdelayReqInterval  0
>  operLogPdelayReqInterval 0
>  announceReceiptTimeout   3
> -clockClassThreshold  248
> +clock_class_threshold248
>  syncReceiptTimeout   0
>  delayAsymmetry   0
>  fault_reset_interval 4
> diff --git a/port.c b/port.c
> index ae2a00e..024370f 100644
> --- a/port.c
> +++ b/port.c
> @@ -1861,8 +1861,11 @@ int process_announce(struct port *p, struct 
> ptp_message *m)
>   return result;
>   }
>  
> - /* If the clock class is greater than clock_class_threshold , ignore 
> this master */
> - if(m->announce.grandmasterClockQuality.clockClass > 
> clock_get_clock_class_threshold(p->clock)){
> + if (m->announce.grandmasterClockQuality.clockClass >
> + clock_get_clock_class_threshold(p->clock)) {
> + pl_err(60, "%s: Master clock quality received is "
> +  "greater than configured, ignoring master!",
> +  p->log_name);
>   return result;
>   }
>  
> diff --git a/ptp4l.8 b/ptp4l.8
> index 260aae3..b13471b 100644
> --- a/ptp4l.8
> +++ b/ptp4l.8
> @@ -455,6 +455,11 @@ message is greater than or equal to the value of 
> maxStepsRemoved the
>  Announce message is not considered in the operation of the BMCA.
>  The default value is 255.
>  .TP
> +.B clock_class_threshold
> +The maximum clock class value from master, acceptible to sub-ordinate
> +clock beyond which it moves out of lock state.
> +The default value is 248.
> +.TP
>  
>  .B domainNumber
>  The domain attribute of the local clock.
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/1] clock: Introduce step_window to free run x seconds after a clock step.

2021-02-01 Thread Jacob Keller



On 2/1/2021 2:55 PM, vincent.cheng...@renesas.com wrote:
> From: Vincent Cheng 
> 
> When clock stepping is unable to happen instantaneously the subsequent
> timestamps after a clock step does not reflect the step result and
> undesired clock freq and step adjustments will occur.
> 
> When using ts2phc to synchronize timestamping clock using external
> 1 PPS, it could take up to 1 second for the timestamps to reflect the
> clock step.
> 
> step_window, when set, indicates the time in seconds after a clock
> step in which the clock servo will not do any frequency or step
> adjustments.


This seems like it could be useful in a number of circumstances!

> 
> Signed-off-by: Vincent Cheng 
> ---
>  clock.c  | 40 
>  config.c |  1 +
>  ptp4l.8  |  8 
>  3 files changed, 49 insertions(+)
> 
> diff --git a/clock.c b/clock.c
> index a34737a..c03d548 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -20,6 +20,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -132,6 +133,8 @@ struct clock {
>   struct interface *udsif;
>   LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
>   struct monitor *slave_event_monitor;
> + int step_window;
> + timer_t step_timer_id;
>  };
>  
>  struct clock the_clock;
> @@ -141,6 +144,13 @@ static int clock_resize_pollfd(struct clock *c, int 
> new_nports);
>  static void clock_remove_port(struct clock *c, struct port *p);
>  static void clock_stats_display(struct clock_stats *s);
>  
> +static void clock_clear_free_running(union sigval callback_data)
> +{
> + struct clock *c = (struct clock *)(callback_data.sival_ptr);
> +
> + c->free_running  = 0;
> +}
> +

I'm not sure if we really want to overload free_running, but I can see
how this makes some sense.

>  static void remove_subscriber(struct clock_subscriber *s)
>  {
>   LIST_REMOVE(s, list);
> @@ -286,6 +296,7 @@ void clock_destroy(struct clock *c)
>   if (c->sanity_check) {
>   clockcheck_destroy(c->sanity_check);
>   }
> + timer_delete(c->step_timer_id);
>   memset(c, 0, sizeof(*c));
>   msg_cleanup();
>   tc_cleanup();
> @@ -897,6 +908,7 @@ struct clock *clock_create(enum clock_type type, struct 
> config *config,
>   unsigned char oui[OUI_LEN];
>   struct interface *iface;
>   struct timespec ts;
> + struct sigevent se;
>   int sfl;
>  
>   clock_gettime(CLOCK_REALTIME, );
> @@ -1194,6 +1206,18 @@ struct clock *clock_create(enum clock_type type, 
> struct config *config,
>   return NULL;
>   }
>  
> + /* Set up timer expire notification mechanism */
> + se.sigev_notify = SIGEV_THREAD;
> + se.sigev_value.sival_ptr = (void *)c;
> + se.sigev_notify_function = clock_clear_free_running;
> + se.sigev_notify_attributes = NULL;
> +
> + if (timer_create(CLOCK_MONOTONIC, , >step_timer_id)) {
> + pr_err("failed to create step timer_id");
> + return NULL;
> + }
> + c->step_window = config_get_int(config, NULL, "step_window");
> +
>   /* Create the ports. */
>   STAILQ_FOREACH(iface, >interfaces, list) {
>   if (clock_add_port(c, phc_device, phc_index, timestamping, 
> iface)) {
> @@ -1696,6 +1720,21 @@ int clock_switch_phc(struct clock *c, int phc_index)
>   return 0;
>  }
>  
> +static void clock_step_window(struct clock *c)
> +{
> + struct itimerspec tmo = {
> + {0, 0}, {0, 0}
> + };
> +
> + if (!c->step_window)
> + return;
> +
> + c->free_running = 1;
> +
> + tmo.it_value.tv_sec = c->step_window;
> + timer_settime(c->step_timer_id, 0, , 0);
> +}
> +
>  static void clock_synchronize_locked(struct clock *c, double adj)
>  {
>   clockadj_set_freq(c->clkid, -adj);
> @@ -1748,6 +1787,7 @@ enum servo_state clock_synchronize(struct clock *c, 
> tmv_t ingress, tmv_t origin)
>   case SERVO_JUMP:
>   clockadj_set_freq(c->clkid, -adj);
>   clockadj_step(c->clkid, -tmv_to_nanoseconds(c->master_offset));
> + clock_step_window(c);
>   c->ingress_ts = tmv_zero();
>   if (c->sanity_check) {
>   clockcheck_set_freq(c->sanity_check, -adj);
> diff --git a/config.c b/config.c
> index 4095b33..2b74bc8 100644
> --- a/config.c
> +++ b/config.c
> @@ -303,6 +303,7 @@ struct config_item config_tab[] = {
>   GLOB_ITEM_INT("slaveOnly", 0, 0, 1), /*deprecated*/
>   GLOB_ITEM_INT("socket_priority", 0, 0, 15),
>   GLOB_ITEM_DBL("step_threshold", 0.0, 0.0, DBL_MAX),
> + GLOB_ITEM_INT("step_window", 0, 0, UINT8_MAX),
>   GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX),
>   PORT_ITEM_INT("syncReceiptTimeout", 0, 0, UINT8_MAX),
>   GLOB_ITEM_INT("tc_spanning_tree", 0, 0, 1),
> diff --git a/ptp4l.8 b/ptp4l.8
> index 260aae3..0923bf3 100644
> --- a/ptp4l.8
> +++ b/ptp4l.8
> @@ -699,6 +699,14 @@ one-second offset 

Re: [Linuxptp-devel] [PATCH 5/6] clock: Add read-only UDS port for monitoring.

2021-01-26 Thread Jacob Keller



On 1/26/2021 2:00 AM, Miroslav Lichvar wrote:
> 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_address2 option (default is
> /var/run/ptp4lro).
> 

should uds_address2 be "uds_ro_address"? or some other name that implies
the read only aspect?

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/6] port: Don't assume transport from port number.

2021-01-26 Thread Jacob Keller



On 1/26/2021 2:00 AM, Miroslav Lichvar wrote:
> In port_open(), don't assume that UDS ports always have to have a zero
> number. Check the transport directly to make make the code cleaner.
> 
> Signed-off-by: Miroslav Lichvar 

This seems more straight forward than assuming the clock number is zero.

Reviewed-by: Jacob Keller 

> ---
>  port.c | 12 +++-
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/port.c b/port.c
> index 0a93c06..6136153 100644
> --- a/port.c
> +++ b/port.c
> @@ -3108,23 +3108,25 @@ struct port *port_open(const char *phc_device,
>   p->versionNumber = PTP_VERSION;
>   p->slave_event_monitor = clock_slave_monitor(clock);
>  
> - if (number && unicast_client_initialize(p)) {
> + if (transport != TRANS_UDS && unicast_client_initialize(p)) {
>   goto err_transport;
>   }
>   if (unicast_client_enabled(p) &&
>   config_set_section_int(cfg, p->name, "hybrid_e2e", 1)) {
>   goto err_uc_client;
>   }
> - if (number && unicast_service_initialize(p)) {
> + if (transport != TRANS_UDS && unicast_service_initialize(p)) {
>   goto err_uc_client;
>   }
>   p->hybrid_e2e = config_get_int(cfg, p->name, "hybrid_e2e");
>  
> - if (number && type == CLOCK_TYPE_P2P && p->delayMechanism != DM_P2P) {
> + if (transport != TRANS_UDS &&
> + type == CLOCK_TYPE_P2P && p->delayMechanism != DM_P2P) {
>   pr_err("port %d: P2P TC needs P2P ports", number);
>   goto err_uc_service;
>   }
> - if (number && type == CLOCK_TYPE_E2E && p->delayMechanism != DM_E2E) {
> + if (transport != TRANS_UDS &&
> + type == CLOCK_TYPE_E2E && p->delayMechanism != DM_E2E) {
>   pr_err("port %d: E2E TC needs E2E ports", number);
>   goto err_uc_service;
>   }
> @@ -3158,7 +3160,7 @@ struct port *port_open(const char *phc_device,
>  
>   port_clear_fda(p, N_POLLFD);
>   p->fault_fd = -1;
> - if (number) {
> + if (transport != TRANS_UDS) {
>   p->fault_fd = timerfd_create(CLOCK_MONOTONIC, 0);
>   if (p->fault_fd < 0) {
>   pr_err("timerfd_create failed: %m");
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [RFC PATCH] clock: Add read-only UDS port for monitoring.

2021-01-21 Thread Jacob Keller



On 1/21/2021 12:31 AM, Miroslav Lichvar wrote:
> On Wed, Jan 20, 2021 at 10:13:25PM +, Keller, Jacob E wrote:
>> It makes sense to remove forwarding, but I am not sure I understand the 
>> justification for removing access to subscriptions.. if the subscription is 
>> for read only data, why doesn't it make sense to allow that over the read 
>> only socket?
> 
> The subscription itself requires some state. If we say the new socket
> is safe to be accessed by untrusted applications, we need to be really
> sure they cannot do anything bad, e.g. create a large number of
> subscriptions to crash ptp4l or break subscriptions on the "rw"
> socket. Such issues would become security issues.
> 
> There might be a way to provide subscriptions on the "ro" socket, but
> they need to be separate from the "rw" subscriptions and have some
> limiting implemented.
> 
> I'd like to start with a minimal feature set that we can be
> comfortable with and maybe add other features later if there is a
> demand for them.
> 

Right. This makes sense. We can obviously extend the RO sockets in the
future, but I think it makes sense to limit it. To me, it seems good to
have some condensed version of this explanation in the commit message or
somewhere, since it may not be obvious why it is limited to those on the
outside.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/4] Deprecate the slaveOnly option in favor of clientOnly.

2021-01-14 Thread Jacob Keller



On 1/14/2021 6:15 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 
> ---
>  clock.c  | 4 ++--
>  config.c | 5 -
>  port.c   | 2 +-
>  ptp4l.c  | 2 +-
>  timemaster.c | 2 +-
>  5 files changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/clock.c b/clock.c
> index 0156bc3..08c61eb 100644
> --- a/clock.c
> +++ b/clock.c
> @@ -955,12 +955,12 @@ struct clock *clock_create(enum clock_type type, struct 
> config *config,
>  
>   c->dds.domainNumber = config_get_int(config, NULL, "domainNumber");
>  
> - if (config_get_int(config, NULL, "slaveOnly")) {
> + if (config_get_int(config, NULL, "clientOnly")) {
>   c->dds.flags |= DDS_SLAVE_ONLY;
>   }
>   if (!config_get_int(config, NULL, "gmCapable") &&
>   c->dds.flags & DDS_SLAVE_ONLY) {
> - pr_err("Cannot mix 1588 slaveOnly with 802.1AS !gmCapable");
> + pr_err("Cannot mix 1588 clientOnly with 802.1AS !gmCapable");
>   return NULL;
>   }
>   if (!config_get_int(config, NULL, "gmCapable") ||
> diff --git a/config.c b/config.c
> index a09739d..4095b33 100644
> --- a/config.c
> +++ b/config.c
> @@ -227,6 +227,7 @@ struct config_item config_tab[] = {
>   PORT_ITEM_INT("boundary_clock_jbod", 0, 0, 1),
>   PORT_ITEM_ENU("BMCA", BMCA_PTP, bmca_enu),
>   GLOB_ITEM_INT("check_fup_sync", 0, 0, 1),
> + GLOB_ITEM_INT("clientOnly", 0, 0, 1),
>   GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX),
>   GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX),
>   GLOB_ITEM_STR("clockIdentity", "00..00"),
> @@ -299,7 +300,7 @@ struct config_item config_tab[] = {
>   GLOB_ITEM_INT("servo_num_offset_values", 10, 0, INT_MAX),
>   GLOB_ITEM_INT("servo_offset_threshold", 0, 0, INT_MAX),
>   GLOB_ITEM_STR("slave_event_monitor", ""),
> - GLOB_ITEM_INT("slaveOnly", 0, 0, 1),
> + GLOB_ITEM_INT("slaveOnly", 0, 0, 1), /*deprecated*/>
> GLOB_ITEM_INT("socket_priority", 0, 0, 15),
>   GLOB_ITEM_DBL("step_threshold", 0.0, 0.0, DBL_MAX),
>   GLOB_ITEM_INT("summary_interval", 0, INT_MIN, INT_MAX),
> @@ -707,6 +708,8 @@ static void check_deprecated_options(const char **option)
>   new_option = "first_step_threshold";
>   } else if (!strcmp(*option, "pi_max_frequency")) {
>   new_option = "max_frequency";
> + } else if (!strcmp(*option, "slaveOnly")) {
> + new_option = "clientOnly";

Ahh. here is where the options get converted to support switching. Ok!

>   }
>  
>   if (new_option) {
> diff --git a/port.c b/port.c
> index 6c52004..0a93c06 100644
> --- a/port.c
> +++ b/port.c
> @@ -3048,7 +3048,7 @@ struct port *port_open(const char *phc_device,
>   } else if (clock_slave_only(clock)) {
>   p->state_machine = designated_slave_fsm;
>   } else {
> - pr_err("Please enable at least one of masterOnly or 
> slaveOnly when BMCA == noop.\n");
> + pr_err("Please enable at least one of masterOnly or 
> clientOnly when BMCA == noop.\n");
>   goto err_port;
>   }
>   } else {
> diff --git a/ptp4l.c b/ptp4l.c
> index ccbaa02..c61175b 100644
> --- a/ptp4l.c
> +++ b/ptp4l.c
> @@ -146,7 +146,7 @@ int main(int argc, char *argv[])
>   req_phc = optarg;
>   break;
>   case 's':
> - if (config_set_int(cfg, "slaveOnly", 1)) {
> + if (config_set_int(cfg, "clientOnly", 1)) {
>   goto out;
>   }
>   break;
> diff --git a/timemaster.c b/timemaster.c
> index 00db59f..fb27d72 100644
> --- a/timemaster.c
> +++ b/timemaster.c
> @@ -829,7 +829,7 @@ static int add_ptp_source(struct ptp_domain *source,
>   extend_config_string(_file->content,
>source->ptp4l_settings);
>   string_appendf(_file->content,
> -"slaveOnly 1\n"
> +"clientOnly 1\n"
>  "domainNumber %d\n"
>  "uds_address %s\n"
>  "message_tag %s\n",
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 1/4] Check for deprecated "long" options on the command line.

2021-01-14 Thread Jacob Keller



On 1/14/2021 6:15 AM, Richard Cochran wrote:
> The slaveOnly and masterOnly options will be deprecated in favor of
> clientOnly and serverOnly, respectively.  However, existing user scripts
> may very well make use of these options.  Apply the deprecated option
> check to the long command line options in order to avoid breaking existing
> deployments in the near future.
> 
> Signed-off-by: Richard Cochran 
> ---
>  config.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/config.c b/config.c
> index d237de9..a09739d 100644
> --- a/config.c
> +++ b/config.c
> @@ -1036,6 +1036,8 @@ int config_parse_option(struct config *cfg, const char 
> *opt, const char *val)
>  {
>   enum parser_result result;
>  
> + check_deprecated_options();
> +

Was this function introduced in a previous change? I don't recall it...

>   result = parse_item(cfg, 1, NULL, opt, val);
>  
>   switch (result) {
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 0/8] Convert to inclusive terminology, Part I

2021-01-11 Thread Jacob Keller



On 1/11/2021 9:05 AM, Richard Cochran wrote:
> On Mon, Jan 11, 2021 at 10:07:41AM +0100, Miroslav Lichvar wrote:
>> What will happen with the "grandmaster" term? Does it stay, or should
> 
> No decision yet on that one.
> 
>> it be replaced with something like "Primary time server"?
> 
> That sound reasonable to me.
>  
>> My only concern is the risk that the next standard will use a
>> different terminology and linuxptp users will have have to go through
>> the transition twice.
> 

I think I agree with Richard that much of the things we're renaming
don't strictly have to match. Plus, if we are able to influence the
standards towards this terminology we can avoid the potential.

> We can choose the terminology we like without causing confusion.  In
> fact, thanks to your insight of differentiating server/client and
> source/sink, this project will have clear and helpful documentation!
> 
> The *only* things we'll have to adapt to the new standard (if and when
> it ever appears) are the log messages that include port states.  Those
> will optionally follow the new terminology.  For now, I'm keeping
> almost all log messages unchanged, because some users are surely have
> scripts that scrape through the logs.
> 

Right. We can worry about changing those once standards have caught up.
I also think it's important to use the correct terms for various states
and other standard-specific names when possible (much like how you keep
some of the standard names the same even if they do not follow coding
guidelines such as camel casing or not)

> Thanks,
> Richard


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [RFC Patch 2/2] port: Fix link down/up to continue using phc_index set from command line -p option.

2021-01-07 Thread Jacob Keller



On 1/6/2021 11:39 AM, vincent.cheng...@renesas.com wrote:
> From: Vincent Cheng 
> 
> In the scenario where a port link goes down and up, current code checks
> the port's phc_index against the interface's phc_index and if they are
> different will set the port phc_index to the interface phc_index.
> 
> If the phc_index was initially set by the command line -p option, then we
> end up using the wrong phc_index.
> 
> Fix is to skip updating the port phc_index with the interface phc_index
> when port link is back up if it was initialy set from the command line.
> 
> Signed-off-by: Vincent Cheng 
> ---
>  port.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/port.c b/port.c
> index db3e9ac..bdc73e4 100644
> --- a/port.c
> +++ b/port.c
> @@ -2568,7 +2568,8 @@ void port_link_status(void *ctx, int linkup, int 
> ts_index)
>  "timestamping mode, set link status down 
> by force.",
>  interface_label(p->iface));
>   p->link_status = LINK_DOWN | LINK_STATE_CHANGED;
> - } else if (p->phc_index != 
> interface_phc_index(p->iface)) {
> + } else if ((p->phc_index != 
> interface_phc_index(p->iface)) &&
> +(!p->phc_from_cmdline)) {
>   p->phc_index = interface_phc_index(p->iface);
>  

Makes sense. But maybe we would want to do a warning about when the PHC
index on the networking device no longer matches the command line? (like
we do during the initial setup?)

>   if (clock_switch_phc(p->clock, p->phc_index)) {
> @@ -3064,6 +3065,7 @@ struct port *port_open(const char *phc_device,
>  "not the attached ptp%d", number, phc_device,
>  interface_phc_index(interface));
>   p->phc_index = phc_index;
> + p->phc_from_cmdline = 1;
>   } else {
>   pr_err("port %d: PHC device mismatch", number);
>   pr_err("port %d: /dev/ptp%d requested, ptp%d attached",
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [RFC Patch 1/2] port: Add phc_from_cmdline to indicate the phc index was from the command line.

2021-01-07 Thread Jacob Keller



On 1/6/2021 11:39 AM, vincent.cheng...@renesas.com wrote:
> From: Vincent Cheng 
> 
> Signed-off-by: Vincent Cheng 
> ---
>  port_private.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/port_private.h b/port_private.h
> index fcabaa6..6e40e15 100644
> --- a/port_private.h
> +++ b/port_private.h
> @@ -69,6 +69,7 @@ struct port {
>   struct fdarray fda;
>   int fault_fd;
>   int phc_index;
> + int phc_from_cmdline;
>  

This doesn't need to be a separate patch. You can just squash these
together, since there is no user added in this patch.

>   void (*dispatch)(struct port *p, enum fsm_event event, int mdiff);
>   enum fsm_event (*event)(struct port *p, int fd_index);
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 8/8] ts2phc: Convert usage message to time source/sink terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  ts2phc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/ts2phc.c b/ts2phc.c
> index 2342858..bc41041 100644
> --- a/ts2phc.c
> +++ b/ts2phc.c
> @@ -35,7 +35,7 @@ static void usage(char *progname)
>   fprintf(stderr,
>   "\n"
>   "usage: %s [options]\n\n"
> - " -c [dev|name]  phc slave clock (like /dev/ptp0 or eth0)\n"
> + " -c [dev|name]  PHC time sink (like /dev/ptp0 or eth0)\n"


You might have used "PHC device" here too, but since this is supposed to
be the side that is synchronized, I think this makes sense too.

>   "(may be specified multiple times)\n"
>   " -f [file]  read configuration from 'file'\n"
>   " -h prints this message and exits\n"
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 7/8] ptp4l: Convert usage messages to client/server terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  ptp4l.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/ptp4l.c b/ptp4l.c
> index 84661c5..ccbaa02 100644
> --- a/ptp4l.c
> +++ b/ptp4l.c
> @@ -58,7 +58,7 @@ static void usage(char *progname)
>   "   (may be specified multiple times)\n"
>   " -p [dev]  Clock device to use, default auto\n"
>   "   (ignored for SOFTWARE/LEGACY HW time stamping)\n"
> - " -sslave only mode (overrides configuration file)\n"
> + " -sclient only synchronization mode (overrides 
> configuration file)\n"
>   " -l [num]  set the logging level to 'num'\n"
>   " -mprint messages to stdout\n"
>   " -qdo not print messages to the syslog\n"
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 6/8] phc2sys: Convert usage messages to time source/sink terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index aafff6c..70155f9 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -1024,10 +1024,10 @@ static void usage(char *progname)
>   " -r synchronize system (realtime) clock\n"
>   "repeat -r to consider it also as a time 
> source\n"
>   " manual configuration:\n"
> - " -c [dev|name]  slave clock (CLOCK_REALTIME)\n"
> - " -d [dev]   master PPS device\n"
> - " -s [dev|name]  master clock\n"
> - " -O [offset]slave-master time offset (0)\n"
> + " -c [dev|name]  time sink device (CLOCK_REALTIME)\n"
> + " -d [dev]   time source PPS device\n"
> + " -s [dev|name]  time source device\n"
> + " -O [offset]sink-source time offset in seconds (0)\n"
>   " -w wait for ptp4l\n"
>   " common options:\n"
>   " -f [file]  configuration file\n"
> @@ -1036,8 +1036,8 @@ static void usage(char *progname)
>   " -I [ki]integration constant (0.3)\n"
>   " -S [step]  step threshold (disabled)\n"
>   " -F [step]  step threshold only on start (0.2)\n"
> - " -R [rate]  slave clock update rate in HZ (1.0)\n"
> - " -N [num]   number of master clock readings per update 
> (5)\n"
> + " -R [rate]  update rate for the time sink devices in HZ 
> (1.0)\n"
> + " -N [num]   number of source clock readings per update 
> (5)\n"
>   " -L [limit] sanity frequency limit in ppb (2)\n"
>   " -M [num]   NTP SHM segment number (0)\n"
>   " -u [num]   number of clock updates in summary stats (0)\n"
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 5/8] ts2phc: Convert man page to source/sink terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  ts2phc.8 | 20 ++--
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/ts2phc.8 b/ts2phc.8
> index 77f8940..0bd523d 100644
> --- a/ts2phc.8
> +++ b/ts2phc.8
> @@ -1,4 +1,4 @@
> -.TH TS2PHC 8 "December 2019" "linuxptp"
> +.TH TS2PHC 8 "January 2021" "linuxptp"
>  .SH NAME
>  ts2phc - Synchronizes one or more PTP Hardware Clocks using external time 
> stamps.
>  
> @@ -27,7 +27,7 @@ A single source may be used to distribute time to one or 
> more PHC devices.
>  .SH OPTIONS
>  .TP
>  .BI \-c " device|name"
> -Specifies a PHC slave clock to be synchronized.
> +Specifies a PHC to be synchronized.

Makes sense, no reason to keep "clock" since PHC as an acronym already
includes clock.

>  The clock may be identified by its character device (like /dev/ptp0)
>  or its associated network interface (like eth0).
>  This option may be given multiple times.
> @@ -52,7 +52,7 @@ Prevents sending log messages to the system logger.
>  .BI \-s " device|name"
>  Specifies the source of the PPS signal.
>  Use the key word "generic" for an external 1-PPS without ToD information.
> -When using a master PHC, the clock may be identified by its character
> +When using a PHC as the time source, the clock may be identified by its 
> character
>  device (like /dev/ptp0) or its associated network interface (like
>  eth0).
>  Use the key word "nmea" for an external 1-PPS from a GPS providing ToD
> @@ -88,14 +88,14 @@ There are two different section types.
>  .B 1.
>  The global section (indicated as
>  .BR [global] )
> -sets the program options and default slave clock options. Other
> +sets the program options and the default time sink options. Other
>  sections are clock specific sections, and they override the default
>  options.
>  .TP
>  .B 2.
> -Slave clock sections give the name of the configured slave (e.g.
> +Time sink sections give the name of the configured PHC (e.g.
>  .BR [eth0] ).
> -Slave clocks specified in the configuration file need not be specified
> +Time sinks specified in the configuration file need not be specified
>  with the
>  .B \-c
>  command line option.
> @@ -111,10 +111,10 @@ step the clock on start.
>  The default is 0.2 (20 microseconds).
>  .TP
>  .B free_running
> -When set to 1, no the slave clock will be adjusted.
> +When set to 1, no PHC will be adjusted.
>  This option can be useful in test scenarios, for example to determine
>  how well synchronized a group of local clocks are to each other.
> -The default is 0 (adjust the slave clocks).
> +The default is 0 (adjust the clocks).
>  .TP
>  .B leapfile
>  The path to the current leap seconds definition file.
> @@ -173,7 +173,7 @@ Print messages to the system log if enabled.  The default 
> is 1 (enabled).
>  .B verbose
>  Print messages to the standard output if enabled.  The default is 0 
> (disabled).
>  
> -.SH SLAVE CLOCK OPTIONS
> +.SH TIME SINK OPTIONS
>  
>  .TP
>  .B ts2phc.channel
> @@ -199,7 +199,7 @@ The default is "rising".
>  .B ts2phc.master
>  Setting this option to 1 configures the given PHC device as the source
>  of the PPS signal.
> -The default is 0 for the slave role.
> +The default is 0 for the time sink role.
>  .TP
>  .B ts2phc.pin_index
>  The pin index to be used.
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 4/8] ptp4l: Convert man page to client/server terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  ptp4l.8 | 80 +
>  1 file changed, 41 insertions(+), 39 deletions(-)
> 
> diff --git a/ptp4l.8 b/ptp4l.8
> index 473215b..42c9bde 100644
> --- a/ptp4l.8
> +++ b/ptp4l.8
> @@ -1,4 +1,4 @@
> -.TH PTP4l 8 "April 2018" "linuxptp"
> +.TH PTP4l 8 "January 2021" "linuxptp"
>  .SH NAME
>  ptp4l - PTP Boundary/Ordinary/Transparent Clock
>  
> @@ -145,13 +145,13 @@ See UNICAST DISCOVERY OPTIONS, below.
>  .TP
>  .B delayAsymmetry
>  The time difference in nanoseconds of the transmit and receive
> -paths. This value should be positive when the master-to-slave
> -propagation time is longer and negative when the slave-to-master time
> +paths. This value should be positive when the server-to-client
> +propagation time is longer and negative when the client-to-server time
>  is longer. The default is 0 nanoseconds.
>  .TP
>  .B logAnnounceInterval
>  The mean time interval between Announce messages. A shorter interval makes
> -ptp4l react faster to the changes in the master-slave hierarchy. The interval
> +ptp4l react faster to the changes in the client/server hierarchy. The 
> interval
>  should be the same in the whole domain. It's specified as a power of two in
>  seconds.
>  The default is 1 (2 seconds).
> @@ -164,7 +164,7 @@ The default is 0 (1 second).
>  .B operLogSyncInterval
>  The Sync message interval to be requested once the clock enters the
>  SERVO_LOCKED_STABLE state.  If the 'msg_interval_request' option is
> -set, then the local slave port will request the remote master to
> +set, then the local client port will request the remote server to
>  switch to the given message rate via a signaling message containing a
>  Message interval request TLV.  This option is specified as a power of
>  two in seconds, and default value is 0 (1 second).
> @@ -183,14 +183,14 @@ The default is 0 (1 second).
>  .B operLogPdelayReqInterval
>  The Pdelay Request messages interval to be used once the clock enters
>  the SERVO_LOCKED_STABLE state.  If the 'msg_interval_request' option
> -is set, then the local slave port will adopt this rate when the local
> +is set, then the local client port will adopt this rate when the local
>  clock enters the "locked stable" state.  This option is specified as a
>  power of two in seconds, and the default value is 0 (1 second).
>  .TP
>  .B inhibit_delay_req
>  Don't send any delay requests. This will need the asCapable config option to 
> be
> -set to 'true'. This is useful when running as a designated master who does 
> not
> -need to calculate offset from slave. The default is 0 (disabled).
> +set to 'true'. This is useful when running as a designated server who does 
> not
> +need to calculate offset from client. The default is 0 (disabled).
>  .TP
>  .B announceReceiptTimeout
>  The number of missed Announce messages before the last Announce messages
> @@ -244,9 +244,9 @@ The default is E2E.
>  .TP
>  .B hybrid_e2e
>  Enables the "hybrid" delay mechanism from the draft Enterprise
> -Profile. When enabled, ports in the slave state send their delay
> -request messages to the unicast address taken from the master's
> -announce message. Ports in the master state will reply to unicast
> +Profile. When enabled, ports in the client state send their delay
> +request messages to the unicast address taken from the server's
> +announce message. Ports in the server state will reply to unicast
>  delay requests using unicast delay responses. This option has no
>  effect if the delay_mechanism is set to P2P.
>  The default is 0 (disabled).
> @@ -302,7 +302,7 @@ greater than this value the port is marked as not 802.1AS 
> capable.
>  .TP
>  .B masterOnly
>  Setting this option to one (1) prevents the port from entering the
> -SLAVE state. In addition, the local clock will ignore Announce
> +client state. In addition, the local clock will ignore Announce
>  messages received on this port. This option's intended use is to
>  support the Telecom Profiles according to ITU-T G.8265.1, G.8275.1,
>  and G.8275.2. The default value is zero or false.
> @@ -381,7 +381,7 @@ hardware time stamping.
>  The default is 1 (enabled).
>  .TP
>  .B slaveOnly
> -The local clock is a slave-only clock if enabled. The default is 0 
> (disabled).
> +The local clock is a client-only clock if enabled. The default is 0 
> (disabled).
>  .TP
>  .B socket_priority
>  Configure the SO_PRIORITY of sockets. This is to support cases where a user
> @@ -396,13 +396,13 @@ This is only for use with 802.1AS clocks

Re: [Linuxptp-devel] [PATCH v2 3/8] phc2sys: Convert man page to client/server terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.8 | 18 +-
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/phc2sys.8 b/phc2sys.8
> index 7773fd0..99fc937 100644
> --- a/phc2sys.8
> +++ b/phc2sys.8
> @@ -414,22 +414,22 @@ or
>  .B \-w
>  is in effect or from command line when
>  .B \-O
> -is supplied.  Failure to maintain the correct offset can result in local 
> system
> -clock being off some seconds to domain master system clock when in slave 
> mode,
> -or incorect PTP time announced to the network in case the host is the domain
> -master.
> +is supplied.  Failure to maintain the correct offset can result in the
> +local system clock being offset some whole number of seconds from the
> +domain server's clock when in client mode, or incorect PTP time
> +announced to the network in case the host is the domain server.
>  
>  .SH EXAMPLES
>  
>  Synchronize time automatically according to the current
>  .B ptp4l
> -state, synchronize the system clock to the remote master.
> +state, synchronizing the system clock to the remote server.
>  
>  .RS
>  \f(CWphc2sys \-a \-r\fP
>  .RE
>  
> -Same as above, but when the host becomes the domain master, synchronize time
> +Same as above, but when the host becomes the domain server, synchronize time
>  in the domain to its system clock.
>  
>  .RS
> @@ -442,13 +442,13 @@ Same as above, in an IEEE 802.1AS domain.
>  \f(CWphc2sys \-a \-rr --transportSpecific=1\fP
>  .RE
>  
> -The host is a domain master, PTP clock is synchronized to system clock and 
> the
> +The host is a domain server, PTP clock is synchronized to system clock and 
> the
>  time offset is obtained from
>  .BR ptp4l .
>  .B Phc2sys
>  waits for
>  .B ptp4l
> -to get at least one port in master or slave mode before starting the
> +to get at least one port in server or client mode before starting the
>  synchronization.
>  
>  .RS
> @@ -464,7 +464,7 @@ does not wait for
>  \f(CWphc2sys \-c /dev/ptp0 \-s CLOCK_REALTIME \-O 35\fP
>  .RE
>  
> -The host is in slave mode, system clock is synchronized from PTP clock,
> +The host is in client mode, system clock is synchronized from PTP clock,
>  .B phc2sys
>  waits for
>  .B ptp4l
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 2/8] phc2sys: Convert man page to source/sink terminology.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 
> ---

Makes sense. I like this direction for the terminology change.

Reviewed-by: Jacob Keller 

>  phc2sys.8 | 24 
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/phc2sys.8 b/phc2sys.8
> index 66007eb..7773fd0 100644
> --- a/phc2sys.8
> +++ b/phc2sys.8
> @@ -52,7 +52,7 @@ Manual configuration is also possible. When using manual 
> configuration, two
>  synchronization modes are supported, one uses a pulse per second (PPS)
>  signal provided by the source clock and the other mode reads time from the
>  source clock directly. Some clocks can be used in both modes, the mode which
> -will synchronize the slave clock with better accuracy depends on hardware
> +will synchronize the time sink with better accuracy depends on hardware
>  and driver implementation.
>  
>  .SH OPTIONS
> @@ -82,22 +82,22 @@ Read configuration from the specified file. No 
> configuration file is read by
>  default.
>  .TP
>  .BI \-d " pps-device"
> -Specify the PPS device of the master clock (e.g. /dev/pps0). With this option
> +Specify the PPS device of the source clock (e.g. /dev/pps0). With this option
>  the PPS synchronization mode is used instead of the direct mode.  The
>  matching PHC must be specified using the
>  .B \-s
>  command line option.
> -This option can be used only with the system clock as the slave clock. Not
> +This option can be used only with the system clock as the time sink. Not
>  compatible with the
>  .B \-a
>  option.
>  .TP
>  .BI \-s " device"
> -Specify the master clock by device (e.g. /dev/ptp0) or interface (e.g. eth0) 
> or
> +Specify the source clock by device (e.g. /dev/ptp0) or interface (e.g. eth0) 
> or
>  by name (e.g. CLOCK_REALTIME for the system clock). When this option is used
>  together with the
>  .B \-d
> -option, the master clock is used only to correct the offset by whole number 
> of
> +option, the source clock is used only to correct the offset by whole number 
> of
>  seconds, which cannot be fixed with PPS alone. Not compatible with the
>  .B \-a
>  option. This option does not support bonded interface (e.g. bond0, team0). If
> @@ -109,14 +109,14 @@ option can be used to track the active interface.
>  .BI \-i " interface"
>  Performs the exact same function as
>  .B \-s
> -for compatibility reasons. Previously enabled specifying master clock by 
> network
> +for compatibility reasons. Previously enabled specifying source clock by 
> network
>  interface. However, this can now be done using
>  .B \-s
>  and this option is no longer necessary. As such it has been deprecated, and
>  should no longer be used.
>  .TP
>  .BI \-c " device"
> -Specify the slave clock by device (e.g. /dev/ptp1) or interface (e.g. eth1) 
> or
> +Specify the time sink by device (e.g. /dev/ptp1) or interface (e.g. eth1) or
>  by  name. The default is CLOCK_REALTIME (the system clock). Not compatible
>  with the
>  .B \-a
> @@ -151,17 +151,17 @@ seconds. The value of 0.0 disables stepping on start. 
> The default is 0.2
>  (20 microseconds).
>  .TP
>  .BI \-R " update-rate"
> -Specify the slave clock update rate when running in the direct 
> synchronization
> +Specify the time sink update rate when running in the direct synchronization
>  mode. The default is 1 per second.
>  .TP
>  .BI \-N " phc-num"
> -Specify the number of master clock readings per one slave clock update. Only
> -the fastest reading is used to update the slave clock, this is useful to
> +Specify the number of source clock readings used for each time sink update.
> +Only the fastest reading is used to update the clock.  This is useful to
>  minimize the error caused by random delays in scheduling and bus utilization.
>  The default is 5.
>  .TP
>  .BI \-O " offset"
> -Specify the offset between the slave and master times in seconds. Not
> +Specify the offset between the sink and source times in seconds. Not
>  compatible with the
>  .B \-a
>  option.  See
> @@ -192,7 +192,7 @@ The default is 0 (disabled).
>  .B \-w
>  Wait until ptp4l is in a synchronized state. If the
>  .B \-O
> -option is not used, also keep the offset between the slave and master
> +option is not used, also keep the offset between the sink and source
>  times updated according to the currentUtcOffset value obtained from ptp4l and
>  the direction of the clock synchronization. Not compatible with the
>  .B \-a
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH v2 1/8] phc2sys: Update man page to reflect the new restriction on the PPS mode.

2021-01-07 Thread Jacob Keller



On 1/5/2021 6:42 AM, Richard Cochran wrote:
> Signed-off-by: Richard Cochran 
> ---
>  phc2sys.8 | 16 
>  1 file changed, 4 insertions(+), 12 deletions(-)
> 
> diff --git a/phc2sys.8 b/phc2sys.8
> index b3a3de3..66007eb 100644
> --- a/phc2sys.8
> +++ b/phc2sys.8
> @@ -1,4 +1,4 @@
> -.TH PHC2SYS 8 "April 2018" "linuxptp"
> +.TH PHC2SYS 8 "January 2021" "linuxptp"
>  .SH NAME
>  phc2sys \- synchronize two or more clocks
>  
> @@ -83,18 +83,10 @@ default.
>  .TP
>  .BI \-d " pps-device"
>  Specify the PPS device of the master clock (e.g. /dev/pps0). With this option
> -the PPS synchronization mode is used instead of the direct mode. As the PPS
> -signal does not specify time and only marks start of a second, the slave 
> clock
> -should be already close to the correct time before
> -.B phc2sys
> -is started or the
> -.B \-s
> -option should be used too. With the
> +the PPS synchronization mode is used instead of the direct mode.  The
> +matching PHC must be specified using the
>  .B \-s
Makes sense. We don't need a further explanation about the clocks being
close together because -s is always required now. ok.

> -option the PPS signal of the master clock is enabled automatically, otherwise
> -it has to be enabled before
> -.B phc2sys
> -is started (e.g. by running \f(CWecho 1 > /sys/class/ptp/ptp0/pps_enable\fP).
> +command line option.
>  This option can be used only with the system clock as the slave clock. Not
>  compatible with the
>  .B \-a
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 6/6] phc2sys: Replace magical test with a proper test.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> When using a PPS time source with the -w flag, the program closes the PMC
> agent's connection once the ptp4l service has appeared and the UTC offset
> has been optionally queried.
> 
> In order to tell whether PPS is the time source, the code tests for
> 
> src->clkid == CLOCK_INVALID
> 
> which is completely opaque and non-obvious.  Presently only the case where
> src_name is NULL (and pps_fd is valid) will trigger this test, but that is
> only incidental.
> 
> Clarify the intention of the code by using a proper test.
> 
> Signed-off-by: Richard Cochran 

Significant improvement here, it is a bit more clear what's going on
here now.

Reviewed-by: Jacob Keller 

Thanks,
Jake

> ---
>  phc2sys.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index e65bdf5..15ccb80 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -1328,7 +1328,7 @@ int main(int argc, char *argv[])
>  
>   if (priv.forced_sync_offset ||
>   (src->clkid != CLOCK_REALTIME && dst->clkid != 
> CLOCK_REALTIME) ||
> - src->clkid == CLOCK_INVALID) {
> + hardpps_configured(pps_fd)) {
>   pmc_agent_disable(priv.agent);
>   }
>   }
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 5/6] phc2sys: Expand the validation of the PPS mode.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> When using a PPS time source, the PHC character device or network interface
> specified using the -s command line flag will be ignored.  Detect this
> mis-configuration and throw a usage error.
> 
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index 03347f0..e65bdf5 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -1253,6 +1253,10 @@ int main(int argc, char *argv[])
>   "cannot use a pps device unless destination is 
> CLOCK_REALTIME\n");
>   goto bad_usage;
>   }
> + if (hardpps_configured(pps_fd) && src_name) {
> + fprintf(stderr, "please specify -s or -d, but not both\n");
> + goto bad_usage;
> + }

Should this have an associated manual page update, or is the manual page
already correct?

>  
>   print_set_progname(progname);
>   print_set_tag(config_get_string(cfg, NULL, "message_tag"));
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 4/6] phc2sys: Validate the PPS mode right away.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> When using a PPS time source, the code only checks the destination
> clock after performing much static setup.  There is no need to delay
> the validation, so move this to the other sanity checks.
> 
> Signed-off-by: Richard Cochran 

Makes sense.

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 17 ++---
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index f28e9be..03347f0 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -1245,6 +1245,15 @@ int main(int argc, char *argv[])
>   goto bad_usage;
>   }
>  
> + if (!dst_name) {
> + dst_name = "CLOCK_REALTIME";
> + }
> + if (hardpps_configured(pps_fd) && strcmp(dst_name, "CLOCK_REALTIME")) {
> + fprintf(stderr,
> + "cannot use a pps device unless destination is 
> CLOCK_REALTIME\n");
> + goto bad_usage;

Now we do a strcmp instead of checking the raw clkid, but that is only
because we haven't yet opened the clock. Makes sense.

> + }
> +
>   print_set_progname(progname);
>   print_set_tag(config_get_string(cfg, NULL, "message_tag"));
>   print_set_verbose(config_get_int(cfg, NULL, "verbose"));
> @@ -1280,7 +1289,7 @@ int main(int argc, char *argv[])
>   src->state = PS_SLAVE;
>   priv.master = src;
>  
> - dst = clock_add(, dst_name ? dst_name : "CLOCK_REALTIME");
> + dst = clock_add(, dst_name);
>   if (!dst) {
>   fprintf(stderr, "valid destination clock must be selected.\n");
>   goto bad_usage;
> @@ -1288,12 +1297,6 @@ int main(int argc, char *argv[])
>   dst->state = PS_MASTER;
>   LIST_INSERT_HEAD(_clocks, dst, dst_list);
>  
> - if (hardpps_configured(pps_fd) && dst->clkid != CLOCK_REALTIME) {
> - fprintf(stderr,
> - "cannot use a pps device unless destination is 
> CLOCK_REALTIME\n");
> - goto bad_usage;
> - }
> -
>   r = -1;
>  
>   if (wait_sync) {
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 3/6] phc2sys: Replace hard coded tests with a readable helper function.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> The main program determines whether a PPS device is the time source
> with an open-coded test for a valid file descriptor.  Replace it with
> a helper routine whose name properly signifies the meaning of the
> test.
> 
> Signed-off-by: Richard Cochran 

Makes sense.

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 14 ++
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index e17909f..f28e9be 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -979,6 +979,11 @@ static int clock_handle_leap(struct phc2sys_private 
> *priv, struct clock *clock,
>   return 0;
>  }
>  
> +static bool hardpps_configured(int fd)
> +{
> + return fd >= 0;
> +}
> +
>  static void usage(char *progname)
>  {
>   fprintf(stderr,
> @@ -1222,12 +1227,13 @@ int main(int argc, char *argv[])
>   return c;
>   }
>  
> - if (autocfg && (src_name || dst_name || pps_fd >= 0 || wait_sync || 
> priv.forced_sync_offset)) {
> + if (autocfg && (src_name || dst_name || hardpps_configured(pps_fd) ||
> + 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 && !hardpps_configured(pps_fd) && !src_name) {
>   fprintf(stderr,
>   "autoconfiguration or valid source clock must be 
> selected.\n");
>   goto bad_usage;
> @@ -1282,7 +1288,7 @@ int main(int argc, char *argv[])
>   dst->state = PS_MASTER;
>   LIST_INSERT_HEAD(_clocks, dst, dst_list);
>  
> - if (pps_fd >= 0 && dst->clkid != CLOCK_REALTIME) {
> + if (hardpps_configured(pps_fd) && dst->clkid != CLOCK_REALTIME) {
>   fprintf(stderr,
>   "cannot use a pps device unless destination is 
> CLOCK_REALTIME\n");
>   goto bad_usage;
> @@ -1320,7 +1326,7 @@ int main(int argc, char *argv[])
>   }
>   }
>  
> - if (pps_fd >= 0) {
> + if (hardpps_configured(pps_fd)) {
>   /* only one destination clock allowed with PPS until we
>* implement a mean to specify PTP port to PPS mapping */
>   dst->servo = servo_add(, dst);
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/6] phc2sys: Rename PMC agent pointer from node to agent.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> Node is not a very descriptive name.  Rename it.
> 
> Signed-off-by: Richard Cochran 

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 48 
>  1 file changed, 24 insertions(+), 24 deletions(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index 13cf235..e17909f 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 *agent;
>   LIST_HEAD(port_head, port) ports;
>   LIST_HEAD(clock_head, clock) clocks;
>   LIST_HEAD(dst_clock_head, clock) dst_clocks;
> @@ -302,7 +302,7 @@ static void clock_reinit(struct phc2sys_private *priv, 
> struct clock *clock,
>   if (p->clock != clock) {
>   continue;
>   }
> - err = pmc_agent_query_port_properties(priv->node, 1000,
> + err = pmc_agent_query_port_properties(priv->agent, 1000,
> p->number, ,
> , iface);
>   if (!err) {
> @@ -644,7 +644,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. */
> - pmc_agent_set_sync_offset(priv->node, 0);
> + pmc_agent_set_sync_offset(priv->agent, 0);
>   } else {
>   enable_pps_output(priv->master->clkid);
>   }
> @@ -675,7 +675,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(priv->agent) < 0)
>   continue;
>   update_clock(priv, clock, pps_offset, pps_ts, -1);
>   }
> @@ -713,16 +713,16 @@ static int do_loop(struct phc2sys_private *priv, int 
> subscriptions)
>   while (is_running()) {
>   clock_nanosleep(CLOCK_MONOTONIC, 0, , NULL);
>  
> - if (pmc_agent_update(priv->node) < 0) {
> + if (pmc_agent_update(priv->agent) < 0) {
>   continue;
>   }
>  
>   if (subscriptions) {
> - run_pmc_events(priv->node);
> + run_pmc_events(priv->agent);
>   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)) {
> + if (pmc_agent_query_utc_offset(priv->agent, 
> 1000)) {
>   pr_err("failed to get UTC offset");
>   continue;
>   }
> @@ -853,7 +853,7 @@ static int auto_init_ports(struct phc2sys_private *priv, 
> int add_rt)
>   if (!is_running()) {
>   return -1;
>   }
> - err = pmc_agent_query_dds(priv->node, 1000);
> + err = pmc_agent_query_dds(priv->agent, 1000);
>   if (!err) {
>   break;
>   }
> @@ -864,20 +864,20 @@ static int auto_init_ports(struct phc2sys_private 
> *priv, int add_rt)
>   }
>   }
>  
> - number_ports = pmc_agent_get_number_ports(priv->node);
> + number_ports = pmc_agent_get_number_ports(priv->agent);
>   if (number_ports <= 0) {
>   pr_err("failed to get number of ports");
>   return -1;
>   }
>  
> - err = pmc_agent_subscribe(priv->node, 1000);
> + err = pmc_agent_subscribe(priv->agent, 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,
> + err = pmc_agent_query_port_properties(priv->agent, 1000, i,
> , ,
> iface);
>   if (err == -ENODEV) {
> @@ -915,7 +915,7 @@ static int auto_init_ports(struct phc2sys_private *priv, 
> int add_rt)
>   }
>  
>   /* get

Re: [Linuxptp-devel] [PATCH 1/6] phc2sys: Don't duplicate the command line arguments.

2020-11-30 Thread Jacob Keller



On 11/29/2020 7:50 PM, Richard Cochran wrote:
> The names of the source and destination clocks are generated by
> duplicating command line arguments, and then the newly allocated
> memory is immediately freed.  Remove the unnecessary malloc/free dance
> and use the arguments directly.
> 
> Signed-off-by: Richard Cochran 

Yep, makes sense.

Reviewed-by: Jacob Keller 

> ---
>  phc2sys.c | 12 
>  1 file changed, 4 insertions(+), 8 deletions(-)
> 
> diff --git a/phc2sys.c b/phc2sys.c
> index c300984..13cf235 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -1071,7 +1071,7 @@ int main(int argc, char *argv[])
>   rt++;
>   break;
>   case 'c':
> - dst_name = strdup(optarg);
> + dst_name = optarg;
>   break;
>   case 'd':
>   pps_fd = open(optarg, O_RDONLY);
> @@ -1089,7 +1089,7 @@ int main(int argc, char *argv[])
>   "'-i' has been deprecated. please use '-s' 
> instead.\n");
>  /* fallthrough */
>   case 's':
> - src_name = strdup(optarg);
> + src_name = optarg;
>   break;
>   case 'E':
>   if (!strcasecmp(optarg, "pi")) {
> @@ -1267,20 +1267,16 @@ int main(int argc, char *argv[])
>   }
>  
>   src = clock_add(, src_name);
> - free(src_name);
>   if (!src) {
> - fprintf(stderr,
> - "valid source clock must be selected.\n");
> + fprintf(stderr, "valid source clock must be selected.\n");
>   goto bad_usage;
>   }
>   src->state = PS_SLAVE;
>   priv.master = src;
>  
>   dst = clock_add(, dst_name ? dst_name : "CLOCK_REALTIME");
> - free(dst_name);
>   if (!dst) {
> - fprintf(stderr,
> - "valid destination clock must be selected.\n");
> + fprintf(stderr, "valid destination clock must be selected.\n");
>   goto bad_usage;
>   }
>   dst->state = PS_MASTER;
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 4/4] pmc_agent: Simplify the method that gets of the number of local ports.

2020-11-30 Thread Jacob Keller



On 11/28/2020 9:08 AM, Richard Cochran wrote:
> The number of ports is already available in the cached default data
> set.  Use it directly.
> 
> Signed-off-by: Richard Cochran 
> ---
>  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 5386cf4..16daa66 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -864,7 +864,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 4c5b18a..d3db975 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, );
> - 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;
> @@ -292,6 +276,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;
> +}
> +

Based on your previous patches suggestions, shouldn't this be
"pmc_agent_query_number_ports", considering that this is returning a
cached value?

>  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 2bb3101..abe62f5 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);
>  
>  /**
> @@ -56,6 +55,16 @@ void pmc_agent_destroy(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().
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 2/4] pmc_agent: Convert the method that queries the port properties.

2020-11-30 Thread Jacob Keller



On 11/28/2020 9:08 AM, Richard Cochran wrote:
> 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 
> ---
>  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 725a25c..610b8bb 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -292,24 +292,26 @@ 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 sk_ts_info ts_info;
>   char iface[IFNAMSIZ];
>   clockid_t clkid = CLOCK_INVALID;
>  
>   LIST_FOREACH(p, >ports, list) {
> - if (p->clock == clock) {
> - ret = run_pmc_port_properties(priv->node, 1000, 
> p->number,
> -   , ,
> -   iface);
> - if (ret > 0)
> - p->state = normalize_state(state);
> + if (p->clock != clock) {
> + continue;
> + }

We do a continue now to skip over the clock until we found it. Ok.. Bit odd.

Seems like it might be worth introducing some helper function that loops
over the port list and locates the clock.

> + err = pmc_agent_query_port_properties(priv->node, 1000,
> +   p->number, ,
> +   , iface);
> + if (!err) {
> + p->state = normalize_state(state);
>   }
> + break;
>   }
>  

To me, this entire block might have read better as something like:

LIST_FOREACH(p, >ports, list) {
if (p->clock == clock) {
break
}
}

/* exit if we failed to find a clock */

/* do the run_pmc_port_properties */


But that's a bit awkward because you do need to check that the loop
didn't hit the end without finding a clock. In the previous code that
was snuck in by having "ret" be -1 by initialization. This could be even
further reduced if we had a helper function that returned the first port
with the matching clock.

None of this is really the fault of this patch, and could easily be left
for a future cleanup/refactor. I believe the patch as written has the
same semantics as the original before the return code cleanup.

> - if (ret > 0 && timestamping != TS_SOFTWARE) {
> + if (!err && timestamping != TS_SOFTWARE) {
>   /* Check if device changed */
>   if (strcmp(clock->device, iface)) {
>   free(clock->device);
> @@ -841,12 +843,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())
> @@ -866,20 +868,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, ,
> -   , iface);
> - if (res == -1) {
> + err = pmc_agent_query_port_properties(priv->node, 1000, i,
> +   , ,
> +   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 5e066ac..f5ce59d 100644
> --- a/pmc_agent.c
> +++ 

Re: [Linuxptp-devel] [PATCH 1/4] pmc_agent: Convert the method that queries TAI-UTC offset into the canonical form.

2020-11-30 Thread Jacob Keller



On 11/28/2020 9:08 AM, Richard Cochran wrote:
> 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 

Reviewed-by: Jacob Keller 

I appreciate the function rename too, it seems a bit more clear. (Plus,
if this were a project with many patches in flight, renaming the
function helps prevent potential non-text merge conflicts where a new
user was added but didn't update with the new return semantics).

> ---
>  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 999d20e..725a25c 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;
>   }
> @@ -910,7 +910,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;
>   }
> @@ -1305,8 +1305,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 22af306..5e066ac 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, );
> - 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;
> @@ -376,6 +346,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, );
> + 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)
> +  

Re: [Linuxptp-devel] [PATCH 1/7] Introduce error codes for the run_pmc method.

2020-11-11 Thread Jacob Keller



On 11/11/2020 10:50 AM, Richard Cochran wrote:
> On Wed, Nov 11, 2020 at 10:35:20AM -0800, Jacob Keller wrote:
>> Thoughts on making this an enum instead so that it's even more clear
>> from the function signatures that this is not an integer return code?
>> The run_pmc function is static so it would only affect callers in this file.
> 
> I considered an enum, but that meant churn on all the callers due to
> the change in return type of run_pmc().
> 
> At the end, I want to have run_pmc return errno codes.
> 
> Thanks,
> Richard
> 

Makes sense. Having run_pmc just return error codes or zero makes more
sense in the long run, so the enumeration isn't really necessary. This
is especially true since the return values really are one success and 3
possible failures, where we pretty much just forward the error value out.

It might be different if many of the callers had to switch on the return
and do things differently based on which return value.


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH] Avoid setting clock frequency when free running.

2020-11-11 Thread Jacob Keller



On 11/9/2020 8:14 AM, Richard Cochran wrote:
> On Mon, Nov 09, 2020 at 10:12:58AM +0100, Miroslav Lichvar wrote:
>>
>> Makes sense to me, but maybe it's time to drop the workaround? Looking
>> at the git log, it was added in 2013. Are people still using linuxptp
>> on kernels older than that?
> 
> Yes, I think so.
> 
> When I was collaborating with Balint on his ts2phc not too long ago,
> someone from Intel was asking to please make sure it still works on
> Linux v3.0.
> 
> Thanks,
> Richard
> 

I know we get requests and reports from a few folks who end up sticking
to the same release for a long time.

If we were going to change where LinuxPTP is supported, I think we would
want to do so in some staged manner where we produce deprecation
warnings in one release indicating that support will be dropped for
older kernels, and only drop support in a later release after we've
given some time for folks to (hopefully) be made aware of this fact.

Of course, we should weigh the cost of maintaining the code vs the cost
of headaches when someone uses the program and it doesn't work quite
right. Special care should be taken when failure is non-obvious, and the
application doesn't fail immediately when it isn't working.

In this case, the issue is that our attempt to read the frequency may
not give us valid results. If it fails, then we'll mistakenly assume an
incorrect frequency. This will cause the programs calculations of
frequency drift to be incorrect, resulting in non-optimal adjustments
especially early on. Because this type of failure does not result in an
immediate and obvious failure, I think we ought to be more careful in
handling this work around.

Thanks,
Jake


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 4/7] pmc_agent: Simplify logic in update method.

2020-11-11 Thread Jacob Keller



On 11/10/2020 2:21 PM, Richard Cochran wrote:
> 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 


Makes sense.

Reviewed-by: Jacob Keller 

> ---
>  pmc_agent.c | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/pmc_agent.c b/pmc_agent.c
> index 24587b4..47562bc 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, )) {
>   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->subscription_active) {
>   renew_subscription(node, 0);
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


Re: [Linuxptp-devel] [PATCH 3/7] pmc_agent: Simplify the update method.

2020-11-11 Thread Jacob Keller



On 11/10/2020 2:21 PM, Richard Cochran wrote:
> 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 

Makes sense. I definitely like dropping the on/off parameter. It makes
the API between the callers easier to follow.

> ---
>  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 d758aca..436ccea 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -673,7 +673,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, , NULL);
> - if (update_pmc_node(priv->node, subscriptions) < 0)
> +
> + if (update_pmc_node(priv->node) < 0) {
>   continue;
> + }

Ok, so now the node/agent tracks the subscriptions automatically. So
someone else needs to call renew_subscription first.

Patch context alone isn't enough to follow where that happens. We pass
subscriptions to do_loop. Is this still used? No longer necessary? hmm.

>  
>   if (subscriptions) {
>   run_pmc_events(priv->node);
> diff --git a/pmc_agent.c b/pmc_agent.c
> index 714c5c5..24587b4 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;
> + int subscription_active;
>   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, );
> + 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->subscription_active) {
> + 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, );
> - if (is_run_pmc_error(res)) {
> - return run_pmc_err2errno(res);
> - }
> - msg_put(msg);
> - return 0;
> + node->subscription_active = 1;
> + 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 551c4a5..e4d3c3c 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);
> 


___
Linuxptp-devel mailing list

Re: [Linuxptp-devel] [PATCH 2/7] pmc_agent: Convert the subscribe method into the canonical form.

2020-11-11 Thread Jacob Keller



On 11/10/2020 2:21 PM, Richard Cochran wrote:
> This patch renames the function to have the module prefix and corrects the
> return code semantics.
> 
> Signed-off-by: Richard Cochran 

This looks good to me.

Reviewed-by: Jacob Keller 

> ---
>  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 7b488ba..d758aca 100644
> --- a/phc2sys.c
> +++ b/phc2sys.c
> @@ -864,8 +864,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 d28f3b6..714c5c5 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 
>  #include 
>  #include 
>  #include 
> @@ -98,6 +99,26 @@ static int get_mgt_err_id(struct ptp_message *msg)
>  #define RUN_PMC_BADMSG   -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_BADMSG:
> + return -EBADMSG;
> + 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, );
> - 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, );
> + 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..551c4a5 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 timeout in millis

Re: [Linuxptp-devel] [PATCH 1/7] Introduce error codes for the run_pmc method.

2020-11-11 Thread Jacob Keller



On 11/10/2020 2:21 PM, Richard Cochran wrote:
> 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 
> ---
>  pmc_agent.c | 19 +--
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/pmc_agent.c b/pmc_agent.c
> index 6e9c023..d28f3b6 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_BADMSG   -1
> +#define RUN_PMC_INTR -2
> +

Thoughts on making this an enum instead so that it's even more clear
from the function signatures that this is not an integer return code?
The run_pmc function is static so it would only affect callers in this file.

Either way, this is a marked improvement over leaving the values as raw
numbers.

>  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_BADMSG;
>   }
>   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;
>   }
>  }
>  
> 


___
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel


  1   2   3   >