c70811eaa4
The problem happens for bidirectional flows. The sequence of events is as follows when you start Tx on Ports p1, p2 with the current code - 1. Clear stream stats on p1 2. Start tx on p1 3. Clear stream stats on p2 4. Start tx on p2 By the time #3 is executed, it may have already rx packets from p1 which are being incorrectly cleared, this will cause these number of packets to show up as dropped instead - incorrectly. The fix is to change the order like this - 1. Clear stream stats on p1 2. Clear stream stats on p2 3. Start tx on p1 4. Start tx on p2 Unidirectional flows will not see this problem - as long as startTx is done only on the Tx port and not the Rx port. This bug is a regression caused due to the code changes introduced for the stream stats rates feature implemented in 1.2.0
139 lines
3.6 KiB
C++
139 lines
3.6 KiB
C++
/*
|
|
Copyright (C) 2010-2016 Srivats P.
|
|
|
|
This file is part of "Ostinato"
|
|
|
|
This is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
#include "pcaptransmitter.h"
|
|
|
|
PcapTransmitter::PcapTransmitter(
|
|
const char *device,
|
|
StreamStats &portStreamStats)
|
|
: streamStats_(portStreamStats), txThread_(device)
|
|
{
|
|
adjustRxStreamStats_ = false;
|
|
txStats_.setObjectName(QString("TxStats:%1").arg(device));
|
|
memset(&stats_, 0, sizeof(stats_));
|
|
txStats_.setTxThreadStats(&stats_);
|
|
txStats_.start(); // TODO: alongwith user transmit start
|
|
|
|
txThread_.setStats(&stats_);
|
|
connect(&txThread_, SIGNAL(finished()), SLOT(updateTxThreadStreamStats()));
|
|
}
|
|
|
|
PcapTransmitter::~PcapTransmitter()
|
|
{
|
|
txStats_.stop(); // TODO: alongwith user transmit stop
|
|
}
|
|
|
|
bool PcapTransmitter::setRateAccuracy(
|
|
AbstractPort::Accuracy accuracy)
|
|
{
|
|
return txThread_.setRateAccuracy(accuracy);
|
|
}
|
|
|
|
void PcapTransmitter::adjustRxStreamStats(bool enable)
|
|
{
|
|
adjustRxStreamStats_ = enable;
|
|
}
|
|
|
|
bool PcapTransmitter::setStreamStatsTracking(bool enable)
|
|
{
|
|
return txThread_.setStreamStatsTracking(enable);
|
|
}
|
|
|
|
void PcapTransmitter::clearPacketList()
|
|
{
|
|
txThread_.clearPacketList();
|
|
}
|
|
|
|
void PcapTransmitter::loopNextPacketSet(
|
|
qint64 size,
|
|
qint64 repeats,
|
|
long repeatDelaySec,
|
|
long repeatDelayNsec)
|
|
{
|
|
txThread_.loopNextPacketSet(size, repeats, repeatDelaySec, repeatDelayNsec);
|
|
}
|
|
|
|
bool PcapTransmitter::appendToPacketList(long sec, long nsec,
|
|
const uchar *packet, int length)
|
|
{
|
|
return txThread_.appendToPacketList(sec, nsec, packet, length);
|
|
}
|
|
|
|
void PcapTransmitter::setHandle(pcap_t *handle)
|
|
{
|
|
txThread_.setHandle(handle);
|
|
}
|
|
|
|
void PcapTransmitter::setPacketListLoopMode(
|
|
bool loop,
|
|
quint64 secDelay,
|
|
quint64 nsecDelay)
|
|
{
|
|
txThread_.setPacketListLoopMode(loop, secDelay, nsecDelay);
|
|
}
|
|
|
|
void PcapTransmitter::useExternalStats(AbstractPort::PortStats *stats)
|
|
{
|
|
txStats_.useExternalStats(stats);
|
|
}
|
|
|
|
void PcapTransmitter::start()
|
|
{
|
|
txThread_.start();
|
|
}
|
|
|
|
void PcapTransmitter::stop()
|
|
{
|
|
txThread_.stop();
|
|
}
|
|
|
|
bool PcapTransmitter::isRunning()
|
|
{
|
|
return txThread_.isRunning();
|
|
}
|
|
double PcapTransmitter::lastTxDuration()
|
|
{
|
|
return txThread_.lastTxDuration();
|
|
}
|
|
|
|
void PcapTransmitter::updateTxThreadStreamStats()
|
|
{
|
|
PcapTxThread *txThread = dynamic_cast<PcapTxThread*>(sender());
|
|
const StreamStats& threadStreamStats = txThread->streamStats();
|
|
StreamStatsIterator i(threadStreamStats);
|
|
|
|
while (i.hasNext())
|
|
{
|
|
i.next();
|
|
uint guid = i.key();
|
|
StreamStatsTuple sst = i.value();
|
|
|
|
streamStats_[guid].tx_pkts += sst.tx_pkts;
|
|
streamStats_[guid].tx_bytes += sst.tx_bytes;
|
|
if (adjustRxStreamStats_) {
|
|
// XXX: rx_pkts counting may lag behind tx_pkts, so stream stats
|
|
// may become negative after adjustment transiently. But this
|
|
// should fix itself once all the rx pkts come in
|
|
streamStats_[guid].rx_pkts -= sst.tx_pkts;
|
|
streamStats_[guid].rx_bytes -= sst.tx_bytes;
|
|
}
|
|
}
|
|
txThread->clearStreamStats();
|
|
}
|