The PORTS_STATS_2_NP carries all the PORTS_STATS_NP RX/TX counters adding room for extra counters (up to 16 counters for RX and TX). Not all counters are filled yet.
The PORTS_STATS_2_NP TLV has the following definition: struct port_stats_2_np { struct PortIdentity portIdentity; // As PORT_STATS_NP struct PortStats stats; // As PORT_STATS_NP struct PortStats extraStats; // Extra room } PACKED; The proposed implementation adds the following counters: Offset Dir Description 0x00 RX Bad Message 0x01 RX Bad Protocol 0x02 RX Fail on Receive 0x03 RX Missing Timestamp 0x04 RX Announce from Foreign Masters (used by 1588-2019 Annex J) 0x05 RX Announce from current Master 0x02 TX Fail on Transmit 0x03 TX Missing Timestamp The counters are properly updated by runtime when required. --- ddt.h | 10 +++++ pmc.c | 115 +++++++++++++++++++++++++++++++------------------ pmc_common.c | 4 ++ port.c | 51 +++++++++++++++++----- port_private.h | 1 + tlv.c | 28 ++++++++++++ tlv.h | 7 +++ 7 files changed, 163 insertions(+), 53 deletions(-) diff --git a/ddt.h b/ddt.h index 5dc5530..1eadc29 100644 --- a/ddt.h +++ b/ddt.h @@ -107,6 +107,16 @@ struct PortStats { uint64_t txMsgType[MAX_MESSAGE_TYPES]; }; +#define EXTRA_STATS_RX_BAD_MESSAGE 0x00 +#define EXTRA_STATS_RX_BAD_PROTOCOL 0x01 +#define EXTRA_STATS_RX_FAIL_RECEIVE 0x02 +#define EXTRA_STATS_RX_MISSING_TIMESTAMP 0x03 +#define EXTRA_STATS_RX_ANNOUNCE_FOREIGN_MASTER 0x04 +#define EXTRA_STATS_RX_ANNOUNCE_CURRENT_MASTER 0x05 + +#define EXTRA_STATS_TX_FAIL_TRANSMIT 0x02 +#define EXTRA_STATS_TX_MISSING_TIMESTAMP 0x03 + struct PortServiceStats { uint64_t announce_timeout; uint64_t sync_timeout; diff --git a/pmc.c b/pmc.c index bc87058..05a717a 100644 --- a/pmc.c +++ b/pmc.c @@ -155,6 +155,53 @@ static void pmc_show_signaling(struct ptp_message *msg, FILE *fp) fflush(fp); } +static inline void pmc_show_stats(struct PortIdentity pid, struct PortStats stats, FILE *fp) +{ + fprintf(fp, + IFMT "portIdentity %s" + IFMT "rx_Sync %" PRIu64 + IFMT "rx_Delay_Req %" PRIu64 + IFMT "rx_Pdelay_Req %" PRIu64 + IFMT "rx_Pdelay_Resp %" PRIu64 + IFMT "rx_Follow_Up %" PRIu64 + IFMT "rx_Delay_Resp %" PRIu64 + IFMT "rx_Pdelay_Resp_Follow_Up %" PRIu64 + IFMT "rx_Announce %" PRIu64 + IFMT "rx_Signaling %" PRIu64 + IFMT "rx_Management %" PRIu64 + IFMT "tx_Sync %" PRIu64 + IFMT "tx_Delay_Req %" PRIu64 + IFMT "tx_Pdelay_Req %" PRIu64 + IFMT "tx_Pdelay_Resp %" PRIu64 + IFMT "tx_Follow_Up %" PRIu64 + IFMT "tx_Delay_Resp %" PRIu64 + IFMT "tx_Pdelay_Resp_Follow_Up %" PRIu64 + IFMT "tx_Announce %" PRIu64 + IFMT "tx_Signaling %" PRIu64 + IFMT "tx_Management %" PRIu64, + pid2str(&pid), + stats.rxMsgType[SYNC], + stats.rxMsgType[DELAY_REQ], + stats.rxMsgType[PDELAY_REQ], + stats.rxMsgType[PDELAY_RESP], + stats.rxMsgType[FOLLOW_UP], + stats.rxMsgType[DELAY_RESP], + stats.rxMsgType[PDELAY_RESP_FOLLOW_UP], + stats.rxMsgType[ANNOUNCE], + stats.rxMsgType[SIGNALING], + stats.rxMsgType[MANAGEMENT], + stats.txMsgType[SYNC], + stats.txMsgType[DELAY_REQ], + stats.txMsgType[PDELAY_REQ], + stats.txMsgType[PDELAY_RESP], + stats.txMsgType[FOLLOW_UP], + stats.txMsgType[DELAY_RESP], + stats.txMsgType[PDELAY_RESP_FOLLOW_UP], + stats.txMsgType[ANNOUNCE], + stats.txMsgType[SIGNALING], + stats.txMsgType[MANAGEMENT]); +} + static void pmc_show(struct ptp_message *msg, FILE *fp) { struct alternate_time_offset_properties *atop; @@ -168,6 +215,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) struct unicast_master_entry *ume; struct subscribe_events_np *sen; struct port_properties_np *ppn; + struct port_stats_2_np *ps2n; struct port_hwclock_np *phn; struct timePropertiesDS *tp; struct management_tlv *mgt; @@ -509,49 +557,8 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) break; case MID_PORT_STATS_NP: pcp = (struct port_stats_np *) mgt->data; - fprintf(fp, "PORT_STATS_NP " - IFMT "portIdentity %s" - IFMT "rx_Sync %" PRIu64 - IFMT "rx_Delay_Req %" PRIu64 - IFMT "rx_Pdelay_Req %" PRIu64 - IFMT "rx_Pdelay_Resp %" PRIu64 - IFMT "rx_Follow_Up %" PRIu64 - IFMT "rx_Delay_Resp %" PRIu64 - IFMT "rx_Pdelay_Resp_Follow_Up %" PRIu64 - IFMT "rx_Announce %" PRIu64 - IFMT "rx_Signaling %" PRIu64 - IFMT "rx_Management %" PRIu64 - IFMT "tx_Sync %" PRIu64 - IFMT "tx_Delay_Req %" PRIu64 - IFMT "tx_Pdelay_Req %" PRIu64 - IFMT "tx_Pdelay_Resp %" PRIu64 - IFMT "tx_Follow_Up %" PRIu64 - IFMT "tx_Delay_Resp %" PRIu64 - IFMT "tx_Pdelay_Resp_Follow_Up %" PRIu64 - IFMT "tx_Announce %" PRIu64 - IFMT "tx_Signaling %" PRIu64 - IFMT "tx_Management %" PRIu64, - pid2str(&pcp->portIdentity), - pcp->stats.rxMsgType[SYNC], - pcp->stats.rxMsgType[DELAY_REQ], - pcp->stats.rxMsgType[PDELAY_REQ], - pcp->stats.rxMsgType[PDELAY_RESP], - pcp->stats.rxMsgType[FOLLOW_UP], - pcp->stats.rxMsgType[DELAY_RESP], - pcp->stats.rxMsgType[PDELAY_RESP_FOLLOW_UP], - pcp->stats.rxMsgType[ANNOUNCE], - pcp->stats.rxMsgType[SIGNALING], - pcp->stats.rxMsgType[MANAGEMENT], - pcp->stats.txMsgType[SYNC], - pcp->stats.txMsgType[DELAY_REQ], - pcp->stats.txMsgType[PDELAY_REQ], - pcp->stats.txMsgType[PDELAY_RESP], - pcp->stats.txMsgType[FOLLOW_UP], - pcp->stats.txMsgType[DELAY_RESP], - pcp->stats.txMsgType[PDELAY_RESP_FOLLOW_UP], - pcp->stats.txMsgType[ANNOUNCE], - pcp->stats.txMsgType[SIGNALING], - pcp->stats.txMsgType[MANAGEMENT]); + fprintf(fp, "PORT_STATS_NP "); + pmc_show_stats(pcp->portIdentity, pcp->stats, fp); break; case MID_PORT_SERVICE_STATS_NP: pssp = (struct port_service_stats_np *) mgt->data; @@ -651,6 +658,28 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) fprintf(fp, "LOG_MIN_PDELAY_REQ_INTERVAL " IFMT "logMinPdelayReqInterval %hhd", mtd->val); break; + case MID_PORT_STATS_2_NP: + ps2n = (struct port_stats_2_np *) mgt->data; + fprintf(fp, "PORT_STATS_2_NP "); + pmc_show_stats(ps2n->portIdentity, ps2n->stats, fp); + fprintf(fp, + IFMT "rx_Bad_Message %" PRIu64 + IFMT "rx_Bad_Protocol %" PRIu64 + IFMT "rx_Fail %" PRIu64 + IFMT "rx_Missing_Timestamp %" PRIu64 + IFMT "rx_Announce_For_Master %" PRIu64 + IFMT "rx_Announce_Cur_Master %" PRIu64 + IFMT "tx_Fail %" PRIu64 + IFMT "tx_Missing_Timestamp %" PRIu64, + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_BAD_MESSAGE], + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_BAD_PROTOCOL], + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_FAIL_RECEIVE], + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_MISSING_TIMESTAMP], + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_ANNOUNCE_FOREIGN_MASTER], + ps2n->extraStats.rxMsgType[EXTRA_STATS_RX_ANNOUNCE_CURRENT_MASTER], + ps2n->extraStats.txMsgType[EXTRA_STATS_TX_FAIL_TRANSMIT], + ps2n->extraStats.txMsgType[EXTRA_STATS_TX_MISSING_TIMESTAMP]); + break; } out: fprintf(fp, "\n"); diff --git a/pmc_common.c b/pmc_common.c index 9e251c4..77b2cd2 100644 --- a/pmc_common.c +++ b/pmc_common.c @@ -156,6 +156,7 @@ struct management_id idtab[] = { { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, do_get_action }, { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, { "POWER_PROFILE_SETTINGS_NP", MID_POWER_PROFILE_SETTINGS_NP, do_set_action }, + { "PORT_STATS_2_NP", MID_PORT_STATS_2_NP, do_get_action }, }; static void do_get_action(struct pmc *pmc, int action, int index, char *str) @@ -675,6 +676,9 @@ static int pmc_tlv_datalen(struct pmc *pmc, int id) case MID_LOG_MIN_PDELAY_REQ_INTERVAL: len += sizeof(struct management_tlv_datum); break; + case MID_PORT_STATS_2_NP: + len += sizeof(struct port_stats_2_np); + break; } return len + len % 2; } diff --git a/port.c b/port.c index 5803cd3..7a03da5 100644 --- a/port.c +++ b/port.c @@ -203,6 +203,26 @@ static int port_unicast_message_valid(struct port *p, struct ptp_message *m) return 1; } +static void port_stats_inc_rx(struct port *p, const struct ptp_message *msg) +{ + p->stats.rxMsgType[msg_type(msg)]++; +} + +static void port_stats_inc_tx(struct port *p, const struct ptp_message *msg) +{ + p->stats.txMsgType[msg_type(msg)]++; +} + +static void port_extra_stats_inc_rx(struct port *p, int type) +{ + p->extra_stats.rxMsgType[type]++; +} + +static void port_extra_stats_inc_tx(struct port *p, int type) +{ + p->extra_stats.txMsgType[type]++; +} + int source_pid_eq(struct ptp_message *m1, struct ptp_message *m2) { return pid_eq(&m1->header.sourcePortIdentity, @@ -381,6 +401,8 @@ static int add_foreign_master(struct port *p, struct ptp_message *m) struct ptp_message *tmp; int broke_threshold = 0, diff = 0; + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_ANNOUNCE_FOREIGN_MASTER); + LIST_FOREACH(fc, &p->foreign_masters, list) { if (msg_source_equal(m, fc)) { break; @@ -663,16 +685,6 @@ static int path_trace_ignore(struct port *p, struct ptp_message *m) return 0; } -static void port_stats_inc_rx(struct port *p, const struct ptp_message *msg) -{ - p->stats.rxMsgType[msg_type(msg)]++; -} - -static void port_stats_inc_tx(struct port *p, const struct ptp_message *msg) -{ - p->stats.txMsgType[msg_type(msg)]++; -} - static int peer_prepare_and_send(struct port *p, struct ptp_message *msg, enum transport_event event) { @@ -886,6 +898,7 @@ static int port_management_fill_response(struct port *target, struct unicast_master_entry *ume; struct clock_description *desc; struct port_properties_np *ppn; + struct port_stats_2_np *ps2n; struct port_hwclock_np *phn; struct management_tlv *tlv; struct port_stats_np *psn; @@ -1129,6 +1142,13 @@ static int port_management_fill_response(struct port *target, memcpy(pwr, &target->pwr, sizeof(*pwr)); datalen = sizeof(*pwr); break; + case MID_PORT_STATS_2_NP: + ps2n = (struct port_stats_2_np *)tlv->data; + ps2n->portIdentity = target->portIdentity; + ps2n->stats = target->stats; + ps2n->extraStats = target->extra_stats; + datalen = sizeof(*ps2n); + break; default: /* The caller should *not* respond to this message. */ tlv_extra_recycle(extra); @@ -1558,6 +1578,7 @@ static int port_pdelay_request(struct port *p) goto out; } if (msg_sots_missing(msg)) { + port_extra_stats_inc_tx(p, EXTRA_STATS_TX_MISSING_TIMESTAMP); pr_err("missing timestamp on transmitted peer delay request"); goto out; } @@ -1620,6 +1641,7 @@ int port_delay_request(struct port *p) goto out; } if (msg_sots_missing(msg)) { + port_extra_stats_inc_tx(p, EXTRA_STATS_TX_MISSING_TIMESTAMP); pr_err("missing timestamp on transmitted delay request"); goto out; } @@ -1759,6 +1781,7 @@ int port_tx_sync(struct port *p, struct address *dst, uint16_t sequence_id) if (p->timestamping == TS_ONESTEP || p->timestamping == TS_P2P1STEP) { goto out; } else if (msg_sots_missing(msg)) { + port_extra_stats_inc_tx(p, EXTRA_STATS_TX_MISSING_TIMESTAMP); pr_err("missing timestamp on transmitted sync"); err = -1; goto out; @@ -2025,6 +2048,8 @@ static int update_current_master(struct port *p, struct ptp_message *m) if (!msg_source_equal(m, fc)) return add_foreign_master(p, m); + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_ANNOUNCE_CURRENT_MASTER); + if (p->state != PS_PASSIVE) { tds.currentUtcOffset = m->announce.currentUtcOffset; tds.flags = m->header.flagField[1]; @@ -2345,6 +2370,7 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) if (p->timestamping == TS_P2P1STEP) { goto out; } else if (msg_sots_missing(rsp)) { + port_extra_stats_inc_tx(p, EXTRA_STATS_TX_MISSING_TIMESTAMP); pr_err("missing timestamp on transmitted peer delay response"); err = -1; goto out; @@ -2957,6 +2983,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index) cnt = transport_recv(p->trp, fd, msg); if (cnt < 0) { + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_FAIL_RECEIVE); pr_err("%s: recv message failed", p->log_name); msg_put(msg); return EV_FAULT_DETECTED; @@ -2965,9 +2992,11 @@ static enum fsm_event bc_event(struct port *p, int fd_index) if (err) { switch (err) { case -EBADMSG: + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_BAD_MESSAGE); pr_err("%s: bad message", p->log_name); break; case -EPROTO: + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_BAD_PROTOCOL); pr_debug("%s: ignoring message", p->log_name); break; } @@ -2983,6 +3012,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index) !(p->timestamping == TS_P2P1STEP && msg_type(msg) == PDELAY_REQ)) { pr_err("%s: received %s without timestamp", p->log_name, msg_type_string(msg_type(msg))); + port_extra_stats_inc_rx(p, EXTRA_STATS_RX_MISSING_TIMESTAMP); msg_put(msg); return EV_NONE; } @@ -3076,6 +3106,7 @@ int port_prepare_and_send(struct port *p, struct ptp_message *msg, cnt = transport_send(p->trp, &p->fda, event, msg); } if (cnt <= 0) { + port_extra_stats_inc_tx(p, EXTRA_STATS_TX_FAIL_TRANSMIT); return -1; } port_stats_inc_tx(p, msg); diff --git a/port_private.h b/port_private.h index 3b02d2f..8825b3c 100644 --- a/port_private.h +++ b/port_private.h @@ -149,6 +149,7 @@ struct port { bool iface_rate_tlv; Integer64 portAsymmetry; struct PortStats stats; + struct PortStats extra_stats; struct PortServiceStats service_stats; /* foreignMasterDS */ LIST_HEAD(fm, foreign_clock) foreign_masters; diff --git a/tlv.c b/tlv.c index 9b82bd9..e4d720f 100644 --- a/tlv.c +++ b/tlv.c @@ -174,6 +174,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, struct unicast_master_entry *ume; struct subscribe_events_np *sen; struct port_properties_np *ppn; + struct port_stats_2_np *ps2n; struct port_hwclock_np *phn; struct timePropertiesDS *tp; struct time_status_np *tsn; @@ -490,6 +491,21 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, if (data_len != 0) goto bad_length; break; + case MID_PORT_STATS_2_NP: + if (data_len < sizeof(struct port_stats_2_np)) + goto bad_length; + ps2n = (struct port_stats_2_np *)m->data; + ps2n->portIdentity.portNumber = + ntohs(ps2n->portIdentity.portNumber); + for (i = 0 ; i < MAX_MESSAGE_TYPES; i++) { + ps2n->stats.rxMsgType[i] = __le64_to_cpu(ps2n->stats.rxMsgType[i]); + ps2n->stats.txMsgType[i] = __le64_to_cpu(ps2n->stats.txMsgType[i]); + ps2n->extraStats.rxMsgType[i] = __le64_to_cpu(ps2n->extraStats.rxMsgType[i]); + ps2n->extraStats.txMsgType[i] = __le64_to_cpu(ps2n->extraStats.txMsgType[i]); + } + extra_len = sizeof(struct port_stats_2_np); + break; + } if (extra_len) { if (extra_len % 2) @@ -513,6 +529,7 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) struct unicast_master_entry *ume; struct subscribe_events_np *sen; struct port_properties_np *ppn; + struct port_stats_2_np *ps2n; struct port_hwclock_np *phn; struct timePropertiesDS *tp; struct time_status_np *tsn; @@ -672,6 +689,17 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) HTONL(pwr->networkTimeInaccuracy); HTONL(pwr->totalTimeInaccuracy); break; + case MID_PORT_STATS_2_NP: + ps2n = (struct port_stats_2_np *)m->data; + ps2n->portIdentity.portNumber = + htons(ps2n->portIdentity.portNumber); + for (i = 0 ; i < MAX_MESSAGE_TYPES; i++) { + ps2n->stats.rxMsgType[i] = __cpu_to_le64(ps2n->stats.rxMsgType[i]); + ps2n->stats.txMsgType[i] = __cpu_to_le64(ps2n->stats.txMsgType[i]); + ps2n->extraStats.rxMsgType[i] = __cpu_to_le64(ps2n->extraStats.rxMsgType[i]); + ps2n->extraStats.txMsgType[i] = __cpu_to_le64(ps2n->extraStats.txMsgType[i]); + } + break; } } diff --git a/tlv.h b/tlv.h index 8b51ffd..33ecd26 100644 --- a/tlv.h +++ b/tlv.h @@ -129,6 +129,7 @@ enum management_action { #define MID_UNICAST_MASTER_TABLE_NP 0xC008 #define MID_PORT_HWCLOCK_NP 0xC009 #define MID_POWER_PROFILE_SETTINGS_NP 0xC00A +#define MID_PORT_STATS_2_NP 0xC00B /* Management error ID values */ #define MID_RESPONSE_TOO_BIG 0x0001 @@ -426,6 +427,12 @@ struct port_stats_np { struct PortStats stats; } PACKED; +struct port_stats_2_np { + struct PortIdentity portIdentity; + struct PortStats stats; + struct PortStats extraStats; +} PACKED; + struct port_service_stats_np { struct PortIdentity portIdentity; struct PortServiceStats stats; -- 2.42.0 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel