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 0xFFFFFFFF. On most platforms, a signed integer cannot hold 0xFFFFFFFF, and on these platforms ptp4l is unable to read the default configuration file:
$ ./ptp4l -f configs/default.cfg -i eno0 0xFFFFFFFF 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 <jacob.e.kel...@intel.com> --- 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", 0xFFFFFFFF, 0, INT_MAX), - PORT_ITEM_INT("power_profile.2011.networkTimeInaccuracy", 0, 0, INT_MAX), - PORT_ITEM_INT("power_profile.2017.totalTimeInaccuracy", 0xFFFFFFFF, 0, INT_MAX), + PORT_ITEM_INT("power_profile.2011.grandmasterTimeInaccuracy", 0xFFFFFFFF, 0, UINT32_MAX), + PORT_ITEM_INT("power_profile.2011.networkTimeInaccuracy", 0, 0, UINT32_MAX), + PORT_ITEM_INT("power_profile.2017.totalTimeInaccuracy", 0xFFFFFFFF, 0, UINT32_MAX), PORT_ITEM_INT("power_profile.grandmasterID", 0, 0, 0xFFFF), 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, &val, cgi->min.i, cgi->max.i); + r = get_ranged_ll(value, &val, cgi->min.i, cgi->max.i); break; case CFG_TYPE_DOUBLE: r = get_ranged_double(value, &df, 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. */ @@ -1153,7 +1175,7 @@ int config_set_section_int(struct config *cfg, const char *section, } } dst->val.i = val; - pr_debug("section item %s.%s now %d", section, option, dst->val.i); + pr_debug("section item %s.%s now %lld", section, option, dst->val.i); return 0; } diff --git a/config.h b/config.h index 14d2f64415dc..10de851ddc2f 100644 --- a/config.h +++ b/config.h @@ -61,6 +61,9 @@ double config_get_double(struct config *cfg, const char *section, int config_get_int(struct config *cfg, const char *section, const char *option); +unsigned int config_get_uint(struct config *cfg, const char *section, + const char *option); + char *config_get_string(struct config *cfg, const char *section, const char *option); diff --git a/port.c b/port.c index 3453716f6020..697cf08ce421 100644 --- a/port.c +++ b/port.c @@ -3401,11 +3401,11 @@ struct port *port_open(const char *phc_device, p->pwr.grandmasterID = config_get_int(cfg, p->name, "power_profile.grandmasterID"); p->pwr.grandmasterTimeInaccuracy = - config_get_int(cfg, p->name, "power_profile.2011.grandmasterTimeInaccuracy"); + config_get_uint(cfg, p->name, "power_profile.2011.grandmasterTimeInaccuracy"); p->pwr.networkTimeInaccuracy = - config_get_int(cfg, p->name, "power_profile.2011.networkTimeInaccuracy"); + config_get_uint(cfg, p->name, "power_profile.2011.networkTimeInaccuracy"); p->pwr.totalTimeInaccuracy = - config_get_int(cfg, p->name, "power_profile.2017.totalTimeInaccuracy"); + config_get_uint(cfg, p->name, "power_profile.2017.totalTimeInaccuracy"); p->slave_event_monitor = clock_slave_monitor(clock); if (!port_is_uds(p) && unicast_client_initialize(p)) { diff --git a/util.c b/util.c index e204c9cdb02a..d189701702ff 100644 --- a/util.c +++ b/util.c @@ -531,6 +531,21 @@ enum parser_result get_ranged_uint(const char *str_val, unsigned int *result, return PARSED_OK; } +enum parser_result get_ranged_ll(const char *str_val, long long *result, + long long min, long long max) +{ + long long parsed_val; + char *endptr = NULL; + errno = 0; + parsed_val = strtoll(str_val, &endptr, 0); + if (*endptr != '\0' || endptr == str_val) + return MALFORMED; + if (errno == ERANGE || parsed_val < min || parsed_val > max) + return OUT_OF_RANGE; + *result = parsed_val; + return PARSED_OK; +} + enum parser_result get_ranged_double(const char *str_val, double *result, double min, double max) { diff --git a/util.h b/util.h index 2bbde7186bce..ad772cc1d466 100644 --- a/util.h +++ b/util.h @@ -295,6 +295,22 @@ enum parser_result get_ranged_int(const char *str_val, int *result, enum parser_result get_ranged_uint(const char *str_val, unsigned int *result, unsigned int min, unsigned int max); +/** + * get a long long integer value from string with error checking and range + * specification. + * + * @param str_val string which contains an integer value. + * @param result parsed value is stored in here. + * @param min lower limit. return out_of_range if parsed value + * is less than min. + * @param max upper limit. return out_of_range if parsed value + * is bigger than max. + * @return parsed_ok on success, malformed if str_val is malformed, + * out_of_range if str_val is out of range. + */ +enum parser_result get_ranged_ll(const char *str_val, long long *result, + long long min, long long max); + /** * Get a double value from string with error checking and range * specification. -- 2.40.0.471.gbd7f14d9353b _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel