Make win32 specific changes for per-stream latency

There are 2 changes -
1. Encode txPort in ttag packets and use it at TxTtagStats and
RxPcapStats to identify Tx and Rx packets respectively
2. Don't use pcap_sendqueue_transmit() if stream timing is in use -
since we can't modify TTAG packets inside that API
This commit is contained in:
Srivats P 2023-05-06 13:15:37 +05:30
parent e138fa0d3d
commit bafdd948f8
6 changed files with 58 additions and 3 deletions

View File

@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "sign.h" #include "sign.h"
#include "../common/streambase.h"
SignProtocol::SignProtocol(StreamBase *stream, AbstractProtocol *parent) SignProtocol::SignProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent) : AbstractProtocol(stream, parent)
{ {
@ -76,6 +78,7 @@ AbstractProtocol::FieldFlags SignProtocol::fieldFlags(int index) const
switch (index) switch (index)
{ {
case sign_magic: case sign_magic:
case sign_tlv_tx_port:
case sign_tlv_guid: case sign_tlv_guid:
case sign_tlv_ttag: case sign_tlv_ttag:
case sign_tlv_end: case sign_tlv_end:
@ -140,6 +143,29 @@ QVariant SignProtocol::fieldData(int index, FieldAttrib attrib,
} }
break; break;
} }
case sign_tlv_tx_port:
{
switch(attrib)
{
case FieldName:
return QString("TxPort");
case FieldValue:
return mpStream->portId();
case FieldTextValue:
return QString("%1").arg(mpStream->portId());
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
fv[0] = mpStream->portId() & 0xFF;
fv[1] = kTypeLenTxPort;
return fv;
}
default:
break;
}
break;
}
case sign_tlv_guid: case sign_tlv_guid:
{ {
quint32 guid = data.stream_guid() & 0xFFFFFF; quint32 guid = data.stream_guid() & 0xFFFFFF;
@ -258,6 +284,8 @@ bool SignProtocol::packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint
ret = true; ret = true;
} else if (*p == kTypeLenGuid) { } else if (*p == kTypeLenGuid) {
*guid = qFromBigEndian<quint32>(p - 3) >> 8; *guid = qFromBigEndian<quint32>(p - 3) >> 8;
} else if (*p == kTypeLenTxPort) {
*ttagId |= uint(*(p - 1)) << 8;
} }
p -= 1 + (*p >> 5); // move to next TLV p -= 1 + (*p >> 5); // move to next TLV
} }

View File

@ -46,6 +46,7 @@ TLVs are encoded as
Type = 1, Len = 3 (0x61): Stream GUID Type = 1, Len = 3 (0x61): Stream GUID
Type = 2, Len = 1 (0x22): T-Tag Placeholder (0 value) Type = 2, Len = 1 (0x22): T-Tag Placeholder (0 value)
Type = 3, Len = 1 (0x23): T-Tag with actual value Type = 3, Len = 1 (0x23): T-Tag with actual value
Type = 4, Len = 1 (0x24): Tx Port Id
*/ */
class SignProtocol : public AbstractProtocol class SignProtocol : public AbstractProtocol
@ -55,6 +56,7 @@ public:
{ {
// Frame Fields // Frame Fields
sign_tlv_end = 0, sign_tlv_end = 0,
sign_tlv_tx_port,
sign_tlv_guid, sign_tlv_guid,
sign_tlv_ttag, sign_tlv_ttag,
sign_magic, sign_magic,
@ -100,6 +102,7 @@ private:
static const quint32 kSignMagic = 0x1d10c0da; // coda! (unicode - 0x1d10c) static const quint32 kSignMagic = 0x1d10c0da; // coda! (unicode - 0x1d10c)
static const quint8 kTypeLenEnd = 0x00; static const quint8 kTypeLenEnd = 0x00;
static const quint8 kTypeLenGuid = 0x61; static const quint8 kTypeLenGuid = 0x61;
static const quint8 kTypeLenTxPort = 0x24;
OstProto::Sign data; OstProto::Sign data;
}; };

