ostinato/server/pcaptransmitter.cpp
Srivats P c70811eaa4 Fix spurious stream stats drops
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
2023-02-08 16:34:03 +05:30

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();
}