Commit 35eef679 authored by Alessandro Rubini's avatar Alessandro Rubini

time: introduce a new unified data structure

Commit only build for arch-unix (and no tools either)
This simplifies a lot the calculations.

  - all times are now living in a single structure
  - all fields are signed and 64-bit long
  - the 2038 bug is over (we still had 32-bit seconds)
  - no overflow in math or unexplained "unsigned" appearing
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 828f7350
......@@ -16,7 +16,7 @@ unsigned long pp_global_d_flags; /* This is the only "global" file in ppsi */
static void pp_fsm_printf(struct pp_instance *ppi, char *fmt, ...)
{
va_list args;
TimeInternal t;
struct pp_time t;
unsigned long oflags = pp_global_d_flags;
if (!pp_diag_allow(ppi, fsm, 1))
......@@ -28,7 +28,7 @@ static void pp_fsm_printf(struct pp_instance *ppi, char *fmt, ...)
pp_global_d_flags = oflags;
pp_printf("diag-fsm-1-%s: %09d.%03d: ", ppi->port_name,
(int)t.seconds, (int)t.nanoseconds / 1000000);
(int)t.secs, (int)((t.scaled_nsecs >> 16)) / 1000000);
va_start(args, fmt);
pp_vprintf(fmt, args);
va_end(args);
......@@ -203,10 +203,10 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
if (plen) {
msgtype = packet[0] & 0xf;
pp_diag(ppi, frames, 1,
"RECV %02d bytes at %d.%09d (type %x, %s)\n", plen,
(int)ppi->last_rcv_time.seconds,
(int)ppi->last_rcv_time.nanoseconds, msgtype,
pp_msgtype_info[msgtype].name);
"RECV %02d bytes at %9d.%09d (type %x, %s)\n", plen,
(int)ppi->last_rcv_time.secs,
(int)(ppi->last_rcv_time.scaled_nsecs >> 16),
msgtype, pp_msgtype_info[msgtype].name);
}
/*
......
......@@ -11,6 +11,7 @@
#define __PPSI_IEEE_1588_TYPES_H__
#include <stdint.h>
#include <ppsi/pp-time.h>
/* See F.2, pag.223 */
#define PP_ETHERTYPE 0x88f7
......@@ -61,30 +62,6 @@ typedef struct Timestamp { /* page 13 (33) -- no typedef expected */
UInteger32 nanosecondsField;
} Timestamp;
typedef struct TimeInternal {
Integer32 seconds;
Integer32 nanoseconds;
/* White Rabbit extension begin */
Integer32 phase; /* This is the set point */
int correct; /* 0 or 1 */
#if 0
/*
* The following two fields may be used for diagnostics, but
* they cost space. So remove them but keep the code around just
* in case it is useful again (they are only set, never read)
*/
int32_t raw_phase;
int32_t raw_nsec;
#endif
int32_t raw_ahead; /* raw_ahead is used during calibration */
/* White Rabbit extension end */
} TimeInternal;
static inline void clear_TimeInternal(struct TimeInternal *t)
{
memset(t, 0, sizeof(*t));
}
typedef struct ClockIdentity { /* page 13 (33) */
Octet id[8];
} ClockIdentity;
......@@ -136,7 +113,7 @@ typedef struct MsgHeader {
UInteger16 messageLength;
UInteger8 domainNumber;
Octet flagField[2];
Integer64 correctionfield;
struct pp_time cField;;
PortIdentity sourcePortIdentity;
UInteger16 sequenceId;
UInteger8 controlField;
......@@ -158,40 +135,40 @@ typedef struct MsgAnnounce {
/* Sync Message (table 26, page 129) */
typedef struct MsgSync {
Timestamp originTimestamp;
struct pp_time originTimestamp;
} MsgSync;
/* DelayReq Message (table 26, page 129) */
typedef struct MsgDelayReq {
Timestamp originTimestamp;
struct pp_time originTimestamp;
} MsgDelayReq;
/* DelayResp Message (table 27, page 130) */
typedef struct MsgFollowUp {
Timestamp preciseOriginTimestamp;
struct pp_time preciseOriginTimestamp;
} MsgFollowUp;
/* DelayResp Message (table 28, page 130) */
typedef struct MsgDelayResp {
Timestamp receiveTimestamp;
struct pp_time receiveTimestamp;
PortIdentity requestingPortIdentity;
} MsgDelayResp;
/* PdelayReq Message (table 29, page 131) */
typedef struct MsgPDelayReq {
Timestamp originTimestamp;
struct pp_time originTimestamp;
} MsgPDelayReq;
/* PdelayResp Message (table 30, page 131) */
typedef struct MsgPDelayResp {
Timestamp requestReceiptTimestamp;
struct pp_time requestReceiptTimestamp;
PortIdentity requestingPortIdentity;
} MsgPDelayResp;
/* PdelayRespFollowUp Message (table 31, page 132) */
typedef struct MsgPDelayRespFollowUp {
Timestamp responseOriginTimestamp;
struct pp_time responseOriginTimestamp;
PortIdentity requestingPortIdentity;
} MsgPDelayRespFollowUp;
......@@ -229,8 +206,8 @@ typedef struct DSDefault { /* page 65 */
typedef struct DSCurrent { /* page 67 */
/* Dynamic */
UInteger16 stepsRemoved;
TimeInternal offsetFromMaster;
TimeInternal meanPathDelay; /* oneWayDelay */
struct pp_time offsetFromMaster;
struct pp_time meanPathDelay; /* oneWayDelay */
/* White Rabbit extension begin */
UInteger16 primarySlavePortNumber;
/* White Rabbit extension end */
......@@ -256,7 +233,6 @@ typedef struct DSPort { /* page 72 */
/* Dynamic */
/* Enumeration8 portState; -- not used */
Integer8 logMinDelayReqInterval; /* -- same as pdelay one */
/* TimeInternal peerMeanPathDelay; -- not used */
/* Configurable */
Integer8 logAnnounceInterval;
UInteger8 announceReceiptTimeout;
......
......@@ -82,14 +82,14 @@ struct pp_frgn_master {
* where increasing the stiffness (s) lowers the cutoff and increases the delay.
*/
struct pp_avg_fltr {
Integer32 m; /* magnitude */
Integer32 y;
Integer32 s_exp;
int64_t m; /* magnitude */
int64_t y;
int64_t s_exp;
};
struct pp_servo {
TimeInternal m_to_s_dly;
TimeInternal s_to_m_dly;
struct pp_time m_to_s_dly;
struct pp_time s_to_m_dly;
long long obs_drift;
struct pp_avg_fltr mpd_fltr;
};
......@@ -149,10 +149,10 @@ struct pp_instance {
uint16_t peer_vid; /* Our peer's VID (for PROTO_VLAN) */
/* Times, for the various offset computations */
TimeInternal t1, t2, t3, t4, t5, t6; /* *the* stamps */
struct pp_time t1, t2, t3, t4, t5, t6; /* *the* stamps */
Integer32 t4_cf, t6_cf; /* peer delay */
TimeInternal cField; /* transp. clocks */
TimeInternal last_rcv_time, last_snt_time; /* two temporaries */
struct pp_time cField; /* transp. clocks */
struct pp_time last_rcv_time, last_snt_time; /* two temporaries */
/* Page 85: each port shall maintain an implementation-specific
* foreignMasterDS data set for the purposes of qualifying Announce
......
#ifndef __PPSI_PP_TIME_H__
#define __PPSI_PP_TIME_H__
/* Everything internally uses this time format, *signed* */
struct pp_time {
int64_t secs;
int64_t scaled_nsecs;
};
/* The "correct" bit is hidden in the hight bits */
static inline int is_incorrect(const struct pp_time *t)
{
return (((t->secs >> 56) & 0xc0) == 0x80);
}
static inline void mark_incorrect(struct pp_time *t)
{
t->secs |= (0x8fLL << 56);
}
static inline void clear_time(struct pp_time *t)
{
memset(t, 0, sizeof(*t));
}
#endif /* __PPSI_PP_TIME_H__ */
......@@ -22,6 +22,7 @@
#include <arch/arch.h> /* ntohs and so on -- and wr-api.h for wr archs */
/* At this point in time, we need ARRAY_SIZE to conditionally build vlan code */
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
......@@ -154,8 +155,8 @@ struct pp_ext_hooks {
void (*s1)(struct pp_instance *ppi, MsgHeader *hdr, MsgAnnounce *ann);
int (*execute_slave)(struct pp_instance *ppi);
int (*handle_announce)(struct pp_instance *ppi);
int (*handle_followup)(struct pp_instance *ppi, TimeInternal *orig,
TimeInternal *correction_field);
int (*handle_followup)(struct pp_instance *ppi, struct pp_time *orig,
struct pp_time *correction_field);
int (*handle_preq) (struct pp_instance * ppi);
int (*handle_presp) (struct pp_instance * ppi);
int (*pack_announce)(struct pp_instance *ppi);
......@@ -173,7 +174,7 @@ struct pp_network_operations {
int (*init)(struct pp_instance *ppi);
int (*exit)(struct pp_instance *ppi);
int (*recv)(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t);
struct pp_time *t);
int (*send)(struct pp_instance *ppi, void *pkt, int len, int msgtype);
int (*check_packet)(struct pp_globals *ppg, int delay_ms);
};
......@@ -192,8 +193,8 @@ extern struct pp_network_operations unix_net_ops;
* If "set" receives a NULL time value, it should update the TAI offset.
*/
struct pp_time_operations {
int (*get)(struct pp_instance *ppi, TimeInternal *t);
int (*set)(struct pp_instance *ppi, TimeInternal *t);
int (*get)(struct pp_instance *ppi, struct pp_time *t);
int (*set)(struct pp_instance *ppi, const struct pp_time *t);
/* freq_ppb is parts per billion */
int (*adjust)(struct pp_instance *ppi, long offset_ns, long freq_ppb);
int (*adjust_offset)(struct pp_instance *ppi, long offset_ns);
......@@ -380,19 +381,16 @@ extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */
extern int msg_issue_announce(struct pp_instance *ppi);
extern int msg_issue_sync_followup(struct pp_instance *ppi);
extern int msg_issue_request(struct pp_instance *ppi);
extern int msg_issue_delay_resp(struct pp_instance *ppi, TimeInternal *time);
extern int msg_issue_delay_resp(struct pp_instance *ppi,
struct pp_time *time);
extern int msg_issue_pdelay_resp_followup(struct pp_instance *ppi,
TimeInternal * time);
extern int msg_issue_pdelay_resp(struct pp_instance *ppi, TimeInternal * time);
/* Functions for timestamp handling (internal to protocol format conversion*/
/* FIXME: add prefix in function name? */
extern void cField_to_TimeInternal(TimeInternal *internal, Integer64 bigint);
extern int from_TimeInternal(TimeInternal *internal, Timestamp *external);
extern int to_TimeInternal(TimeInternal *internal, Timestamp *external);
extern void add_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y);
extern void sub_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y);
extern void div2_TimeInternal(TimeInternal *r);
struct pp_time *time);
extern int msg_issue_pdelay_resp(struct pp_instance *ppi, struct pp_time *time);
/* Functions for time math */
extern void pp_time_add(struct pp_time *t1, struct pp_time *t2);
extern void pp_time_sub(struct pp_time *t1, struct pp_time *t2);
extern void pp_time_div2(struct pp_time *t);
/*
* The state machine itself is an array of these structures.
......
......@@ -257,8 +257,8 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
return 0;
}
ppi->t4_cf = hdr->correctionfield.lsb;
wr_servo_got_delay(ppi, ppi->t4_cf);
/* FIXME: verify that last-received cField is already accounted for */
wr_servo_got_delay(ppi);
return 0;
}
......
......@@ -133,8 +133,8 @@ enum {
int wr_servo_init(struct pp_instance *ppi);
void wr_servo_reset(struct pp_instance *ppi);
void wr_servo_enable_tracking(int enable);
int wr_servo_got_sync(struct pp_instance *ppi, TimeInternal *t1,
TimeInternal *t2);
int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1,
struct pp_time *t2);
int wr_servo_got_delay(struct pp_instance *ppi, Integer32 cf);
int wr_servo_update(struct pp_instance *ppi);
......@@ -156,12 +156,12 @@ struct wr_servo_state {
int32_t clock_period_ps;
/* These fields are used by servo code, across iterations */
TimeInternal t1, t2, t3, t4, t5, t6;
struct pp_time t1, t2, t3, t4, t5, t6;
int64_t delta_ms_prev;
int missed_iters;
/* Following fields are for monitoring/diagnostics (use w/ shmem) */
TimeInternal mu;
struct pp_time mu;
int64_t picos_mu;
int32_t cur_setpoint;
int64_t delta_ms;
......@@ -176,14 +176,14 @@ struct wr_servo_state {
uint32_t n_err_state;
uint32_t n_err_offset;
uint32_t n_err_delta_rtt;
TimeInternal update_time;
struct pp_time update_time;
};
int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s);
int wr_e2e_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw);
struct wr_servo_state *s, struct pp_time *ts_offset_hw);
int wr_p2p_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw);
struct wr_servo_state *s, struct pp_time *ts_offset_hw);
/* All data used as extension ppsi-wr must be put here */
......
......@@ -234,7 +234,7 @@ int wr_servo_got_sync(struct pp_instance *ppi, TimeInternal *t1,
return 0;
}
int wr_servo_got_delay(struct pp_instance *ppi, Integer32 cf)
int wr_servo_got_delay(struct pp_instance *ppi)
{
struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state;
......@@ -244,15 +244,13 @@ int wr_servo_got_delay(struct pp_instance *ppi, Integer32 cf)
s->t3 = ppi->t3;
/* s->t3.phase = 0; */
s->t4 = ppi->t4;
s->t4.correct = 1; /* clock->delay_req_receive_time.correct; */
s->t4.phase = (int64_t) cf * 1000LL / 65536LL;
/* FIXME: verify that cField is already merged */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
s->t5 = ppi->t5;
s->t5.correct = 1;
s->t5.phase = 0;
s->t6 = ppi->t6;
s->t6.phase = (int64_t) ppi->t6_cf * 1000LL / 65536LL;
wr_p2p_delay(ppi, s);
}
......
......@@ -9,108 +9,68 @@
#include <limits.h>
#include <ppsi/ppsi.h>
void cField_to_TimeInternal(TimeInternal *internal, Integer64 cField)
static void normalize_pp_time(struct pp_time *t)
{
uint64_t i64;
i64 = cField.lsb;
i64 |= ((int64_t)cField.msb) << 32;
if ((int32_t)cField.msb < 0)
pp_error("BUG: %s doesn't support negatives\n", __func__);
/*
* the correctionField is nanoseconds scaled by 16 bits.
* It is updated by transparent clocks and may be used to count
* for asymmetry. Since we support no better than nanosecond with
* the standard protocol and WR (which is better than nanosecond)
* doesn't use this field, just approximate to nanoseconds.
* and the WR extension uses its own methods for asymmetry,
*/
i64 += 0x8000;
i64 >>= 16;
/* Use __div64_32 from library, to avoid libgcc on small targets */
internal->nanoseconds = __div64_32(&i64, PP_NSEC_PER_SEC);
internal->seconds = i64;
}
int from_TimeInternal(TimeInternal *internal, Timestamp *external)
{
/*
* fromInternalTime is only used to convert time given by the system
* to a timestamp As a consequence, no negative value can normally
* be found in (internal)
*
* Note that offsets are also represented with TimeInternal structure,
* and can be negative, but offset are never convert into Timestamp
* so there is no problem here.
*/
if ((internal->seconds & ~INT_MAX) ||
(internal->nanoseconds & ~INT_MAX)) {
pp_error("Negative value (%08x.%08x) cannot be converted "
"into timestamp\n",
internal->seconds,
internal->nanoseconds);
return -1;
} else {
external->secondsField.lsb = internal->seconds;
external->nanosecondsField = internal->nanoseconds;
external->secondsField.msb = 0;
/* no 64b division please, we'll rather loop a few times */
#define SNS_PER_S ((1000LL * 1000 * 1000) << 16)
/* 0 is special: it can have both negative and positive fractions */
if (t->secs == 0LL) {
while (t->scaled_nsecs > SNS_PER_S) {
t->secs++;
t->scaled_nsecs -= SNS_PER_S;
}
while (t->scaled_nsecs < -SNS_PER_S) {
t->secs--;
t->scaled_nsecs += SNS_PER_S;
}
return;
}
return 0;
}
int to_TimeInternal(TimeInternal *internal, Timestamp *external)
{
/* Program will not run after 2038... */
if (external->secondsField.lsb < INT_MAX) {
internal->seconds = external->secondsField.lsb;
internal->nanoseconds = external->nanosecondsField;
return 0;
} else {
pp_error("to_TimeInternal: "
"seconds field is higher than signed integer (32bits)\n");
return -1;
if (t->secs > 0LL) {
while (t->scaled_nsecs < 0) {
t->secs--;
t->scaled_nsecs += SNS_PER_S;
}
while (t->scaled_nsecs > SNS_PER_S) {
t->secs++;
t->scaled_nsecs -= SNS_PER_S;
}
return;
}
}
/* A negative TimeInternal has both secs and nsecs <= 0 */
static void normalize_TimeInternal(TimeInternal *r)
{
r->seconds += r->nanoseconds / PP_NSEC_PER_SEC;
r->nanoseconds -= r->nanoseconds / PP_NSEC_PER_SEC * PP_NSEC_PER_SEC;
if (r->seconds > 0 && r->nanoseconds < 0) {
r->seconds -= 1;
r->nanoseconds += PP_NSEC_PER_SEC;
} else if (r->seconds < 0 && r->nanoseconds > 0) {
r->seconds += 1;
r->nanoseconds -= PP_NSEC_PER_SEC;
/* A negative pp_time has both secs and scaled_nsecs <= 0 */
while (t->scaled_nsecs < -SNS_PER_S) {
t->secs--;
t->scaled_nsecs += SNS_PER_S;
}
while (t->scaled_nsecs > 0) {
t->secs++;
t->scaled_nsecs -= SNS_PER_S;
}
}
void add_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y)
void pp_time_add(struct pp_time *t1, struct pp_time *t2)
{
r->seconds = x->seconds + y->seconds;
r->nanoseconds = x->nanoseconds + y->nanoseconds;
normalize_TimeInternal(r);
t1->secs += t2->secs;
t1->scaled_nsecs += t2->scaled_nsecs;
normalize_pp_time(t1);
}
void sub_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y)
void pp_time_sub(struct pp_time *t1, struct pp_time *t2)
{
r->seconds = x->seconds - y->seconds;
r->nanoseconds = x->nanoseconds - y->nanoseconds;
normalize_TimeInternal(r);
t1->secs -= t2->secs;
t1->scaled_nsecs -= t2->scaled_nsecs;
normalize_pp_time(t1);
}
void div2_TimeInternal(TimeInternal *r)
void pp_time_div2(struct pp_time *t)
{
r->nanoseconds += r->seconds % 2 * PP_NSEC_PER_SEC;
r->seconds /= 2;
r->nanoseconds /= 2;
int sign = (t->secs < 0) ? -1 : 1;
normalize_TimeInternal(r);
t->scaled_nsecs >>= 1;
if (t->secs &1)
t->scaled_nsecs += sign * SNS_PER_S / 2;
t->secs >>= 1;
}
......@@ -24,8 +24,8 @@ void m1(struct pp_instance *ppi)
/* Current data set update */
DSCUR(ppi)->stepsRemoved = 0;
clear_TimeInternal(&DSCUR(ppi)->offsetFromMaster);
clear_TimeInternal(&DSCUR(ppi)->meanPathDelay);
clear_time(&DSCUR(ppi)->offsetFromMaster);
clear_time(&DSCUR(ppi)->meanPathDelay);
/* Parent data set: we are the parent */
memset(parent, 0, sizeof(*parent));
......
......@@ -109,7 +109,8 @@ int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
/* t2 may be overriden by follow-up, cField is always valid */
ppi->t2 = ppi->last_rcv_time;
cField_to_TimeInternal(&ppi->cField, hdr->correctionfield);
/* FIXME: merge cField here? */
ppi->cField = hdr->cField;
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0) {
ppi->flags |= PPI_FLAG_WAITING_FOR_F_UP;
......@@ -118,8 +119,7 @@ int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
}
msg_unpack_sync(buf, &sync);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
to_TimeInternal(&ppi->t1,
&sync.originTimestamp);
ppi->t1 = sync.originTimestamp;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
......@@ -145,9 +145,9 @@ int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
resp.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t4, &resp.requestReceiptTimestamp);
ppi->t4 = resp.requestReceiptTimestamp;
pp_time_add(&ppi->t4, &hdr->cField);
ppi->t6 = ppi->last_rcv_time;
ppi->t6_cf = phase_to_cf_units(ppi->last_rcv_time.phase);
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0)
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
else {
......@@ -159,9 +159,6 @@ int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
memset(&ppi->t5, 0, sizeof(ppi->t5));
}
/* Save correctionField of pdelay_resp, see 11.4.3 d 3/4 */
cField_to_TimeInternal(&ppi->cField, hdr->correctionfield);
if (!(hdr->flagField[0] & PP_TWO_STEP_FLAG)) {
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
......@@ -182,7 +179,6 @@ int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
int e = 0;
TimeInternal tmp;
if (plen < PP_PDELAY_R_FUP_LENGTH)
/* Ignore */
......@@ -199,14 +195,12 @@ int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t5,
&respFllw.responseOriginTimestamp);
ppi->t5 = respFllw.responseOriginTimestamp;
/*
* Add correctionField of pdelay_resp_followup to
* cf of pdelay_resp (see 11.4.3 d 4)
*/
cField_to_TimeInternal(&tmp, hdr->correctionfield);
add_TimeInternal(&ppi->cField, &ppi->cField, &tmp);
pp_time_add(&ppi->t4, &hdr->cField);
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
......@@ -242,7 +236,6 @@ int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
{
MsgFollowUp follow;
int ret = 0;
TimeInternal cField;
MsgHeader *hdr = &ppi->received_ptp_header;
......@@ -266,11 +259,10 @@ int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
msg_unpack_follow_up(buf, &follow);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
to_TimeInternal(&ppi->t1, &follow.preciseOriginTimestamp);
ppi->t1 = follow.preciseOriginTimestamp;
/* Add correctionField in follow-up to sync correctionField, see 11.2 */
cField_to_TimeInternal(&cField, hdr->correctionfield);
add_TimeInternal(&ppi->cField, &ppi->cField, &cField);
pp_time_add(&ppi->cField, &hdr->cField); /* FIXME: check this cField */
/* Call the extension; it may do it all and ask to return */
if (pp_hooks.handle_followup)
......@@ -311,10 +303,10 @@ int __send_and_log(struct pp_instance *ppi, int msglen, int chtype)
}
/* FIXME: diagnosticst should be looped back in the send method */
pp_diag(ppi, frames, 1, "SENT %02d bytes at %d.%09d (%s)\n", msglen,
(int)(ppi->last_snt_time.seconds),
(int)(ppi->last_snt_time.nanoseconds),
(int)(ppi->last_snt_time.secs),
(int)(ppi->last_snt_time.scaled_nsecs >> 16),
pp_msgtype_info[msgtype].name);
if (chtype == PP_NP_EVT && ppi->last_snt_time.correct == 0)
if (chtype == PP_NP_EVT && is_incorrect(&ppi->last_snt_time))
return PP_SEND_NO_STAMP;
/* count sent packets */
......
......@@ -42,7 +42,7 @@ int __send_and_log(struct pp_instance *ppi, int msglen, int chtype);
/* Count successfully received PTP packets */
static inline int __recv_and_count(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
struct pp_time *t)
{
int ret;
ret = ppi->n_ops->recv(ppi, pkt, len, t);
......
This diff is collapsed.
This diff is collapsed.
......@@ -51,10 +51,9 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
return 0;
}
to_TimeInternal(&ppi->t4, &resp.receiveTimestamp);
ppi->t4 = resp.receiveTimestamp;
/* Save delay resp cf in ppi->cField */
cField_to_TimeInternal(&ppi->cField,
hdr->correctionfield);
ppi->cField = hdr->cField; /* FIXME: merge cField here? */
if (pp_hooks.handle_resp)
e = pp_hooks.handle_resp(ppi);
......
......@@ -26,7 +26,7 @@
/* unix_recv_msg uses recvmsg for timestamp query */
static int unix_recv_msg(struct pp_instance *ppi, int fd, void *pkt, int len,
TimeInternal *t)
struct pp_time *t)
{
struct ethhdr *hdr = pkt;
ssize_t ret;
......@@ -88,9 +88,8 @@ static int unix_recv_msg(struct pp_instance *ppi, int fd, void *pkt, int len,
}
if (tv) {
t->seconds = tv->tv_sec + DSPRO(ppi)->currentUtcOffset;
t->nanoseconds = tv->tv_usec * 1000;
t->correct = 1;
t->secs = tv->tv_sec + DSPRO(ppi)->currentUtcOffset;
t->scaled_nsecs = (uint64_t)(tv->tv_usec * 1000) << 16;
} else {
/*
* get the recording time here, even though it may put a big
......@@ -122,13 +121,14 @@ static int unix_recv_msg(struct pp_instance *ppi, int fd, void *pkt, int len,
/* This is not really hw... */
pp_diag(ppi, time, 2, "recv stamp: %i.%09i (%s)\n",
(int)t->seconds, (int)t->nanoseconds, tv ? "kernel" : "user");
(int)t->secs, (int)(t->scaled_nsecs >> 16),
tv ? "kernel" : "user");
return ret;
}
/* Receive and send is *not* so trivial */
static int unix_net_recv(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
struct pp_time *t)
{
struct pp_channel *ch1, *ch2;
struct ethhdr *hdr = pkt;
......@@ -184,7 +184,7 @@ static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
struct ethhdr *hdr = pkt;
struct pp_vlanhdr *vhdr = pkt;
struct pp_channel *ch = ppi->ch + chtype;
TimeInternal *t = &ppi->last_snt_time;
struct pp_time *t = &ppi->last_snt_time;
int is_pdelay = pp_msgtype_info[msgtype].is_pdelay;
static const uint16_t udpport[] = {
[PP_NP_GEN] = PP_GEN_PORT,
......@@ -653,4 +653,3 @@ struct pp_network_operations unix_net_ops = {
.check_packet = unix_net_check_packet,
};
......@@ -23,22 +23,21 @@ static void clock_fatal_error(char *context)
exit(1);
}
static int unix_time_get(struct pp_instance *ppi, TimeInternal *t)
static int unix_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct timespec tp;
if (clock_gettime(CLOCK_REALTIME, &tp) < 0)
clock_fatal_error("clock_gettime");
/* TAI = UTC + 35 */
t->seconds = tp.tv_sec + DSPRO(ppi)->currentUtcOffset;
t->nanoseconds = tp.tv_nsec;
t->correct = 1;
t->secs = tp.tv_sec + DSPRO(ppi)->currentUtcOffset;
t->scaled_nsecs = ((int64_t)tp.tv_nsec) << 16;
if (!(pp_global_d_flags & PP_FLAG_NOTIMELOG))
pp_diag(ppi, time, 2, "%s: %9li.%09li\n", __func__,
tp.tv_sec, tp.tv_nsec);
return 0;
}
static int unix_time_set(struct pp_instance *ppi, TimeInternal *t)
static int unix_time_set(struct pp_instance *ppi, const struct pp_time *t)
{
struct timespec tp;
......@@ -55,8 +54,8 @@ static int unix_time_set(struct pp_instance *ppi, TimeInternal *t)
}
/* UTC = TAI - 35 */
tp.tv_sec = t->seconds - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->nanoseconds;
tp.tv_sec = t->secs - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->scaled_nsecs >> 16;
if (clock_settime(CLOCK_REALTIME, &tp) < 0)
clock_fatal_error("clock_settime");
pp_diag(ppi, time, 1, "%s: %9li.%09li\n", __func__,
......
......@@ -31,18 +31,18 @@ static int dumpstruct(char *p1, char *p2, char *name, void *ptr, int size)
}
#if __STDC_HOSTED__
static void dump_time(char *prefix, struct TimeInternal *ti)
static void dump_time(char *prefix, const struct pp_time *t)
{
struct timeval tv;
struct tm tm;
tv.tv_sec = ti->seconds;
tv.tv_usec = ti->nanoseconds / 1000;
tv.tv_sec = t->secs;
tv.tv_usec = (t->scaled_nsecs >> 16) / 1000;
localtime_r(&tv.tv_sec, &tm);
printf("%sTIME: (%li - 0x%lx) %02i:%02i:%02i.%06li%s\n", prefix,
tv.tv_sec, tv.tv_sec,
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec,
!ti->correct ? " invalid" : "");
is_incorrect(t) ? " invalid" : "");
}
#else
static void dump_time(char *prefix, struct TimeInternal *ti)
......@@ -259,7 +259,7 @@ out:
}
/* This dumps a complete udp frame, starting from the eth header */
int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
int dump_udppkt(char *prefix, void *buf, int len, const struct pp_time *t,
int vlan)
{
struct ethhdr *eth = buf;
......@@ -267,8 +267,8 @@ int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
struct udphdr *udp;
void *payload;
if (ti)
dump_time(prefix, ti);
if (t)
dump_time(prefix, t);
dump_vlan(prefix, vlan);
......@@ -285,23 +285,23 @@ int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
}
/* This dumps the payload only, used for udp frames without headers */
int dump_payloadpkt(char *prefix, void *buf, int len, struct TimeInternal *ti)
int dump_payloadpkt(char *prefix, void *buf, int len, const struct pp_time *t)
{
if (ti)
dump_time(prefix, ti);
if (t)
dump_time(prefix, t);
dump_payload(prefix, buf, len);
return 0;
}
/* This dumps everything, used for raw frames with headers and ptp payload */
int dump_1588pkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
int dump_1588pkt(char *prefix, void *buf, int len, const struct pp_time *t,
int vlan)
{
struct ethhdr *eth = buf;
void *payload;
if (ti)
dump_time(prefix, ti);
if (t)
dump_time(prefix, t);
dump_vlan(prefix, vlan);
payload = buf + dump_eth(prefix, eth);
dump_payload(prefix, payload, len - (payload - buf));
......
......@@ -14,10 +14,11 @@
#define printf pp_printf
#endif
int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
int vlan);
int dump_payloadpkt(char *prefix, void *buf, int len, struct TimeInternal *ti);
int dump_1588pkt(char *prefix, void *buf, int len, struct TimeInternal *ti,
int dump_udppkt(char *prefix, void *buf, int len,
const struct pp_time *t, int vlan);
int dump_payloadpkt(char *prefix, void *buf, int len,
const struct pp_time *t);
int dump_1588pkt(char *prefix, void *buf, int len, const struct pp_time *t,
int vlan);
#endif /* __PTPDUMP_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment