diff --git a/common/abstractprotocol.cpp b/common/abstractprotocol.cpp index 8ff9529..333bd51 100644 --- a/common/abstractprotocol.cpp +++ b/common/abstractprotocol.cpp @@ -882,9 +882,19 @@ quint64 AbstractProtocol::gcd(quint64 u, quint64 v) quint64 AbstractProtocol::lcm(quint64 u, quint64 v) { - /* FIXME: LCM(0,x) := x */ +#if 0 + /* LCM(0,x) := x */ if (u == 0 || v == 0) return u | v; +#else + /* For our use case, neither u nor v can ever be 0, the minimum + value is 1; we do this correction silently here */ + if (u == 0) u = 1; + if (v == 0) v = 1; + + if (u == 1 || v == 1) + return (u * v); +#endif return (u * v)/gcd(u, v); } diff --git a/server/abstractport.cpp b/server/abstractport.cpp index 3bf9148..e186227 100644 --- a/server/abstractport.cpp +++ b/server/abstractport.cpp @@ -152,14 +152,18 @@ void AbstractPort::updatePacketListSequential() { if (streamList_[i]->isEnabled()) { - long n, x, y; - long burstSize; + int len; + ulong n, x, y; + ulong burstSize; double ibg = 0; - long ibg1 = 0, ibg2 = 0; - long nb1 = 0, nb2 = 0; + quint64 ibg1 = 0, ibg2 = 0; + quint64 nb1 = 0, nb2 = 0; double ipg = 0; - long ipg1 = 0, ipg2 = 0; - long np1 = 0, np2 = 0; + quint64 ipg1 = 0, ipg2 = 0; + quint64 npx1 = 0, npx2 = 0; + quint64 npy1 = 0, npy2 = 0; + quint64 loopDelay; + ulong frameVariableCount = streamList_[i]->frameVariableCount(); // We derive n, x, y such that // n * x + y = total number of packets to be sent @@ -168,32 +172,37 @@ void AbstractPort::updatePacketListSequential() { case OstProto::StreamControl::e_su_bursts: burstSize = streamList_[i]->burstSize(); - x = AbstractProtocol::lcm(streamList_[i]->frameVariableCount(), - burstSize); - n = ulong(burstSize * streamList_[i]->burstRate()) / x; - y = ulong(burstSize * streamList_[i]->burstRate()) % x; + x = AbstractProtocol::lcm(frameVariableCount, burstSize); + n = ulong(burstSize * streamList_[i]->burstRate() + * streamList_[i]->numBursts()) / x; + y = ulong(burstSize * streamList_[i]->burstRate() + * streamList_[i]->numBursts()) % x; if (streamList_[i]->burstRate() > 0) { ibg = 1e9/double(streamList_[i]->burstRate()); - ibg1 = long(ceil(ibg)); - ibg2 = long(floor(ibg)); - nb1 = long((ibg - double(ibg2)) * double(x)); + ibg1 = quint64(ceil(ibg)); + ibg2 = quint64(floor(ibg)); + nb1 = quint64((ibg - double(ibg2)) * double(x)); nb2 = x - nb1; } + loopDelay = ibg2; break; case OstProto::StreamControl::e_su_packets: - x = streamList_[i]->frameVariableCount(); + x = frameVariableCount; n = streamList_[i]->numPackets() / x; y = streamList_[i]->numPackets() % x; burstSize = x + y; if (streamList_[i]->packetRate() > 0) { ipg = 1e9/double(streamList_[i]->packetRate()); - ipg1 = long(ceil(ipg)); - ipg2 = long(floor(ipg)); - np1 = long((ipg - double(ipg2)) * double(x)); - np2 = x - np1; + ipg1 = quint64(ceil(ipg)); + ipg2 = quint64(floor(ipg)); + npx1 = quint64((ipg - double(ipg2)) * double(x)); + npx2 = x - npx1; + npy1 = quint64((ipg - double(ipg2)) * double(y)); + npy2 = y - npy1; } + loopDelay = ipg2; break; default: qWarning("Unhandled stream control unit %d", @@ -201,25 +210,37 @@ void AbstractPort::updatePacketListSequential() continue; } - qDebug("\nframeVariableCount = %d", - streamList_[i]->frameVariableCount()); - qDebug("n = %ld, x = %ld, y = %ld, burstSize = %ld", + qDebug("\nframeVariableCount = %lu", frameVariableCount); + qDebug("n = %lu, x = %lu, y = %lu, burstSize = %lu", n, x, y, burstSize); - qDebug("ibg = %g, ibg1/nb1 = %ld/%ld ibg2/nb2 = %ld/%ld", - ibg, ibg1, nb1, ibg2, nb2); - qDebug("ipg = %g, ipg1/np1 = %ld/%ld ipg2/np2 = %ld/%ld\n", - ipg, ipg1, np1, ipg2, np2); + + qDebug("ibg = %g", ibg); + qDebug("ibg1 = %" PRIu64, ibg1); + qDebug("nb1 = %" PRIu64, nb1); + qDebug("ibg2 = %" PRIu64, ibg2); + qDebug("nb2 = %" PRIu64 "\n", nb2); + + qDebug("ipg = %g", ipg); + qDebug("ipg1 = %" PRIu64, ipg1); + qDebug("npx1 = %" PRIu64, npx1); + qDebug("npy1 = %" PRIu64, npy1); + qDebug("ipg2 = %" PRIu64, ipg2); + qDebug("npx2 = %" PRIu64, npx2); + qDebug("npy2 = %" PRIu64 "\n", npy2); if (n > 1) - loopNextPacketSet(x, n); + loopNextPacketSet(x, n, 0, loopDelay); else if (n == 0) x = 0; - for (int j = 0; j < (x+y); j++) + for (uint j = 0; j < (x+y); j++) { - int len; - len = streamList_[i]->frameValue(pktBuf_, sizeof(pktBuf_), j); + if (j == 0 || frameVariableCount > 1) + { + len = streamList_[i]->frameValue( + pktBuf_, sizeof(pktBuf_), j); + } if (len <= 0) continue; @@ -228,10 +249,10 @@ void AbstractPort::updatePacketListSequential() appendToPacketList(sec, nsec, pktBuf_, len); - if ((j % burstSize) == 0) + if ((j > 0) && (((j+1) % burstSize) == 0)) { nsec += (j < nb1) ? ibg1 : ibg2; - while (nsec >= 1e9) + while (nsec >= long(1e9)) { sec++; nsec -= long(1e9); @@ -239,8 +260,12 @@ void AbstractPort::updatePacketListSequential() } else { - nsec += (j < np1) ? ipg1 : ipg2; - while (nsec >= 1e9) + if (j < x) + nsec += (j < npx1) ? ipg1 : ipg2; + else + nsec += ((j-x) < npy1) ? ipg1 : ipg2; + + while (nsec >= long(1e9)) { sec++; nsec -= long(1e9); diff --git a/server/abstractport.h b/server/abstractport.h index 3d0f3ce..f848f17 100644 --- a/server/abstractport.h +++ b/server/abstractport.h @@ -71,7 +71,8 @@ public: void setDirty() { isSendQueueDirty_ = true; } virtual void clearPacketList() = 0; - virtual void loopNextPacketSet(qint64 size, qint64 repeats) = 0; + virtual void loopNextPacketSet(qint64 size, qint64 repeats, + long repeatDelaySec, long repeatDelayNsec) = 0; virtual bool appendToPacketList(long sec, long nsec, const uchar *packet, int length) = 0; virtual void setPacketListLoopMode(bool loop, diff --git a/server/pcapport.cpp b/server/pcapport.cpp index 8a82b1c..3f38ed2 100644 --- a/server/pcapport.cpp +++ b/server/pcapport.cpp @@ -301,10 +301,13 @@ void PcapPort::PortTransmitter::clearPacketList() setPacketListLoopMode(false, 0, 0); } -void PcapPort::PortTransmitter::loopNextPacketSet(qint64 size, qint64 repeats) +void PcapPort::PortTransmitter::loopNextPacketSet(qint64 size, qint64 repeats, + long repeatDelaySec, long repeatDelayNsec) { currentPacketSequence_ = new PacketSequence; currentPacketSequence_->repeatCount_ = repeats; + currentPacketSequence_->usecDelay_ = repeatDelaySec * long(1e6) + + repeatDelayNsec/1000; repeatSequenceStart_ = packetSequenceList_.size(); repeatSize_ = size; @@ -328,7 +331,7 @@ bool PcapPort::PortTransmitter::appendToPacketList(long sec, long nsec, { // Add a zero len packet at end of currentSendQueue_ for // inter-sendQ timing - if (packetSequenceList_.size()) + if (currentPacketSequence_ != NULL) { pcap_pkthdr hdr = pktHdr; hdr.caplen = 0; @@ -360,8 +363,16 @@ bool PcapPort::PortTransmitter::appendToPacketList(long sec, long nsec, // Set the packetSequence repeatSize Q_ASSERT(repeatSequenceStart_ >= 0); Q_ASSERT(repeatSequenceStart_ < packetSequenceList_.size()); - packetSequenceList_[repeatSequenceStart_]->repeatSize_ = - packetSequenceList_.size() - repeatSequenceStart_; + + if (currentPacketSequence_ != packetSequenceList_[repeatSequenceStart_]) + { + PacketSequence *start = packetSequenceList_[repeatSequenceStart_]; + + currentPacketSequence_->usecDelay_ = start->usecDelay_; + start->usecDelay_ = 0; + start->repeatSize_ = + packetSequenceList_.size() - repeatSequenceStart_; + } repeatSize_ = 0; @@ -413,9 +424,10 @@ void PcapPort::PortTransmitter::run() return; for(i = 0; i < packetSequenceList_.size(); i++) { - qDebug("sendQ[%d]: rptCnt = %d, rptSz = %d", i, + qDebug("sendQ[%d]: rptCnt = %d, rptSz = %d usecDelay = %ld", i, packetSequenceList_.at(i)->repeatCount_, - packetSequenceList_.at(i)->repeatSize_); + packetSequenceList_.at(i)->repeatSize_, + packetSequenceList_.at(i)->usecDelay_); } for(i = 0; i < packetSequenceList_.size(); i++) @@ -433,7 +445,19 @@ _restart: packetSequenceList_.at(i+k)->sendQueue_, overHead, kSyncTransmit); - if (ret < 0) + if (ret >= 0) + { + long usecs = packetSequenceList_.at(i+k)->usecDelay_ + + overHead; + if (usecs) + { + udelay(usecs); + overHead = 0; + } + else + overHead = usecs; + } + else { qDebug("error %d in sendQueueTransmit()", ret); qDebug("overHead = %ld", overHead); diff --git a/server/pcapport.h b/server/pcapport.h index f046670..30f10bf 100644 --- a/server/pcapport.h +++ b/server/pcapport.h @@ -42,8 +42,10 @@ public: transmitter_->clearPacketList(); setPacketListLoopMode(false, 0, 0); } - virtual void loopNextPacketSet(qint64 size, qint64 repeats) { - transmitter_->loopNextPacketSet(size, repeats); + virtual void loopNextPacketSet(qint64 size, qint64 repeats, + long repeatDelaySec, long repeatDelayNsec) { + transmitter_->loopNextPacketSet(size, repeats, + repeatDelaySec, repeatDelayNsec); } virtual bool appendToPacketList(long sec, long nsec, const uchar *packet, int length) { @@ -99,7 +101,8 @@ protected: PortTransmitter(const char *device); ~PortTransmitter(); void clearPacketList(); - void loopNextPacketSet(qint64 size, qint64 repeats); + void loopNextPacketSet(qint64 size, qint64 repeats, + long repeatDelaySec, long repeatDelayNsec); bool appendToPacketList(long sec, long usec, const uchar *packet, int length); void setPacketListLoopMode(bool loop, long secDelay, long nsecDelay) { @@ -119,6 +122,7 @@ protected: sendQueue_ = pcap_sendqueue_alloc(1*1024*1024); repeatCount_ = 1; repeatSize_ = 1; + usecDelay_ = 0; } ~PacketSequence() { pcap_sendqueue_destroy(sendQueue_); @@ -132,6 +136,7 @@ protected: pcap_send_queue *sendQueue_; int repeatCount_; int repeatSize_; + long usecDelay_; }; void udelay(long usec);