Code changes to improve transmit performance in Windows. Windows top-speed performance is now at par with Linux in my tests, however for fixed (high) rate transmit, accuracy is not good - need to find ways to improve that.
Fixes issue 33 Fixes issue 39
This commit is contained in:
parent
e9ea3d7934
commit
626ca8ad0e
@ -44,6 +44,7 @@ AbstractPort::AbstractPort(int id, const char *device)
|
|||||||
|
|
||||||
isSendQueueDirty_ = false;
|
isSendQueueDirty_ = false;
|
||||||
linkState_ = OstProto::LinkStateUnknown;
|
linkState_ = OstProto::LinkStateUnknown;
|
||||||
|
minPacketSetSize_ = 1;
|
||||||
|
|
||||||
memset((void*) &stats_, 0, sizeof(stats_));
|
memset((void*) &stats_, 0, sizeof(stats_));
|
||||||
resetStats();
|
resetStats();
|
||||||
@ -138,7 +139,6 @@ void AbstractPort::updatePacketList()
|
|||||||
|
|
||||||
void AbstractPort::updatePacketListSequential()
|
void AbstractPort::updatePacketListSequential()
|
||||||
{
|
{
|
||||||
const int kMinLoopSize = 16;
|
|
||||||
long sec = 0;
|
long sec = 0;
|
||||||
long nsec = 0;
|
long nsec = 0;
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ void AbstractPort::updatePacketListSequential()
|
|||||||
case OstProto::StreamControl::e_su_packets:
|
case OstProto::StreamControl::e_su_packets:
|
||||||
x = frameVariableCount;
|
x = frameVariableCount;
|
||||||
n = 2;
|
n = 2;
|
||||||
while (x < kMinLoopSize)
|
while (x < minPacketSetSize_)
|
||||||
x = frameVariableCount*n++;
|
x = frameVariableCount*n++;
|
||||||
n = streamList_[i]->numPackets() / x;
|
n = streamList_[i]->numPackets() / x;
|
||||||
y = streamList_[i]->numPackets() % x;
|
y = streamList_[i]->numPackets() % x;
|
||||||
|
@ -98,6 +98,7 @@ protected:
|
|||||||
bool isUsable_;
|
bool isUsable_;
|
||||||
OstProto::Port data_;
|
OstProto::Port data_;
|
||||||
OstProto::LinkState linkState_;
|
OstProto::LinkState linkState_;
|
||||||
|
ulong minPacketSetSize_;
|
||||||
|
|
||||||
struct PortStats stats_;
|
struct PortStats stats_;
|
||||||
//! \todo Need lock for stats access/update
|
//! \todo Need lock for stats access/update
|
||||||
|
@ -42,6 +42,7 @@ LinuxPort::LinuxPort(int id, const char *device)
|
|||||||
monitor_ = new StatsMonitor();
|
monitor_ = new StatsMonitor();
|
||||||
|
|
||||||
data_.set_is_exclusive_control(hasExclusiveControl());
|
data_.set_is_exclusive_control(hasExclusiveControl());
|
||||||
|
minPacketSetSize_ = 16;
|
||||||
|
|
||||||
qDebug("adding dev to all ports list <%s>", device);
|
qDebug("adding dev to all ports list <%s>", device);
|
||||||
allPorts_.append(this);
|
allPorts_.append(this);
|
||||||
|
@ -49,6 +49,25 @@ static long inline udiffTimeStamp(const TimeStamp *start, const TimeStamp *end)
|
|||||||
|
|
||||||
return usecs;
|
return usecs;
|
||||||
}
|
}
|
||||||
|
#elif defined(Q_OS_WIN32)
|
||||||
|
static quint64 gTicksFreq;
|
||||||
|
typedef LARGE_INTEGER TimeStamp;
|
||||||
|
static void inline getTimeStamp(TimeStamp* stamp)
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter(stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long inline udiffTimeStamp(const TimeStamp *start, const TimeStamp *end)
|
||||||
|
{
|
||||||
|
if (end->QuadPart > start->QuadPart)
|
||||||
|
return (end->QuadPart - start->QuadPart)*long(1e6)/gTicksFreq;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FIXME: incorrect! what's the max value for this counter before
|
||||||
|
// it rolls over?
|
||||||
|
return (start->QuadPart)*long(1e6)/gTicksFreq;
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
typedef int TimeStamp;
|
typedef int TimeStamp;
|
||||||
static void inline getTimeStamp(TimeStamp*) {}
|
static void inline getTimeStamp(TimeStamp*) {}
|
||||||
@ -256,7 +275,7 @@ PcapPort::PortTransmitter::PortTransmitter(const char *device)
|
|||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
LARGE_INTEGER freq;
|
LARGE_INTEGER freq;
|
||||||
if (QueryPerformanceFrequency(&freq))
|
if (QueryPerformanceFrequency(&freq))
|
||||||
ticksFreq_ = freq.QuadPart;
|
gTicksFreq = ticksFreq_ = freq.QuadPart;
|
||||||
else
|
else
|
||||||
Q_ASSERT_X(false, "PortTransmitter::PortTransmitter",
|
Q_ASSERT_X(false, "PortTransmitter::PortTransmitter",
|
||||||
"This Win32 platform does not support performance counter");
|
"This Win32 platform does not support performance counter");
|
||||||
@ -331,15 +350,18 @@ bool PcapPort::PortTransmitter::appendToPacketList(long sec, long nsec,
|
|||||||
if (currentPacketSequence_ == NULL ||
|
if (currentPacketSequence_ == NULL ||
|
||||||
!currentPacketSequence_->hasFreeSpace(2*sizeof(pcap_pkthdr)+length))
|
!currentPacketSequence_->hasFreeSpace(2*sizeof(pcap_pkthdr)+length))
|
||||||
{
|
{
|
||||||
// Add a zero len packet at end of currentSendQueue_ for
|
|
||||||
// inter-sendQ timing
|
|
||||||
if (currentPacketSequence_ != NULL)
|
if (currentPacketSequence_ != NULL)
|
||||||
{
|
{
|
||||||
pcap_pkthdr hdr = pktHdr;
|
long usecs;
|
||||||
hdr.caplen = 0;
|
|
||||||
pcap_sendqueue_queue(packetSequenceList_.last()->sendQueue_,
|
usecs = (pktHdr.ts.tv_sec
|
||||||
&hdr, (u_char*)packet);
|
- currentPacketSequence_->lastPacket_->ts.tv_sec)
|
||||||
|
* long(1e6);
|
||||||
|
usecs += (pktHdr.ts.tv_usec
|
||||||
|
- currentPacketSequence_->lastPacket_->ts.tv_usec);
|
||||||
|
currentPacketSequence_->usecDelay_ = usecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \todo (LOW): calculate sendqueue size
|
//! \todo (LOW): calculate sendqueue size
|
||||||
currentPacketSequence_ = new PacketSequence;
|
currentPacketSequence_ = new PacketSequence;
|
||||||
|
|
||||||
@ -350,8 +372,7 @@ bool PcapPort::PortTransmitter::appendToPacketList(long sec, long nsec,
|
|||||||
sizeof(pcap_pkthdr) + length));
|
sizeof(pcap_pkthdr) + length));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcap_sendqueue_queue(currentPacketSequence_->sendQueue_, &pktHdr,
|
if (currentPacketSequence_->appendPacket(&pktHdr, (u_char*) packet) < 0)
|
||||||
(u_char*) packet) < 0)
|
|
||||||
{
|
{
|
||||||
op = false;
|
op = false;
|
||||||
}
|
}
|
||||||
@ -419,17 +440,20 @@ void PcapPort::PortTransmitter::run()
|
|||||||
|
|
||||||
const int kSyncTransmit = 1;
|
const int kSyncTransmit = 1;
|
||||||
int i;
|
int i;
|
||||||
long overHead = 0;
|
long overHead = 0; // overHead should be negative or zero
|
||||||
|
|
||||||
qDebug("packetSequenceList_.size = %d", packetSequenceList_.size());
|
qDebug("packetSequenceList_.size = %d", packetSequenceList_.size());
|
||||||
if (packetSequenceList_.size() <= 0)
|
if (packetSequenceList_.size() <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(i = 0; i < packetSequenceList_.size(); i++) {
|
for(i = 0; i < packetSequenceList_.size(); i++) {
|
||||||
qDebug("sendQ[%d]: rptCnt = %d, rptSz = %d usecDelay = %ld", i,
|
qDebug("sendQ[%d]: rptCnt = %d, rptSz = %d, usecDelay = %ld", i,
|
||||||
packetSequenceList_.at(i)->repeatCount_,
|
packetSequenceList_.at(i)->repeatCount_,
|
||||||
packetSequenceList_.at(i)->repeatSize_,
|
packetSequenceList_.at(i)->repeatSize_,
|
||||||
packetSequenceList_.at(i)->usecDelay_);
|
packetSequenceList_.at(i)->usecDelay_);
|
||||||
|
qDebug("sendQ[%d]: pkts = %ld, usecDuration = %ld", i,
|
||||||
|
packetSequenceList_.at(i)->packets_,
|
||||||
|
packetSequenceList_.at(i)->usecDuration_);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < packetSequenceList_.size(); i++)
|
for(i = 0; i < packetSequenceList_.size(); i++)
|
||||||
@ -443,14 +467,41 @@ _restart:
|
|||||||
{
|
{
|
||||||
for (int k = 0; k < rptSz; k++)
|
for (int k = 0; k < rptSz; k++)
|
||||||
{
|
{
|
||||||
int ret = sendQueueTransmit(handle_,
|
int ret;
|
||||||
packetSequenceList_.at(i+k)->sendQueue_,
|
PacketSequence *seq = packetSequenceList_.at(i+k);
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
TimeStamp ovrStart, ovrEnd;
|
||||||
|
|
||||||
|
if (seq->usecDuration_ <= long(1e6)) // 1s
|
||||||
|
{
|
||||||
|
getTimeStamp(&ovrStart);
|
||||||
|
ret = pcap_sendqueue_transmit(handle_,
|
||||||
|
seq->sendQueue_, kSyncTransmit);
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
stats_->txPkts += seq->packets_;
|
||||||
|
stats_->txBytes += seq->bytes_;
|
||||||
|
|
||||||
|
getTimeStamp(&ovrEnd);
|
||||||
|
overHead += seq->usecDuration_
|
||||||
|
- udiffTimeStamp(&ovrStart, &ovrEnd);
|
||||||
|
}
|
||||||
|
if (stop_)
|
||||||
|
ret = -2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = sendQueueTransmit(handle_, seq->sendQueue_,
|
||||||
overHead, kSyncTransmit);
|
overHead, kSyncTransmit);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ret = sendQueueTransmit(handle_, seq->sendQueue_,
|
||||||
|
overHead, kSyncTransmit);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
long usecs = packetSequenceList_.at(i+k)->usecDelay_
|
long usecs = seq->usecDelay_ + overHead;
|
||||||
+ overHead;
|
|
||||||
if (usecs > 0)
|
if (usecs > 0)
|
||||||
{
|
{
|
||||||
udelay(usecs);
|
udelay(usecs);
|
||||||
@ -530,14 +581,11 @@ int PcapPort::PortTransmitter::sendQueueTransmit(pcap_t *p,
|
|||||||
getTimeStamp(&ovrStart);
|
getTimeStamp(&ovrStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pktLen of size 0 is used at the end of a sendQueue and before
|
Q_ASSERT(pktLen > 0);
|
||||||
// the next sendQueue - i.e. for inter sendQueue timing
|
|
||||||
if(pktLen > 0)
|
pcap_sendpacket(p, pkt, pktLen);
|
||||||
{
|
stats_->txPkts++;
|
||||||
pcap_sendpacket(p, pkt, pktLen);
|
stats_->txBytes += pktLen;
|
||||||
stats_->txPkts++;
|
|
||||||
stats_->txBytes += pktLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step to the next packet in the buffer
|
// Step to the next packet in the buffer
|
||||||
hdr = (struct pcap_pkthdr*) (pkt + pktLen);
|
hdr = (struct pcap_pkthdr*) (pkt + pktLen);
|
||||||
|
@ -120,6 +120,10 @@ protected:
|
|||||||
public:
|
public:
|
||||||
PacketSequence() {
|
PacketSequence() {
|
||||||
sendQueue_ = pcap_sendqueue_alloc(1*1024*1024);
|
sendQueue_ = pcap_sendqueue_alloc(1*1024*1024);
|
||||||
|
lastPacket_ = NULL;
|
||||||
|
packets_ = 0;
|
||||||
|
bytes_ = 0;
|
||||||
|
usecDuration_ = 0;
|
||||||
repeatCount_ = 1;
|
repeatCount_ = 1;
|
||||||
repeatSize_ = 1;
|
repeatSize_ = 1;
|
||||||
usecDelay_ = 0;
|
usecDelay_ = 0;
|
||||||
@ -133,7 +137,26 @@ protected:
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int appendPacket(const struct pcap_pkthdr *pktHeader,
|
||||||
|
const uchar *pktData) {
|
||||||
|
if (lastPacket_)
|
||||||
|
{
|
||||||
|
usecDuration_ += (pktHeader->ts.tv_sec
|
||||||
|
- lastPacket_->ts.tv_sec) * long(1e6);
|
||||||
|
usecDuration_ += (pktHeader->ts.tv_usec
|
||||||
|
- lastPacket_->ts.tv_usec);
|
||||||
|
}
|
||||||
|
packets_++;
|
||||||
|
bytes_ += pktHeader->caplen;
|
||||||
|
lastPacket_ = (struct pcap_pkthdr *)
|
||||||
|
(sendQueue_->buffer + sendQueue_->len);
|
||||||
|
return pcap_sendqueue_queue(sendQueue_, pktHeader, pktData);
|
||||||
|
}
|
||||||
pcap_send_queue *sendQueue_;
|
pcap_send_queue *sendQueue_;
|
||||||
|
struct pcap_pkthdr *lastPacket_;
|
||||||
|
long packets_;
|
||||||
|
long bytes_;
|
||||||
|
ulong usecDuration_;
|
||||||
int repeatCount_;
|
int repeatCount_;
|
||||||
int repeatSize_;
|
int repeatSize_;
|
||||||
long usecDelay_;
|
long usecDelay_;
|
||||||
|
@ -44,6 +44,7 @@ WinPcapPort::WinPcapPort(int id, const char *device)
|
|||||||
qFatal("failed to alloc oidData");
|
qFatal("failed to alloc oidData");
|
||||||
|
|
||||||
data_.set_is_exclusive_control(hasExclusiveControl());
|
data_.set_is_exclusive_control(hasExclusiveControl());
|
||||||
|
minPacketSetSize_ = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
WinPcapPort::~WinPcapPort()
|
WinPcapPort::~WinPcapPort()
|
||||||
|
Loading…
Reference in New Issue
Block a user