This is embarrassing, I forgot to remove my debug logs. I will update the patch and resend it.
On Sat, Sep 11, 2021 at 11:53 AM <joseph.matan...@gmail.com> wrote: > From: Joseph Matan <joseph.matan...@gmail.com> > > The percentile filter can be very useful when running in a non-ptp-aware > environment. > For example, if we set a low percentile value (and the filter length is > large enough), > we can still get a good estimation of the real delay, > even if our setup is running under heavy network traffic. > (when setting the percentile value to 0.50, the median filter is a private > use-case of the percentile filter) > > Signed-off-by: Joseph Matan <joseph.matan...@gmail.com> > --- > clock.c | 3 ++- > config.c | 6 ++++-- > configs/default.cfg | 1 + > filter.c | 8 +++++--- > filter.h | 8 +++++--- > makefile | 2 +- > mmedian.c => mpercentile.c | 42 +++++++++++++++++++++----------------- > mmedian.h => mpercentile.h | 10 ++++----- > nsm.c | 2 +- > port.c | 3 ++- > ptp4l.8 | 6 +++++- > tsproc.c | 4 ++-- > tsproc.h | 3 ++- > 13 files changed, 58 insertions(+), 40 deletions(-) > rename mmedian.c => mpercentile.c (64%) > rename mmedian.h => mpercentile.h (81%) > > diff --git a/clock.c b/clock.c > index ec70f91..9c4b6cc 100644 > --- a/clock.c > +++ b/clock.c > @@ -1171,7 +1171,8 @@ struct clock *clock_create(enum clock_type type, > struct config *config, > } > c->tsproc = tsproc_create(config_get_int(config, NULL, > "tsproc_mode"), > config_get_int(config, NULL, > "delay_filter"), > - config_get_int(config, NULL, > "delay_filter_length")); > + config_get_int(config, NULL, > "delay_filter_length"), > + config_get_double(config, NULL, > "delay_filter_percentile")); > if (!c->tsproc) { > pr_err("Failed to create time stamp processor"); > return NULL; > diff --git a/config.c b/config.c > index eb8b988..31351f4 100644 > --- a/config.c > +++ b/config.c > @@ -158,8 +158,9 @@ static struct config_enum dataset_comp_enu[] = { > }; > > static struct config_enum delay_filter_enu[] = { > - { "moving_average", FILTER_MOVING_AVERAGE }, > - { "moving_median", FILTER_MOVING_MEDIAN }, > + { "moving_average", FILTER_MOVING_AVERAGE }, > + { "moving_median", FILTER_MOVING_MEDIAN }, > + { "moving_percentile", FILTER_MOVING_PERCENTILE }, > { NULL, 0 }, > }; > > @@ -238,6 +239,7 @@ struct config_item config_tab[] = { > PORT_ITEM_INT("delayAsymmetry", 0, INT_MIN, INT_MAX), > PORT_ITEM_ENU("delay_filter", FILTER_MOVING_MEDIAN, > delay_filter_enu), > PORT_ITEM_INT("delay_filter_length", 10, 1, INT_MAX), > + PORT_ITEM_DBL("delay_filter_percentile", 0.5, 0.0, 1.0), > PORT_ITEM_ENU("delay_mechanism", DM_E2E, delay_mech_enu), > GLOB_ITEM_INT("dscp_event", 0, 0, 63), > GLOB_ITEM_INT("dscp_general", 0, 0, 63), > diff --git a/configs/default.cfg b/configs/default.cfg > index d615610..29cba1a 100644 > --- a/configs/default.cfg > +++ b/configs/default.cfg > @@ -102,6 +102,7 @@ time_stamping hardware > tsproc_mode filter > delay_filter moving_median > delay_filter_length 10 > +delay_filter_percentile 0.5 > egressLatency 0 > ingressLatency 0 > boundary_clock_jbod 0 > diff --git a/filter.c b/filter.c > index fceb29a..f779280 100644 > --- a/filter.c > +++ b/filter.c > @@ -19,15 +19,17 @@ > > #include "filter_private.h" > #include "mave.h" > -#include "mmedian.h" > +#include "mpercentile.h" > > -struct filter *filter_create(enum filter_type type, int length) > +struct filter *filter_create(enum filter_type type, int length, double > percentile) > { > switch (type) { > case FILTER_MOVING_AVERAGE: > return mave_create(length); > case FILTER_MOVING_MEDIAN: > - return mmedian_create(length); > + return mpercentile_create(length, 0.5); > + case FILTER_MOVING_PERCENTILE: > + return mpercentile_create(length, percentile); > default: > return NULL; > } > diff --git a/filter.h b/filter.h > index 5a196bc..78be629 100644 > --- a/filter.h > +++ b/filter.h > @@ -31,15 +31,17 @@ struct filter; > enum filter_type { > FILTER_MOVING_AVERAGE, > FILTER_MOVING_MEDIAN, > + FILTER_MOVING_PERCENTILE, > }; > > /** > * Create a new instance of a filter. > - * @param type The type of the filter to create. > - * @param length The filter's length. > + * @param type The type of the filter to create. > + * @param length The filter's length. > + * @param percentile The percentile of the delay filter samples (valid > only for FILTER_MOVING_PERCENTILE filter type). > * @return A pointer to a new filter on success, NULL otherwise. > */ > -struct filter *filter_create(enum filter_type type, int length); > +struct filter *filter_create(enum filter_type type, int length, double > percentile); > > /** > * Destroy an instance of a filter. > diff --git a/makefile b/makefile > index 33e7ca0..7de5eab 100644 > --- a/makefile > +++ b/makefile > @@ -23,7 +23,7 @@ VER = -DVER=$(version) > CFLAGS = -Wall $(VER) $(incdefs) $(DEBUG) $(EXTRA_CFLAGS) > LDLIBS = -lm -lrt -pthread $(EXTRA_LDFLAGS) > PRG = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc > -FILTERS = filter.o mave.o mmedian.o > +FILTERS = filter.o mave.o mpercentile.o > SERVOS = linreg.o ntpshm.o nullf.o pi.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_master.o \ > diff --git a/mmedian.c b/mpercentile.c > similarity index 64% > rename from mmedian.c > rename to mpercentile.c > index 2383467..cb4010b 100644 > --- a/mmedian.c > +++ b/mpercentile.c > @@ -1,5 +1,5 @@ > /** > - * @file mmedian.c > + * @file mpercentile.c > * @note Copyright (C) 2013 Miroslav Lichvar <mlich...@redhat.com> > * > * This program is free software; you can redistribute it and/or modify > @@ -19,36 +19,41 @@ > #include <stdlib.h> > #include <string.h> > > -#include "mmedian.h" > +#include "mpercentile.h" > #include "filter_private.h" > +#include "print.h" > +#include "math.h" > > -struct mmedian { > +struct mpercentile { > struct filter filter; > int cnt; > int len; > int index; > + double percentile; > + int percentile_index; > /* Indices sorted by value. */ > int *order; > /* Values stored in circular buffer. */ > tmv_t *samples; > }; > > -static void mmedian_destroy(struct filter *filter) > +static void mpercentile_destroy(struct filter *filter) > { > - struct mmedian *m = container_of(filter, struct mmedian, filter); > + struct mpercentile *m = container_of(filter, struct mpercentile, > filter); > free(m->order); > free(m->samples); > free(m); > } > > -static tmv_t mmedian_sample(struct filter *filter, tmv_t sample) > +static tmv_t mpercentile_sample(struct filter *filter, tmv_t sample) > { > - struct mmedian *m = container_of(filter, struct mmedian, filter); > + struct mpercentile *m = container_of(filter, struct mpercentile, > filter); > int i; > > m->samples[m->index] = sample; > if (m->cnt < m->len) { > m->cnt++; > + m->percentile_index = (int)round(m->percentile * (m->cnt - > 1)); > } else { > /* Remove index of the replaced value from order. */ > for (i = 0; i < m->cnt; i++) > @@ -69,32 +74,30 @@ static tmv_t mmedian_sample(struct filter *filter, > tmv_t sample) > > m->index = (1 + m->index) % m->len; > > - if (m->cnt % 2) > - return m->samples[m->order[m->cnt / 2]]; > - else > - return tmv_div(tmv_add(m->samples[m->order[m->cnt / 2 - > 1]], > - m->samples[m->order[m->cnt / 2]]), > 2); > + /*TODO: deleteMe*/ pr_info("lenght(%d) percentile(%0.2f) > percentile_index(%d), filtered_delay(%lld)", > + m->cnt, m->percentile, m->percentile_index, > tmv_to_nanoseconds(m->samples[m->order[m->percentile_index]])); > + return m->samples[m->order[m->percentile_index]]; > } > > -static void mmedian_reset(struct filter *filter) > +static void mpercentile_reset(struct filter *filter) > { > - struct mmedian *m = container_of(filter, struct mmedian, filter); > + struct mpercentile *m = container_of(filter, struct mpercentile, > filter); > m->cnt = 0; > m->index = 0; > } > > -struct filter *mmedian_create(int length) > +struct filter *mpercentile_create(int length, double percentile) > { > - struct mmedian *m; > + struct mpercentile *m; > > if (length < 1) > return NULL; > m = calloc(1, sizeof(*m)); > if (!m) > return NULL; > - m->filter.destroy = mmedian_destroy; > - m->filter.sample = mmedian_sample; > - m->filter.reset = mmedian_reset; > + m->filter.destroy = mpercentile_destroy; > + m->filter.sample = mpercentile_sample; > + m->filter.reset = mpercentile_reset; > m->order = calloc(1, length * sizeof(*m->order)); > if (!m->order) { > free(m); > @@ -107,5 +110,6 @@ struct filter *mmedian_create(int length) > return NULL; > } > m->len = length; > + m->percentile = percentile; > return &m->filter; > } > diff --git a/mmedian.h b/mpercentile.h > similarity index 81% > rename from mmedian.h > rename to mpercentile.h > index 8fee0dc..193a333 100644 > --- a/mmedian.h > +++ b/mpercentile.h > @@ -1,6 +1,6 @@ > /** > - * @file mmedian.h > - * @brief Implements a moving median. > + * @file mpercentile.h > + * @brief Implements a moving percentile. > * @note Copyright (C) 2013 Miroslav Lichvar <mlich...@redhat.com> > * > * This program is free software; you can redistribute it and/or modify > @@ -17,11 +17,11 @@ > * with this program; if not, write to the Free Software Foundation, Inc., > * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > */ > -#ifndef HAVE_MMEDIAN_H > -#define HAVE_MMEDIAN_H > +#ifndef HAVE_MPERCENTILE_H > +#define HAVE_MPERCENTILE_H > > #include "filter.h" > > -struct filter *mmedian_create(int length); > +struct filter *mpercentile_create(int length, double percentile); > > #endif > diff --git a/nsm.c b/nsm.c > index 5aa925b..3ede6a0 100644 > --- a/nsm.c > +++ b/nsm.c > @@ -295,7 +295,7 @@ static int nsm_open(struct nsm *nsm, struct config > *cfg) > } > nsm->port_identity.portNumber = 1; > > - nsm->tsproc = tsproc_create(TSPROC_RAW, FILTER_MOVING_AVERAGE, 10); > + nsm->tsproc = tsproc_create(TSPROC_RAW, FILTER_MOVING_AVERAGE, 10, > 0); > if (!nsm->tsproc) { > pr_err("failed to create time stamp processor"); > goto no_tsproc; > diff --git a/port.c b/port.c > index c82bdaf..6dae97b 100644 > --- a/port.c > +++ b/port.c > @@ -3200,7 +3200,8 @@ struct port *port_open(const char *phc_device, > > p->tsproc = tsproc_create(config_get_int(cfg, p->name, > "tsproc_mode"), > config_get_int(cfg, p->name, > "delay_filter"), > - config_get_int(cfg, p->name, > "delay_filter_length")); > + config_get_int(cfg, p->name, > "delay_filter_length"), > + config_get_double(cfg, p->name, > "delay_filter_percentile")); > if (!p->tsproc) { > pr_err("Failed to create time stamp processor"); > goto err_uc_service; > diff --git a/ptp4l.8 b/ptp4l.8 > index a0779ef..3a3fc13 100644 > --- a/ptp4l.8 > +++ b/ptp4l.8 > @@ -340,13 +340,17 @@ The default is filter. > .TP > .B delay_filter > Select the algorithm used to filter the measured delay and peer delay. > Possible > -values are moving_average and moving_median. > +values are moving_average, moving_median and moving_percentile. > The default is moving_median. > .TP > .B delay_filter_length > The length of the delay filter in samples. > The default is 10. > .TP > +.B delay_filter_percentile > +The percentile of the delay filter samples (relevant only when choosing > the delay_filter as moving_percentile). > +The default is 0.5 (50%). > +.TP > .B egressLatency > Specifies the difference in nanoseconds between the actual transmission > time at the reference plane and the reported transmit time stamp. This > diff --git a/tsproc.c b/tsproc.c > index a871049..8ace4a6 100644 > --- a/tsproc.c > +++ b/tsproc.c > @@ -61,7 +61,7 @@ static int weighting(struct tsproc *tsp) > } > > struct tsproc *tsproc_create(enum tsproc_mode mode, > - enum filter_type delay_filter, int > filter_length) > + enum filter_type delay_filter, int > filter_length, double percentile) > { > struct tsproc *tsp; > > @@ -81,7 +81,7 @@ struct tsproc *tsproc_create(enum tsproc_mode mode, > return NULL; > } > > - tsp->delay_filter = filter_create(delay_filter, filter_length); > + tsp->delay_filter = filter_create(delay_filter, filter_length, > percentile); > if (!tsp->delay_filter) { > free(tsp); > return NULL; > diff --git a/tsproc.h b/tsproc.h > index fdb35a8..5970705 100644 > --- a/tsproc.h > +++ b/tsproc.h > @@ -40,10 +40,11 @@ enum tsproc_mode { > * @param mode Time stamp processing mode. > * @param delay_filter Type of the filter that will be applied to delay. > * @param filter_length Length of the filter. > + * @param percentile The percentile of the delay filter samples > (valid only for FILTER_MOVING_PERCENTILE filter type). > * @return A pointer to a new tsproc on success, NULL > otherwise. > */ > struct tsproc *tsproc_create(enum tsproc_mode mode, > - enum filter_type delay_filter, int > filter_length); > + enum filter_type delay_filter, int > filter_length, double percentile); > > /** > * Destroy a time stamp processor. > -- > 2.17.1 > >
_______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel