Add modular filter interface.

Similarly to the servo interface, allow multiple filters to be
used for delay filtering. Convert mave to the new interface.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
master
Miroslav Lichvar 2013-10-29 11:58:18 +01:00 committed by Richard Cochran
parent 7bd59737d3
commit 2c9718f3c2
8 changed files with 191 additions and 46 deletions

16
clock.c
View File

@ -27,7 +27,7 @@
#include "clockadj.h" #include "clockadj.h"
#include "clockcheck.h" #include "clockcheck.h"
#include "foreign.h" #include "foreign.h"
#include "mave.h" #include "filter.h"
#include "missing.h" #include "missing.h"
#include "msg.h" #include "msg.h"
#include "phc.h" #include "phc.h"
@ -86,7 +86,7 @@ struct clock {
enum servo_state servo_state; enum servo_state servo_state;
tmv_t master_offset; tmv_t master_offset;
tmv_t path_delay; tmv_t path_delay;
struct mave *avg_delay; struct filter *delay_filter;
struct freq_estimator fest; struct freq_estimator fest;
struct time_status_np status; struct time_status_np status;
double nrr; double nrr;
@ -121,7 +121,7 @@ void clock_destroy(struct clock *c)
phc_close(c->clkid); phc_close(c->clkid);
} }
servo_destroy(c->servo); servo_destroy(c->servo);
mave_destroy(c->avg_delay); filter_destroy(c->delay_filter);
stats_destroy(c->stats.offset); stats_destroy(c->stats.offset);
stats_destroy(c->stats.freq); stats_destroy(c->stats.freq);
stats_destroy(c->stats.delay); stats_destroy(c->stats.delay);
@ -632,9 +632,9 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
return NULL; return NULL;
} }
c->servo_state = SERVO_UNLOCKED; c->servo_state = SERVO_UNLOCKED;
c->avg_delay = mave_create(MAVE_LENGTH); c->delay_filter = filter_create(FILTER_MOVING_AVERAGE, MAVE_LENGTH);
if (!c->avg_delay) { if (!c->delay_filter) {
pr_err("Failed to create moving average"); pr_err("Failed to create delay filter");
return NULL; return NULL;
} }
c->stats_interval = dds->stats_interval; c->stats_interval = dds->stats_interval;
@ -992,7 +992,7 @@ void clock_path_delay(struct clock *c, struct timespec req, struct timestamp rx,
pr_warning("c3 %10lld", c3); pr_warning("c3 %10lld", c3);
} }
c->path_delay = mave_accumulate(c->avg_delay, pd); c->path_delay = filter_sample(c->delay_filter, pd);
c->cur.meanPathDelay = tmv_to_TimeInterval(c->path_delay); c->cur.meanPathDelay = tmv_to_TimeInterval(c->path_delay);
@ -1170,7 +1170,7 @@ static void handle_state_decision_event(struct clock *c)
if (!cid_eq(&best_id, &c->best_id)) { if (!cid_eq(&best_id, &c->best_id)) {
clock_freq_est_reset(c); clock_freq_est_reset(c);
mave_reset(c->avg_delay); filter_reset(c->delay_filter);
c->t1 = tmv_zero(); c->t1 = tmv_zero();
c->t2 = tmv_zero(); c->t2 = tmv_zero();
c->path_delay = 0; c->path_delay = 0;

46
filter.c 100644
View File

@ -0,0 +1,46 @@
/**
* @file filter.c
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "filter_private.h"
#include "mave.h"
struct filter *filter_create(enum filter_type type, int length)
{
switch (type) {
case FILTER_MOVING_AVERAGE:
return mave_create(length);
default:
return NULL;
}
}
void filter_destroy(struct filter *filter)
{
filter->destroy(filter);
}
tmv_t filter_sample(struct filter *filter, tmv_t sample)
{
return filter->sample(filter, sample);
}
void filter_reset(struct filter *filter)
{
filter->reset(filter);
}

63
filter.h 100644
View File

@ -0,0 +1,63 @@
/**
* @file filter.h
* @brief Implements a generic filter interface.
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef HAVE_FILTER_H
#define HAVE_FILTER_H
#include "tmv.h"
/** Opaque type */
struct filter;
/**
* Defines the available filters.
*/
enum filter_type {
FILTER_MOVING_AVERAGE,
};
/**
* Create a new instance of a filter.
* @param type The type of the filter to create.
* @param length The filter's length.
* @return A pointer to a new filter on success, NULL otherwise.
*/
struct filter *filter_create(enum filter_type type, int length);
/**
* Destroy an instance of a filter.
* @param filter Pointer to a filter obtained via @ref filter_create().
*/
void filter_destroy(struct filter *filter);
/**
* Feed a sample into a filter.
* @param filter Pointer to a filter obtained via @ref filter_create().
* @param sample The input sample.
* @return The output value.
*/
tmv_t filter_sample(struct filter *filter, tmv_t sample);
/**
* Reset a filter.
* @param filter Pointer to a filter obtained via @ref filter_create().
*/
void filter_reset(struct filter *filter);
#endif

33
filter_private.h 100644
View File

@ -0,0 +1,33 @@
/**
* @file filter_private.h
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef HAVE_FILTER_PRIVATE_H
#define HAVE_FILTER_PRIVATE_H
#include "tmv.h"
#include "contain.h"
struct filter {
void (*destroy)(struct filter *filter);
tmv_t (*sample)(struct filter *filter, tmv_t sample);
void (*reset)(struct filter *filter);
};
#endif

View File

@ -24,8 +24,9 @@ CFLAGS = -Wall $(VER) $(incdefs) $(DEBUG) $(EXTRA_CFLAGS)
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS) LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
PRG = ptp4l pmc phc2sys hwstamp_ctl PRG = ptp4l pmc phc2sys hwstamp_ctl
OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o fault.o \ OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o fault.o \
fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o print.o raw.o servo.o \ filter.o fsm.o mave.o msg.o phc.o pi.o port.o print.o \
sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o uds.o util.o version.o ptp4l.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o \
udp6.o uds.o util.o version.o
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
SRC = $(OBJECTS:.o=.c) SRC = $(OBJECTS:.o=.c)

48
mave.c
View File

@ -20,8 +20,10 @@
#include <string.h> #include <string.h>
#include "mave.h" #include "mave.h"
#include "filter_private.h"
struct mave { struct mave {
struct filter filter;
int cnt; int cnt;
int len; int len;
int index; int index;
@ -29,30 +31,17 @@ struct mave {
tmv_t *val; tmv_t *val;
}; };
struct mave *mave_create(int length) static void mave_destroy(struct filter *filter)
{
struct mave *m;
m = calloc(1, sizeof(*m));
if (!m) {
return NULL;
}
m->val = calloc(1, length * sizeof(*m->val));
if (!m->val) {
free(m);
return NULL;
}
m->len = length;
return m;
}
void mave_destroy(struct mave *m)
{ {
struct mave *m = container_of(filter, struct mave, filter);
free(m->val); free(m->val);
free(m); free(m);
} }
tmv_t mave_accumulate(struct mave *m, tmv_t val) static tmv_t mave_accumulate(struct filter *filter, tmv_t val)
{ {
struct mave *m = container_of(filter, struct mave, filter);
m->sum = tmv_sub(m->sum, m->val[m->index]); m->sum = tmv_sub(m->sum, m->val[m->index]);
m->val[m->index] = val; m->val[m->index] = val;
m->index = (1 + m->index) % m->len; m->index = (1 + m->index) % m->len;
@ -63,10 +52,31 @@ tmv_t mave_accumulate(struct mave *m, tmv_t val)
return tmv_div(m->sum, m->cnt); return tmv_div(m->sum, m->cnt);
} }
void mave_reset(struct mave *m) static void mave_reset(struct filter *filter)
{ {
struct mave *m = container_of(filter, struct mave, filter);
m->cnt = 0; m->cnt = 0;
m->index = 0; m->index = 0;
m->sum = 0; m->sum = 0;
memset(m->val, 0, m->len * sizeof(*m->val)); memset(m->val, 0, m->len * sizeof(*m->val));
} }
struct filter *mave_create(int length)
{
struct mave *m;
m = calloc(1, sizeof(*m));
if (!m) {
return NULL;
}
m->filter.destroy = mave_destroy;
m->filter.sample = mave_accumulate;
m->filter.reset = mave_reset;
m->val = calloc(1, length * sizeof(*m->val));
if (!m->val) {
free(m);
return NULL;
}
m->len = length;
return &m->filter;
}

12
mave.h
View File

@ -20,16 +20,8 @@
#ifndef HAVE_MAVE_H #ifndef HAVE_MAVE_H
#define HAVE_MAVE_H #define HAVE_MAVE_H
#include "tmv.h" #include "filter.h"
struct mave; struct filter *mave_create(int length);
struct mave *mave_create(int length);
void mave_destroy(struct mave *m);
tmv_t mave_accumulate(struct mave *m, tmv_t val);
void mave_reset(struct mave *m);
#endif #endif

14
port.c
View File

@ -25,7 +25,7 @@
#include "bmc.h" #include "bmc.h"
#include "clock.h" #include "clock.h"
#include "mave.h" #include "filter.h"
#include "missing.h" #include "missing.h"
#include "msg.h" #include "msg.h"
#include "port.h" #include "port.h"
@ -82,7 +82,7 @@ struct port {
} seqnum; } seqnum;
struct tmtab tmtab; struct tmtab tmtab;
tmv_t peer_delay; tmv_t peer_delay;
struct mave *avg_delay; struct filter *delay_filter;
int log_sync_interval; int log_sync_interval;
struct nrate_estimator nrate; struct nrate_estimator nrate;
unsigned int pdr_missing; unsigned int pdr_missing;
@ -1716,7 +1716,7 @@ calc:
pd = tmv_sub(pd, c2); pd = tmv_sub(pd, c2);
pd = tmv_div(pd, 2); pd = tmv_div(pd, 2);
p->peer_delay = mave_accumulate(p->avg_delay, pd); p->peer_delay = filter_sample(p->delay_filter, pd);
p->peerMeanPathDelay = tmv_to_TimeInterval(p->peer_delay); p->peerMeanPathDelay = tmv_to_TimeInterval(p->peer_delay);
@ -1845,7 +1845,7 @@ void port_close(struct port *p)
port_disable(p); port_disable(p);
} }
transport_destroy(p->trp); transport_destroy(p->trp);
mave_destroy(p->avg_delay); filter_destroy(p->delay_filter);
free(p); free(p);
} }
@ -2306,9 +2306,9 @@ struct port *port_open(int phc_index,
p->delayMechanism = interface->dm; p->delayMechanism = interface->dm;
p->versionNumber = PTP_VERSION; p->versionNumber = PTP_VERSION;
p->avg_delay = mave_create(PORT_MAVE_LENGTH); p->delay_filter = filter_create(FILTER_MOVING_AVERAGE, PORT_MAVE_LENGTH);
if (!p->avg_delay) { if (!p->delay_filter) {
pr_err("Failed to create moving average"); pr_err("Failed to create delay filter");
transport_destroy(p->trp); transport_destroy(p->trp);
free(p); free(p);
return NULL; return NULL;