Commit cdf616d8 authored by Sven Meier's avatar Sven Meier Committed by Adam Wujek

bmc: add agging, call periodically and data sets

BMC fixed to be called periodically and data sets comparisments fixed
also changed the foreign master table adding and agging and some
minor adpatations in state pre-master
parent ed394bc1
......@@ -55,7 +55,7 @@ static int run_all_state_machines(struct pp_globals *ppg)
else {
ppi->n_ops->exit(ppi);
ppi->frgn_rec_num = 0;
ppi->frgn_rec_best = -1;
ppi->frgn_rec_best = 0;
if (ppg->ebest_idx == ppi->port_idx)
wr_servo_reset(ppi);
}
......
......@@ -167,7 +167,7 @@ static int type_length[__PP_NR_MESSAGES_TYPES] = {
[PPM_DELAY_RESP] = PP_DELAY_RESP_LENGTH,
[PPM_PDELAY_R_FUP] = PP_PDELAY_R_FUP_LENGTH,
[PPM_ANNOUNCE] = PP_ANNOUNCE_LENGTH,
[PPM_SIGNALING] = PP_HEADER_LENGTH,
[PPM_SIGNALING] = PP_HEADER_LENGTH,
[PPM_MANAGEMENT] = PP_MANAGEMENT_LENGTH,
};
......@@ -253,11 +253,18 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
plen = 0;
}
}
/* run bmc independent of state, and since not message driven do this
* here 9.2.6.8 */
if (pp_timeout(ppi, PP_TO_BMC))
ppi->next_state = bmc(ppi);
if (ppi->state != ppi->next_state)
return leave_current_state(ppi);
if (!plen)
ppi->received_ptp_header.messageType = PPM_NO_MESSAGE;
err = ip->f1(ppi, packet, plen);
if (err)
pp_printf("fsm for %s: Error %i in %s\n",
......@@ -268,5 +275,10 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
return leave_current_state(ppi);
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* check if the BMC timeout is the next to run */
if (pp_next_delay_1(ppi, PP_TO_BMC) < ppi->next_delay)
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_BMC);
return ppi->next_delay;
}
......@@ -23,11 +23,11 @@
#define PP_DEFAULT_AP 10
#define PP_DEFAULT_AI 1000
#define PP_DEFAULT_DELAY_S 6
#define PP_DEFAULT_ANNOUNCE_INTERVAL 1 /* 0 in 802.1AS */
#define PP_DEFAULT_ANNOUNCE_INTERVAL 1 /* 0 in 802.1AS */
#define PP_DEFAULT_DELAYREQ_INTERVAL 0
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_RECEIPT_TIMEOUT 3
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 20 /* 3 by default */
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 3 /* 3 by default */
/* Clock classes (pag 55, PTP-2008). See ppsi-manual for an explanation */
#define PP_CLASS_SLAVE_ONLY 255
......@@ -43,12 +43,15 @@
* same value as in ptpdv1
*/
#define PP_NR_FOREIGN_RECORDS 5
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
#define PP_FOREIGN_MASTER_THRESHOLD 2
#define PP_DEFAULT_TTL 1
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_REQUEST = 0,
PP_TO_SYNC_SEND,
PP_TO_BMC,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_SEND,
PP_TO_FAULT,
......
......@@ -45,7 +45,7 @@ typedef struct Integer64 {
typedef struct UInteger64 {
uint32_t lsb;
uint32_t msb;
uint32_t msb;
} UInteger64;
struct TimeInterval { /* page 12 (32) -- never used */
......@@ -54,7 +54,7 @@ struct TimeInterval { /* page 12 (32) -- never used */
/* White Rabbit extension */
typedef struct FixedDelta {
UInteger64 scaledPicoseconds;
UInteger64 scaledPicoseconds;
} FixedDelta;
typedef struct Timestamp { /* page 13 (33) -- no typedef expected */
......@@ -217,7 +217,7 @@ typedef struct DSCurrent { /* page 67 */
typedef struct DSParent { /* page 68 */
/* Dynamic */
PortIdentity parentPortIdentity;
/* Boolean parentStats; -- not used */
/* Boolean parentStats; -- not used */
UInteger16 observedParentOffsetScaledLogVariance;
Integer32 observedParentClockPhaseChangeRate;
ClockIdentity grandmasterIdentity;
......
......@@ -65,6 +65,11 @@ struct pp_channel {
*/
struct pp_frgn_master {
PortIdentity port_id; /* used to identify old/new masters */
PortIdentity source_id; /* used for the dataset comparisment */
/* how many announce messages from this port where received in the
* interval */
int ann_cnt[PP_FOREIGN_MASTER_TIME_WINDOW];
/* We don't need all fields of the following ones */
MsgAnnounce ann;
......
......@@ -231,6 +231,7 @@ extern struct pp_time_operations unix_time_ops;
*/
extern void pp_timeout_init(struct pp_instance *ppi);
extern void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec);
extern void pp_timeout_clear(struct pp_instance *ppi, int index);
extern void pp_timeout_set(struct pp_instance *ppi, int index);
extern void pp_timeout_setall(struct pp_instance *ppi);
extern int pp_timeout(struct pp_instance *ppi, int index)
......@@ -360,7 +361,9 @@ extern void pp_servo_got_presp(struct pp_instance *ppi); /* got all t3..t6 */
/* bmc.c */
extern void m1(struct pp_instance *ppi);
extern int bmc(struct pp_instance *ppi);
extern int bmc_dataset_cmp(struct pp_instance *ppi,
struct pp_frgn_master *a,
struct pp_frgn_master *b);
/* msg.c */
extern void msg_init_header(struct pp_instance *ppi, void *buf);
extern int __attribute__((warn_unused_result))
......@@ -383,7 +386,7 @@ extern void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req);
#define PP_SEND_ERROR -1
#define PP_SEND_NO_STAMP 1
#define PP_SEND_DROP -2
#define PP_RECV_DROP PP_SEND_DROP
#define PP_RECV_DROP PP_SEND_DROP
extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */
extern int msg_issue_announce(struct pp_instance *ppi);
......
......@@ -11,8 +11,8 @@
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data
* structure */
#define WRS_PPSI_SHMEM_VERSION 20 /* Replace cField, t4_cf and t6_cf with
syncCF */
#define WRS_PPSI_SHMEM_VERSION 21 /* Added source_id and ann_cnt to struct
* pp_frgn_master */
/* Don't include the Following when this file is included in assembler. */
#ifndef __ASSEMBLY__
......
This diff is collapsed.
......@@ -85,14 +85,13 @@ int st_com_execute_slave(struct pp_instance *ppi)
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)
|| pp_timeout(ppi, PP_TO_FAULT)) {
/*
/*
* Note: TO_FAULTY == SYNCHRONIZATION_FAULT
* should move us to UNCALIBRATED (not implemented)
*/
ppi->frgn_rec_num = 0;
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
......
......@@ -111,14 +111,52 @@ int pp_lib_may_issue_request(struct pp_instance *ppi)
/* Called by this file, basically when an announce is got, all states */
static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
{
int i;
int i, worst, sel;
struct pp_frgn_master frgn_master;
MsgHeader *hdr = &ppi->received_ptp_header;
/* if we are a configured master don't add*/
if (ppi->role == PPSI_ROLE_MASTER)
return;
/*
* header and announce field of each Foreign Master are
* useful to run Best Master Clock Algorithm
*/
msg_copy_header(&frgn_master.hdr, hdr);
msg_unpack_announce(buf, &frgn_master.ann);
/* Copy new foreign master data set from announce message */
memcpy(&frgn_master.port_id,
&hdr->sourcePortIdentity, sizeof(hdr->sourcePortIdentity));
/* Copy the source port identity */
memcpy(&frgn_master.source_id,
&DSPOR(ppi)->portIdentity, sizeof(DSPOR(ppi)->portIdentity));
/* Check if announce from a port from this clock 9.3.2.5 a) */
if (!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSDEF(ppi)->clockIdentity,
sizeof(DSDEF(ppi)->clockIdentity)))
return;
/* Check if announce has steps removed larger than 255 9.3.2.5 d) */
if (frgn_master.ann.stepsRemoved >= 255)
return;
/* Check if foreign master is already known */
for (i = 0; i < ppi->frgn_rec_num; i++) {
if (!memcmp(&hdr->sourcePortIdentity,
&ppi->frgn_master[i].port_id,
sizeof(hdr->sourcePortIdentity))) {
pp_diag(ppi, bmc, 2, "Foreign Master %i updated\n", i);
/* update the number of announce received if correct
* sequence number 9.3.2.5 b) */
if (hdr->sequenceId
== (ppi->frgn_master[i].hdr.sequenceId + 1))
ppi->frgn_master[i].ann_cnt[0]++;
/* already in Foreign master data set, update info */
msg_copy_header(&ppi->frgn_master[i].hdr, hdr);
msg_unpack_announce(buf, &ppi->frgn_master[i].ann);
......@@ -126,32 +164,55 @@ static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
}
}
/* set qualification timeouts as valid to compare against worst*/
for (i = 0; i < PP_FOREIGN_MASTER_TIME_WINDOW; i++)
frgn_master.ann_cnt[i] = 1;
/* New foreign master */
if (ppi->frgn_rec_num < PP_NR_FOREIGN_RECORDS)
if (ppi->frgn_rec_num < PP_NR_FOREIGN_RECORDS) {
/* there is space for a new one */
sel = ppi->frgn_rec_num;
ppi->frgn_rec_num++;
/* FIXME: replace the worst */
i = ppi->frgn_rec_num - 1;
} else {
/* find the worst to replace */
for (i = 1, worst = 0; i < ppi->frgn_rec_num; i++)
if (bmc_dataset_cmp(ppi, &ppi->frgn_master[i],
&ppi->frgn_master[worst]) > 0)
worst = i;
/* check if worst is better than the new one, and skip the new
* one if so */
if (bmc_dataset_cmp(ppi, &ppi->frgn_master[worst], &frgn_master)
< 0) {
pp_diag(ppi, bmc, 1, "%s:%i: New foreign "
"master worse than worst in the full "
"table, skipping\n",
__func__, __LINE__);
return;
}
/* Copy new foreign master data set from announce message */
memcpy(&ppi->frgn_master[i].port_id,
&hdr->sourcePortIdentity, sizeof(hdr->sourcePortIdentity));
sel = worst;
}
/*
* header and announce field of each Foreign Master are
* useful to run Best Master Clock Algorithm
*/
msg_copy_header(&ppi->frgn_master[i].hdr, hdr);
msg_unpack_announce(buf, &ppi->frgn_master[i].ann);
/* clear qualification timeouts */
for (i = 0; i < PP_FOREIGN_MASTER_TIME_WINDOW; i++)
frgn_master.ann_cnt[i] = 0;
/* This is the first one qualified 9.3.2.5 e)*/
frgn_master.ann_cnt[0] = 1;
/* Copy the temporary foreign master entry */
memcpy(&ppi->frgn_master[sel],
&frgn_master, sizeof(frgn_master));
pp_diag(ppi, bmc, 1, "New foreign Master %i added\n", i);
pp_diag(ppi, bmc, 1, "New foreign Master %i added\n", sel);
}
int pp_lib_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len)
{
__lib_add_foreign(ppi, buf);
ppi->next_state = bmc(ppi); /* got a new announce: run bmc */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
if (pp_hooks.handle_announce)
......
......@@ -20,8 +20,6 @@ void pp_servo_init(struct pp_instance *ppi)
int d;
SRV(ppi)->mpd_fltr.s_exp = 0; /* clears meanPathDelay filter */
ppi->frgn_rec_num = 0; /* no known master */
DSPAR(ppi)->parentPortIdentity.portNumber = 0; /* invalid */
if (ppi->t_ops->init_servo) {
/* The system may pre-set us to keep current frequency */
......
......@@ -16,7 +16,7 @@ static void init_parent_ds(struct pp_instance *ppi)
/* 8.2.3.2 */
DSPAR(ppi)->parentPortIdentity.clockIdentity =
DSDEF(ppi)->clockIdentity;
/* FIXME: portNumber ? */
DSPAR(ppi)->parentPortIdentity.portNumber = 0;
/* 8.2.3.3 skipped (parentStats is not used) */
/* 8.2.3.4 */
DSPAR(ppi)->observedParentOffsetScaledLogVariance = 0xffff;
......
......@@ -47,6 +47,10 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
/* upgrade from pre-master to master */
if (pre && pp_timeout(ppi, PP_TO_QUALIFICATION)) {
ppi->next_state = PPS_MASTER;
/* start sending imediately and reenter */
pp_timeout_clear(ppi, PP_TO_SYNC_SEND);
pp_timeout_clear(ppi, PP_TO_ANN_SEND);
ppi->next_delay = 0;
return 0;
}
......@@ -108,9 +112,13 @@ out:
break;
}
/* we also use TO_QUALIFICATION, but avoid counting it here */
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
if (pre) {
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_QUALIFICATION, PP_TO_REQUEST);
} else {
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
}
return e;
}
......@@ -22,6 +22,7 @@ struct timeout_config {
static struct timeout_config to_configs[__PP_TO_ARRAY_SIZE] = {
[PP_TO_REQUEST] = {"REQUEST", RAND_0_200,},
[PP_TO_SYNC_SEND] = {"SYNC_SEND", RAND_70_130,},
[PP_TO_BMC] = {"BMC", RAND_NONE,},
[PP_TO_ANN_RECEIPT] = {"ANN_RECEIPT", RAND_NONE,},
[PP_TO_ANN_SEND] = {"ANN_SEND", RAND_70_130,},
[PP_TO_FAULT] = {"FAULT", RAND_NONE, 4000},
......@@ -40,6 +41,7 @@ void pp_timeout_init(struct pp_instance *ppi)
to_configs[PP_TO_FAULT].value =
1 << (port->logMinDelayReqInterval + 12); /* 0 -> 4096ms */
to_configs[PP_TO_SYNC_SEND].value = port->logSyncInterval;
to_configs[PP_TO_BMC].value = 1000 * (1 << port->logAnnounceInterval);
to_configs[PP_TO_ANN_RECEIPT].value = 1000 * (
port->announceReceiptTimeout << port->logAnnounceInterval);
to_configs[PP_TO_ANN_SEND].value = port->logAnnounceInterval;
......@@ -54,6 +56,10 @@ void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec)
to_configs[index].name, millisec);
}
void pp_timeout_clear(struct pp_instance *ppi, int index)
{
__pp_timeout_set(ppi, index, 0);
}
void pp_timeout_set(struct pp_instance *ppi, int index)
{
......@@ -111,8 +117,11 @@ void pp_timeout_set(struct pp_instance *ppi, int index)
void pp_timeout_setall(struct pp_instance *ppi)
{
int i;
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++)
pp_timeout_set(ppi, i);
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++) {
/* keep BMC timeout */
if (i != PP_TO_BMC)
pp_timeout_set(ppi, i);
}
/* but announce_send must be send soon */
__pp_timeout_set(ppi, PP_TO_ANN_SEND, 20);
}
......
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