* [PATCH v1] net/idpf: harden PTP frequency adjustment @ 2026-03-12 18:43 Soumyadeep Hore 2026-03-12 11:57 ` Bruce Richardson 2026-04-07 20:04 ` [PATCH v2] " Soumyadeep Hore 0 siblings, 2 replies; 5+ messages in thread From: Soumyadeep Hore @ 2026-03-12 18:43 UTC (permalink / raw) To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev, rajesh3.kumar Normalize ppm to an unsigned magnitude before using it in the increment value scaling path. This avoids negating INT64_MIN and also prevents subtracting 62 from the reduced log sum unless the sum is still above the overflow threshold reported by Coverity. Coverity issue: 501832 Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com> --- drivers/net/intel/idpf/idpf_ethdev.c | 32 +++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c index 5e57a45775..1c5bd2ee12 100644 --- a/drivers/net/intel/idpf/idpf_ethdev.c +++ b/drivers/net/intel/idpf/idpf_ethdev.c @@ -1007,7 +1007,7 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) struct idpf_ptp *ptp = adapter->ptp; int64_t incval, diff = 0; bool negative = false; - uint64_t div, rem; + uint64_t abs_ppm, div, rem; uint64_t divisor = 1000000ULL << 16; int shift; int ret; @@ -1016,26 +1016,34 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) if (ppm < 0) { negative = true; - ppm = -ppm; + abs_ppm = ppm == INT64_MIN ? (uint64_t)INT64_MAX + 1 : + (uint64_t)(-ppm); + } else { + abs_ppm = (uint64_t)ppm; } /* can incval * ppm overflow ? */ - if (rte_log2_u64(incval) + rte_log2_u64(ppm) > 62) { - rem = ppm % divisor; - div = ppm / divisor; + if (rte_log2_u64(incval) + rte_log2_u64(abs_ppm) > 62) { + rem = abs_ppm % divisor; + div = abs_ppm / divisor; diff = div * incval; - ppm = rem; + abs_ppm = rem; + + if (abs_ppm != 0) { + uint32_t log_sum; - shift = rte_log2_u64(incval) + rte_log2_u64(ppm) - 62; - if (shift > 0) { - /* drop precision */ - ppm >>= shift; - divisor >>= shift; + log_sum = rte_log2_u64(incval) + rte_log2_u64(abs_ppm); + if (log_sum > 62) { + shift = log_sum - 62; + /* drop precision */ + abs_ppm >>= shift; + divisor >>= shift; + } } } if (divisor) - diff = diff + incval * ppm / divisor; + diff = diff + incval * abs_ppm / divisor; if (negative) incval -= diff; -- 2.47.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v1] net/idpf: harden PTP frequency adjustment 2026-03-12 18:43 [PATCH v1] net/idpf: harden PTP frequency adjustment Soumyadeep Hore @ 2026-03-12 11:57 ` Bruce Richardson 2026-04-07 15:14 ` Stephen Hemminger 2026-04-07 20:04 ` [PATCH v2] " Soumyadeep Hore 1 sibling, 1 reply; 5+ messages in thread From: Bruce Richardson @ 2026-03-12 11:57 UTC (permalink / raw) To: Soumyadeep Hore; +Cc: manoj.kumar.subbarao, aman.deep.singh, dev, rajesh3.kumar On Thu, Mar 12, 2026 at 02:43:44PM -0400, Soumyadeep Hore wrote: > Normalize ppm to an unsigned magnitude before using it in the > increment value scaling path. > > This avoids negating INT64_MIN and also prevents subtracting 62 > from the reduced log sum unless the sum is still above the > overflow threshold reported by Coverity. > > Coverity issue: 501832 > > Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com> > --- > drivers/net/intel/idpf/idpf_ethdev.c | 32 +++++++++++++++++----------- > 1 file changed, 20 insertions(+), 12 deletions(-) > > diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c > index 5e57a45775..1c5bd2ee12 100644 > --- a/drivers/net/intel/idpf/idpf_ethdev.c > +++ b/drivers/net/intel/idpf/idpf_ethdev.c > @@ -1007,7 +1007,7 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > struct idpf_ptp *ptp = adapter->ptp; > int64_t incval, diff = 0; > bool negative = false; > - uint64_t div, rem; > + uint64_t abs_ppm, div, rem; > uint64_t divisor = 1000000ULL << 16; > int shift; > int ret; > @@ -1016,26 +1016,34 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > > if (ppm < 0) { > negative = true; > - ppm = -ppm; > + abs_ppm = ppm == INT64_MIN ? (uint64_t)INT64_MAX + 1 : > + (uint64_t)(-ppm); > + } else { > + abs_ppm = (uint64_t)ppm; > } > > /* can incval * ppm overflow ? */ > - if (rte_log2_u64(incval) + rte_log2_u64(ppm) > 62) { > - rem = ppm % divisor; > - div = ppm / divisor; > + if (rte_log2_u64(incval) + rte_log2_u64(abs_ppm) > 62) { > + rem = abs_ppm % divisor; > + div = abs_ppm / divisor; > diff = div * incval; > - ppm = rem; > + abs_ppm = rem; > + > + if (abs_ppm != 0) { > + uint32_t log_sum; > > - shift = rte_log2_u64(incval) + rte_log2_u64(ppm) - 62; > - if (shift > 0) { > - /* drop precision */ > - ppm >>= shift; > - divisor >>= shift; > + log_sum = rte_log2_u64(incval) + rte_log2_u64(abs_ppm); > + if (log_sum > 62) { > + shift = log_sum - 62; > + /* drop precision */ > + abs_ppm >>= shift; > + divisor >>= shift; > + } > } > } > > if (divisor) > - diff = diff + incval * ppm / divisor; > + diff = diff + incval * abs_ppm / divisor; > Asking Claude AI about this code and how to simplify it a bit while also avoiding the INT64_MIN issue, it suggests using __int128 type, giving much shorter code: __int128 diff; int ret; /* * ppm is scaled ppm: 1 ppm = 2^16 units (matching Linux adjfine). * Use __int128 to avoid overflow without complex split/shift logic, * and to correctly handle ppm == INT64_MIN. */ incval = ptp->base_incval; diff = ((__int128)incval * ppm) / (1000000LL << 16); incval += (int64_t)diff; ret = idpf_ptp_adj_dev_clk_fine(adapter, incval); if (ret != 0) PMD_DRV_LOG(ERR, "PTP failed to set incval, err %d", ret); return ret; Maybe worth considering? /Bruce ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1] net/idpf: harden PTP frequency adjustment 2026-03-12 11:57 ` Bruce Richardson @ 2026-04-07 15:14 ` Stephen Hemminger 2026-04-07 15:56 ` Bruce Richardson 0 siblings, 1 reply; 5+ messages in thread From: Stephen Hemminger @ 2026-04-07 15:14 UTC (permalink / raw) To: Bruce Richardson Cc: Soumyadeep Hore, manoj.kumar.subbarao, aman.deep.singh, dev, rajesh3.kumar On Thu, 12 Mar 2026 11:57:33 +0000 Bruce Richardson <bruce.richardson@intel.com> wrote: > On Thu, Mar 12, 2026 at 02:43:44PM -0400, Soumyadeep Hore wrote: > > Normalize ppm to an unsigned magnitude before using it in the > > increment value scaling path. > > > > This avoids negating INT64_MIN and also prevents subtracting 62 > > from the reduced log sum unless the sum is still above the > > overflow threshold reported by Coverity. > > > > Coverity issue: 501832 > > > > Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com> > > --- > > drivers/net/intel/idpf/idpf_ethdev.c | 32 +++++++++++++++++----------- > > 1 file changed, 20 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c > > index 5e57a45775..1c5bd2ee12 100644 > > --- a/drivers/net/intel/idpf/idpf_ethdev.c > > +++ b/drivers/net/intel/idpf/idpf_ethdev.c > > @@ -1007,7 +1007,7 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > > struct idpf_ptp *ptp = adapter->ptp; > > int64_t incval, diff = 0; > > bool negative = false; > > - uint64_t div, rem; > > + uint64_t abs_ppm, div, rem; > > uint64_t divisor = 1000000ULL << 16; > > int shift; > > int ret; > > @@ -1016,26 +1016,34 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > > > > if (ppm < 0) { > > negative = true; > > - ppm = -ppm; > > + abs_ppm = ppm == INT64_MIN ? (uint64_t)INT64_MAX + 1 : > > + (uint64_t)(-ppm); > > + } else { > > + abs_ppm = (uint64_t)ppm; > > } > > > > /* can incval * ppm overflow ? */ > > - if (rte_log2_u64(incval) + rte_log2_u64(ppm) > 62) { > > - rem = ppm % divisor; > > - div = ppm / divisor; > > + if (rte_log2_u64(incval) + rte_log2_u64(abs_ppm) > 62) { > > + rem = abs_ppm % divisor; > > + div = abs_ppm / divisor; > > diff = div * incval; > > - ppm = rem; > > + abs_ppm = rem; > > + > > + if (abs_ppm != 0) { > > + uint32_t log_sum; > > > > - shift = rte_log2_u64(incval) + rte_log2_u64(ppm) - 62; > > - if (shift > 0) { > > - /* drop precision */ > > - ppm >>= shift; > > - divisor >>= shift; > > + log_sum = rte_log2_u64(incval) + rte_log2_u64(abs_ppm); > > + if (log_sum > 62) { > > + shift = log_sum - 62; > > + /* drop precision */ > > + abs_ppm >>= shift; > > + divisor >>= shift; > > + } > > } > > } > > > > if (divisor) > > - diff = diff + incval * ppm / divisor; > > + diff = diff + incval * abs_ppm / divisor; > > > > Asking Claude AI about this code and how to simplify it a bit while also > avoiding the INT64_MIN issue, it suggests using __int128 type, giving much > shorter code: > > __int128 diff; > int ret; > > /* > * ppm is scaled ppm: 1 ppm = 2^16 units (matching Linux adjfine). > * Use __int128 to avoid overflow without complex split/shift logic, > * and to correctly handle ppm == INT64_MIN. > */ > incval = ptp->base_incval; > diff = ((__int128)incval * ppm) / (1000000LL << 16); > incval += (int64_t)diff; > > ret = idpf_ptp_adj_dev_clk_fine(adapter, incval); > if (ret != 0) > PMD_DRV_LOG(ERR, "PTP failed to set incval, err %d", ret); > return ret; > > Maybe worth considering? > > /Bruce Claude AI review of this patch spotted some possible math issues. Normalize ppm to an unsigned magnitude before using it in the increment value scaling path. This avoids negating INT64_MIN and also prevents subtracting 62 from the reduced log sum unless the sum is still above the overflow threshold reported by Coverity. The simplification is a nice improvement and the __int128 approach is correct for realistic hardware values. One concern: Warning: drivers/net/intel/idpf/idpf_ethdev.c The cast (int64_t)diff silently truncates if diff does not fit in 64 bits. The __int128 multiplication itself never overflows (both UINT64_MAX × INT64_MAX and UINT64_MAX × INT64_MIN fit within signed __int128), but after dividing by 1000000LL << 16 the quotient can still exceed INT64_MAX when incval is large and ppm is extreme. For realistic PTP hardware (base_incval around 2^32) this is fine, but the API accepts the full int64_t range without documented bounds. Adding an explicit clamp or assertion before the cast would preserve the defensive character of the code being replaced: ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1] net/idpf: harden PTP frequency adjustment 2026-04-07 15:14 ` Stephen Hemminger @ 2026-04-07 15:56 ` Bruce Richardson 0 siblings, 0 replies; 5+ messages in thread From: Bruce Richardson @ 2026-04-07 15:56 UTC (permalink / raw) To: Stephen Hemminger Cc: Soumyadeep Hore, manoj.kumar.subbarao, aman.deep.singh, dev, rajesh3.kumar On Tue, Apr 07, 2026 at 08:14:45AM -0700, Stephen Hemminger wrote: > On Thu, 12 Mar 2026 11:57:33 +0000 > Bruce Richardson <bruce.richardson@intel.com> wrote: > > > On Thu, Mar 12, 2026 at 02:43:44PM -0400, Soumyadeep Hore wrote: > > > Normalize ppm to an unsigned magnitude before using it in the > > > increment value scaling path. > > > > > > This avoids negating INT64_MIN and also prevents subtracting 62 > > > from the reduced log sum unless the sum is still above the > > > overflow threshold reported by Coverity. > > > > > > Coverity issue: 501832 > > > > > > Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com> > > > --- > > > drivers/net/intel/idpf/idpf_ethdev.c | 32 +++++++++++++++++----------- > > > 1 file changed, 20 insertions(+), 12 deletions(-) > > > > > > diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c > > > index 5e57a45775..1c5bd2ee12 100644 > > > --- a/drivers/net/intel/idpf/idpf_ethdev.c > > > +++ b/drivers/net/intel/idpf/idpf_ethdev.c > > > @@ -1007,7 +1007,7 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > > > struct idpf_ptp *ptp = adapter->ptp; > > > int64_t incval, diff = 0; > > > bool negative = false; > > > - uint64_t div, rem; > > > + uint64_t abs_ppm, div, rem; > > > uint64_t divisor = 1000000ULL << 16; > > > int shift; > > > int ret; > > > @@ -1016,26 +1016,34 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) > > > > > > if (ppm < 0) { > > > negative = true; > > > - ppm = -ppm; > > > + abs_ppm = ppm == INT64_MIN ? (uint64_t)INT64_MAX + 1 : > > > + (uint64_t)(-ppm); > > > + } else { > > > + abs_ppm = (uint64_t)ppm; > > > } > > > > > > /* can incval * ppm overflow ? */ > > > - if (rte_log2_u64(incval) + rte_log2_u64(ppm) > 62) { > > > - rem = ppm % divisor; > > > - div = ppm / divisor; > > > + if (rte_log2_u64(incval) + rte_log2_u64(abs_ppm) > 62) { > > > + rem = abs_ppm % divisor; > > > + div = abs_ppm / divisor; > > > diff = div * incval; > > > - ppm = rem; > > > + abs_ppm = rem; > > > + > > > + if (abs_ppm != 0) { > > > + uint32_t log_sum; > > > > > > - shift = rte_log2_u64(incval) + rte_log2_u64(ppm) - 62; > > > - if (shift > 0) { > > > - /* drop precision */ > > > - ppm >>= shift; > > > - divisor >>= shift; > > > + log_sum = rte_log2_u64(incval) + rte_log2_u64(abs_ppm); > > > + if (log_sum > 62) { > > > + shift = log_sum - 62; > > > + /* drop precision */ > > > + abs_ppm >>= shift; > > > + divisor >>= shift; > > > + } > > > } > > > } > > > > > > if (divisor) > > > - diff = diff + incval * ppm / divisor; > > > + diff = diff + incval * abs_ppm / divisor; > > > > > > > Asking Claude AI about this code and how to simplify it a bit while also > > avoiding the INT64_MIN issue, it suggests using __int128 type, giving much > > shorter code: > > > > __int128 diff; > > int ret; > > > > /* > > * ppm is scaled ppm: 1 ppm = 2^16 units (matching Linux adjfine). > > * Use __int128 to avoid overflow without complex split/shift logic, > > * and to correctly handle ppm == INT64_MIN. > > */ > > incval = ptp->base_incval; > > diff = ((__int128)incval * ppm) / (1000000LL << 16); > > incval += (int64_t)diff; > > > > ret = idpf_ptp_adj_dev_clk_fine(adapter, incval); > > if (ret != 0) > > PMD_DRV_LOG(ERR, "PTP failed to set incval, err %d", ret); > > return ret; > > > > Maybe worth considering? > > > > /Bruce > > Claude AI review of this patch spotted some possible math issues. > > > > Normalize ppm to an unsigned magnitude before using it in the > increment value scaling path. > This avoids negating INT64_MIN and also prevents subtracting 62 > from the reduced log sum unless the sum is still above the > overflow threshold reported by Coverity. > > The simplification is a nice improvement and the __int128 approach > is correct for realistic hardware values. > > One concern: > Warning: drivers/net/intel/idpf/idpf_ethdev.c > The cast (int64_t)diff silently truncates if diff does not fit in > 64 bits. The __int128 multiplication itself never overflows (both > UINT64_MAX × INT64_MAX and UINT64_MAX × INT64_MIN fit within signed > __int128), but after dividing by 1000000LL << 16 the quotient can > still exceed INT64_MAX when incval is large and ppm is extreme. > For realistic PTP hardware (base_incval around 2^32) this is fine, > but the API accepts the full int64_t range without documented bounds. > Adding an explicit clamp or assertion before the cast would preserve > the defensive character of the code being replaced: Sadly, the CI is also complaining. It seems that __int128 doesn't seem to be available for 32-bit ARM. :-( Not sure what the best approach here is, whether to add a more complicated fallback path for that case, or just disallow the timesync on the unsupported platforms for now. [32-bit x86 doesn't seem to have issues, for example] /Bruce ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] net/idpf: harden PTP frequency adjustment 2026-03-12 18:43 [PATCH v1] net/idpf: harden PTP frequency adjustment Soumyadeep Hore 2026-03-12 11:57 ` Bruce Richardson @ 2026-04-07 20:04 ` Soumyadeep Hore 1 sibling, 0 replies; 5+ messages in thread From: Soumyadeep Hore @ 2026-04-07 20:04 UTC (permalink / raw) To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev, rajesh3.kumar Normalize ppm to an unsigned magnitude before using it in the increment value scaling path. This avoids negating INT64_MIN and also prevents subtracting 62 from the reduced log sum unless the sum is still above the overflow threshold reported by Coverity. Coverity issue: 501832 Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com> --- v2: -Addressed Bruce's comments --- drivers/net/intel/idpf/idpf_ethdev.c | 38 ++++------------------------ 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/drivers/net/intel/idpf/idpf_ethdev.c b/drivers/net/intel/idpf/idpf_ethdev.c index 5e57a45775..23a2af6332 100644 --- a/drivers/net/intel/idpf/idpf_ethdev.c +++ b/drivers/net/intel/idpf/idpf_ethdev.c @@ -1005,42 +1005,14 @@ idpf_timesync_adjust_freq(struct rte_eth_dev *dev, int64_t ppm) struct idpf_vport *vport = dev->data->dev_private; struct idpf_adapter *adapter = vport->adapter; struct idpf_ptp *ptp = adapter->ptp; - int64_t incval, diff = 0; - bool negative = false; - uint64_t div, rem; - uint64_t divisor = 1000000ULL << 16; - int shift; + uint64_t incval; + __int128 diff; int ret; + /* ppm is scaled by 2^16 to match Linux adjfine. */ incval = ptp->base_incval; - - if (ppm < 0) { - negative = true; - ppm = -ppm; - } - - /* can incval * ppm overflow ? */ - if (rte_log2_u64(incval) + rte_log2_u64(ppm) > 62) { - rem = ppm % divisor; - div = ppm / divisor; - diff = div * incval; - ppm = rem; - - shift = rte_log2_u64(incval) + rte_log2_u64(ppm) - 62; - if (shift > 0) { - /* drop precision */ - ppm >>= shift; - divisor >>= shift; - } - } - - if (divisor) - diff = diff + incval * ppm / divisor; - - if (negative) - incval -= diff; - else - incval += diff; + diff = ((__int128)incval * ppm) / (1000000LL << 16); + incval += (int64_t)diff; ret = idpf_ptp_adj_dev_clk_fine(adapter, incval); if (ret) { -- 2.47.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-07 15:57 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-12 18:43 [PATCH v1] net/idpf: harden PTP frequency adjustment Soumyadeep Hore 2026-03-12 11:57 ` Bruce Richardson 2026-04-07 15:14 ` Stephen Hemminger 2026-04-07 15:56 ` Bruce Richardson 2026-04-07 20:04 ` [PATCH v2] " Soumyadeep Hore
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox