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

Reply via email to