NcpBase: Counter for out of order received spinel frames (#1210)

- Adds a new NCP counter to indicate the number of times the
  received `tid` in spinel frames jumps by more than 1. This is
  intended to track dropped (inbound) spinel frames.
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 4ae2768..00cebef 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -478,6 +478,7 @@
 #endif
     mDroppedReplyTid(0),
     mDroppedReplyTidBitSet(0),
+    mNextExpectedTid(0),
     mAllowLocalNetworkDataChange(false),
     mRequireJoinExistingNetwork(false),
     mIsRawStreamEnabled(false),
@@ -485,6 +486,7 @@
 
     mFramingErrorCounter(0),
     mRxSpinelFrameCounter(0),
+    mRxSpinelOutOfOrderTidCounter(0),
     mTxSpinelFrameCounter(0),
     mInboundSecureIpFrameCounter(0),
     mInboundInsecureIpFrameCounter(0),
@@ -930,10 +932,19 @@
     spinel_tid_t tid = 0;
 
     parsedLength = spinel_datatype_unpack(buf, bufLength, "CiD", &header, &command, &arg_ptr, &arg_len);
+    tid = SPINEL_HEADER_GET_TID(header);
 
     if (parsedLength == bufLength)
     {
         errorCode = HandleCommand(header, command, arg_ptr, static_cast<uint16_t>(arg_len));
+
+        // Check if we may have missed a `tid` in the sequence.
+        if ((mNextExpectedTid != 0) && (tid != mNextExpectedTid))
+        {
+            mRxSpinelOutOfOrderTidCounter++;
+        }
+
+        mNextExpectedTid = SPINEL_GET_NEXT_TID(tid);
     }
     else
     {
@@ -954,8 +965,6 @@
         // `mDroppedReplyTid` (with value zero indicating that there
         // is no dropped reply).
 
-        tid = SPINEL_HEADER_GET_TID(header);
-
         if (tid != 0)
         {
             if (mDroppedReplyTid == 0)
@@ -2795,6 +2804,10 @@
         value = mRxSpinelFrameCounter;
         break;
 
+    case SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID:
+        value = mRxSpinelOutOfOrderTidCounter;
+        break;
+
     case SPINEL_PROP_CNTR_RX_SPINEL_ERR:
         value = mFramingErrorCounter;
         break;
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index df4e5bc..d0079aa 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -519,6 +519,8 @@
 
     uint16_t mDroppedReplyTidBitSet;
 
+    spinel_tid_t mNextExpectedTid;
+
     bool mAllowLocalNetworkDataChange;
     bool mRequireJoinExistingNetwork;
     bool mIsRawStreamEnabled;
@@ -526,6 +528,7 @@
 
     uint32_t mFramingErrorCounter;             // Number of improperly formed received spinel frames.
     uint32_t mRxSpinelFrameCounter;            // Number of received (inbound) spinel frames.
+    uint32_t mRxSpinelOutOfOrderTidCounter;    // Number of out of order received spinel frames (tid increase > 1).
     uint32_t mTxSpinelFrameCounter;            // Number of sent (outbound) spinel frames.
     uint32_t mInboundSecureIpFrameCounter;     // Number of secure inbound data/IP frames.
     uint32_t mInboundInsecureIpFrameCounter;   // Number of insecure inbound data/IP frames.
diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h
index 5932b84..faabbb8 100644
--- a/src/ncp/spinel.h
+++ b/src/ncp/spinel.h
@@ -1019,7 +1019,10 @@
     /** Format: `L` (Read-only) */
     SPINEL_PROP_CNTR_RX_SPINEL_ERR     = SPINEL_PROP_CNTR__BEGIN + 302,
 
-
+    /// Number of out of order received spinel frames (tid increase by more than 1).
+    /** Format: `L` (Read-only) */
+    SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID
+                                       = SPINEL_PROP_CNTR__BEGIN + 303,
 
     /// The message buffer counter info
     /** Format: `T(SSSSSSSSSSSSSSSS)` (Read-only)