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:
parent
e138fa0d3d
commit
bafdd948f8
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user