View File

@ -75,9 +75,8 @@ public:
quint32 id() const; quint32 id() const;
bool setId(quint32 id); bool setId(quint32 id);
quint32 portId() { return portId_;}
#if 0 // FIXME(HI): needed? #if 0 // FIXME(HI): needed?
quint32 portId()
{ return mCore->port_id();}
bool setPortId(quint32 id) bool setPortId(quint32 id)
{ mCore->set_port_id(id); return true;} { mCore->set_port_id(id); return true;}
#endif #endif

View File

@ -123,11 +123,27 @@ _skip_filter:
switch (ret) { switch (ret) {
case 1: { case 1: {
uint ttagId, guid; uint ttagId, guid;
#ifdef Q_OS_WIN32
// Npcap (Windows) doesn't support direction, so packets
// Tx by PcapTxThread are received back by us here - use
// TxPort to filter out. TxPort is returned as byte 1 of
// ttagId (byte 0 is ttagId).
// If TxPort is us ==> Tx Packet, so skip
// FIXME: remove once npcap supports pcap direction
if (SignProtocol::packetTtagId(data, hdr->caplen, &ttagId, &guid)
&& (ttagId >> 8 != uint(portId_))) {
ttagId &= 0xFF;
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId_,
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);
}
#else
if (SignProtocol::packetTtagId(data, hdr->caplen, &ttagId, &guid)) { if (SignProtocol::packetTtagId(data, hdr->caplen, &ttagId, &guid)) {
timing_->recordRxTime(portId_, guid, ttagId, hdr->ts); timing_->recordRxTime(portId_, guid, ttagId, hdr->ts);
timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId_, timingDebug("[%d RX] %ld:%ld ttag %u guid %u", portId_,
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid); hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);
} }
#endif
if (guid != SignProtocol::kInvalidGuid) { if (guid != SignProtocol::kInvalidGuid) {
streamStats_[guid].rx_pkts++; streamStats_[guid].rx_pkts++;
streamStats_[guid].rx_bytes += hdr->caplen; streamStats_[guid].rx_bytes += hdr->caplen;

View File

@ -329,7 +329,9 @@ _restart:
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
TimeStamp ovrStart, ovrEnd; TimeStamp ovrStart, ovrEnd;
if (seq->usecDuration_ <= long(1e6)) { // 1s // Use Windows-only pcap_sendqueue_transmit() if duration < 1s
// and no stream timing is configured
if (seq->usecDuration_ <= long(1e6) && firstTtagPkt_ < 0) {
getTimeStamp(&ovrStart); getTimeStamp(&ovrStart);
ret = pcap_sendqueue_transmit(handle_, ret = pcap_sendqueue_transmit(handle_,
seq->sendQueue_, kSyncTransmit); seq->sendQueue_, kSyncTransmit);

View File

@ -107,6 +107,13 @@ _skip_filter:
uint guid; uint guid;
if (SignProtocol::packetTtagId(data, hdr->caplen, if (SignProtocol::packetTtagId(data, hdr->caplen,
&ttagId, &guid)) { &ttagId, &guid)) {
#ifdef Q_OS_WIN32
// TxPort is NOT us ==> Rx Packet, so skip
// See similar check in PcapRxStats for details
if (ttagId >> 8 != uint(portId_))
break;
ttagId &= 0xFF;
#endif
timing_->recordTxTime(portId_, guid, ttagId, hdr->ts); timing_->recordTxTime(portId_, guid, ttagId, hdr->ts);
timingDebug("[%d TX] %ld:%ld ttag %u guid %u", portId_, timingDebug("[%d TX] %ld:%ld ttag %u guid %u", portId_,
hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid); hdr->ts.tv_sec, long(hdr->ts.tv_usec), ttagId, guid);