Skip to content

Commit

Permalink
TrafficMaker の処理共通化 (#21)
Browse files Browse the repository at this point in the history
* ITrafficMaker から AbstractTrafficMaker に改名
* TrafficMaker の Make を共通化
  • Loading branch information
idofront authored Nov 29, 2024
1 parent dfe95fb commit e0007e8
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 221 deletions.
8 changes: 4 additions & 4 deletions main/TrafficPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int main(int argc, char *argv[])

auto queuePtr = std::make_shared<ThreadSafeQueue<TrafficRecord>>();

auto trafficMakerPtr = std::shared_ptr<TrafficMaker::ITrafficMaker>(nullptr);
auto trafficMakerPtr = std::shared_ptr<TrafficMaker::AbstractTrafficMaker>(nullptr);
if (options.Mode() == Mode::Throughput)
{
spdlog::info("Mode: Throughput");
Expand All @@ -44,7 +44,7 @@ int main(int argc, char *argv[])
{
spdlog::info("Mode: SpeedScale");
trafficMakerPtr =
std::make_shared<TrafficMaker::SpeedScaleRepalyTrafficMaker>(pcapFile, options.SpeedScaleFactor());
std::make_shared<TrafficMaker::SpeedScaleReplayTrafficMaker>(pcapFile, options.SpeedScaleFactor());
}
else if (options.Mode() == Mode::Duration)
{
Expand Down Expand Up @@ -86,12 +86,12 @@ int main(int argc, char *argv[])
}
if (repeatCount > 1)
{
spdlog::debug("Cycle: {}/{}", repeat, repeatCount);
spdlog::trace("Cycle: {}/{}", repeat, repeatCount);
}
}
else
{
spdlog::debug("Cycle: {}", repeat);
spdlog::trace("Cycle: {}", repeat);
}

std::for_each(trafficRecords.begin(), trafficRecords.end(),
Expand Down
115 changes: 115 additions & 0 deletions src/TrafficMaker/AbstractTrafficMaker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include <TrafficMaker/AbstractTrafficMaker.hpp>
#include <spdlog/spdlog.h>

namespace TrafficMaker
{
AbstractTrafficMaker::AbstractTrafficMaker(const std::filesystem::path &path) : _path(path)
{
}

AbstractTrafficMaker::~AbstractTrafficMaker()
{
}

std::filesystem::path AbstractTrafficMaker::Path() const
{
return _path;
}

std::vector<PcapRecord> AbstractTrafficMaker::ReadPcapFile(const std::filesystem::path &path)
{
auto pcapRecords = std::vector<PcapRecord>();

auto pcap = pcap_open_offline(path.c_str(), NULL);
if (pcap == NULL)
{
throw std::runtime_error("Failed to open pcap file");
}

struct pcap_pkthdr header;
const u_char *packet;
while ((packet = pcap_next(pcap, &header)) != NULL)
{
std::vector<uint8_t> data(packet, packet + header.len);
auto record = PcapRecord(header, data);
pcapRecords.push_back(record);
}

pcap_close(pcap);

return pcapRecords;
}

std::vector<std::chrono::nanoseconds> AbstractTrafficMaker::NormalizeTimestamps(
const std::vector<std::chrono::nanoseconds> &records, double speedScaleFactor)
{
auto normalizedTimestamps = std::vector<std::chrono::nanoseconds>();
std::transform(records.begin(), records.end(), std::back_inserter(normalizedTimestamps),
[speedScaleFactor](const std::chrono::nanoseconds &timestamp) {
return std::chrono::nanoseconds(static_cast<long long>(timestamp.count() / speedScaleFactor));
});
return normalizedTimestamps;
}

std::vector<std::chrono::nanoseconds> AbstractTrafficMaker::RelativizeTimestamps(
const std::vector<std::chrono::nanoseconds> &timestamps)
{
if (timestamps.empty())
{
return {};
}

auto relativeTimestamps = std::vector<std::chrono::nanoseconds>{std::chrono::nanoseconds(0)};
relativeTimestamps.reserve(timestamps.size());
for (auto i = 1; i < timestamps.size(); i++)
{
relativeTimestamps.push_back(timestamps[i] - timestamps[i - 1]);
}
return relativeTimestamps;
}

std::vector<TrafficRecord> AbstractTrafficMaker::Make()
{
auto pcapRecords = ReadPcapFile(Path());
auto speedScaleFactor = CalculateSpeedScaleFactor(pcapRecords);
return MakeTrafficRecords(pcapRecords, speedScaleFactor);
}
std::vector<TrafficRecord> AbstractTrafficMaker::MakeTrafficRecords(const std::vector<PcapRecord> &pcapRecords,
const double speedScaleFactor)
{
spdlog::debug("Speed scale factor: {}", speedScaleFactor);

auto trafficRecords = std::vector<TrafficRecord>();

auto nsecTimestamps = std::vector<std::chrono::nanoseconds>();
std::transform(pcapRecords.begin(), pcapRecords.end(), std::back_inserter(nsecTimestamps),
[](const PcapRecord &record) {
auto nsec = (uint64_t)(record.Ts().tv_sec * 1e9 + record.Ts().tv_usec * 1e3);
return std::chrono::nanoseconds(nsec);
});

auto relativizedTimestamps = RelativizeTimestamps(nsecTimestamps);
auto normalizedTimestamps = NormalizeTimestamps(relativizedTimestamps, speedScaleFactor);

for (auto i = 0; i < pcapRecords.size(); i++)
{
auto record = pcapRecords[i];
auto timestamp = normalizedTimestamps[i];
auto trafficRecord = TrafficRecord(record.Data(), timestamp);
trafficRecords.push_back(trafficRecord);
}

return trafficRecords;
}

std::vector<std::chrono::nanoseconds> AbstractTrafficMaker::GetTimestamps(std::vector<PcapRecord> pcapRecords)
{
auto nsecTimestamps = std::vector<std::chrono::nanoseconds>();
std::transform(pcapRecords.begin(), pcapRecords.end(), std::back_inserter(nsecTimestamps),
[](const PcapRecord &record) {
auto nsec = static_cast<uint64_t>(record.Ts().tv_sec * 1e9 + record.Ts().tv_usec * 1e3);
return std::chrono::nanoseconds(nsec);
});
return nsecTimestamps;
}
} // namespace TrafficMaker
36 changes: 36 additions & 0 deletions src/TrafficMaker/AbstractTrafficMaker.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef TRAFFIC_MAKER__ABSTRACT_TRAFFIC_MAKER_HPP
#define TRAFFIC_MAKER__ABSTRACT_TRAFFIC_MAKER_HPP

#include <TrafficMaker/PcapRecord.hpp>
#include <TrafficRecord.hpp>
#include <filesystem>
#include <pcap.h>
#include <vector>

namespace TrafficMaker
{
class AbstractTrafficMaker
{
public:
AbstractTrafficMaker(const std::filesystem::path &path);
virtual ~AbstractTrafficMaker() = 0;
virtual std::vector<TrafficRecord> Make();

protected:
std::filesystem::path Path() const;
virtual std::vector<PcapRecord> ReadPcapFile(const std::filesystem::path &path) final;
virtual double CalculateSpeedScaleFactor(const std::vector<PcapRecord> &pcapRecords) = 0;
static std::vector<std::chrono::nanoseconds> NormalizeTimestamps(
const std::vector<std::chrono::nanoseconds> &records, double speedScaleFactor);
static std::vector<std::chrono::nanoseconds> RelativizeTimestamps(
const std::vector<std::chrono::nanoseconds> &timestamps);
static std::vector<TrafficRecord> MakeTrafficRecords(const std::vector<PcapRecord> &pcapRecords,
const double speedScaleFactor);
static std::vector<std::chrono::nanoseconds> GetTimestamps(std::vector<PcapRecord> pcapRecords);

private:
std::filesystem::path _path;
};
} // namespace TrafficMaker

#endif
43 changes: 8 additions & 35 deletions src/TrafficMaker/CustomDurationReplayTrafficMaker.cpp
Original file line number Diff line number Diff line change
@@ -1,50 +1,23 @@
#include <TrafficMaker/CustomDurationReplayTrafficMaker.hpp>
#include <algorithm>
#include <numeric>
#include <spdlog/spdlog.h>

namespace TrafficMaker
{

CustomDurationReplayTrafficMaker::CustomDurationReplayTrafficMaker(const std::string &pcapFilePath,
std::chrono::milliseconds durationTime)
: ITrafficMaker(pcapFilePath), _DurationTime(durationTime)
: AbstractTrafficMaker(pcapFilePath), _DurationTime(durationTime)
{
}

std::vector<TrafficRecord> CustomDurationReplayTrafficMaker::Make()
double CustomDurationReplayTrafficMaker::CalculateSpeedScaleFactor(const std::vector<PcapRecord> &pcapRecords)
{
auto pcapRecords = ReadPcapFile(Path());
auto trafficRecords = std::vector<TrafficRecord>();
auto durationTime = _DurationTime;
auto timestamps = GetTimestamps(pcapRecords);
auto maxTimestamp = *std::max_element(timestamps.begin(), timestamps.end());
auto minTimestamp = *std::min_element(timestamps.begin(), timestamps.end());
auto durationAsNsec = std::chrono::duration_cast<std::chrono::nanoseconds>(_DurationTime);
auto speedScaleFactor = (maxTimestamp - minTimestamp).count() / static_cast<double>(durationAsNsec.count());

auto usecTimestamps = std::vector<uint64_t>();
std::transform(pcapRecords.begin(), pcapRecords.end(), std::back_inserter(usecTimestamps),
[](const PcapRecord &record) { return record.Ts().tv_sec * 1e6 + record.Ts().tv_usec; });

auto maxTimestamp = *std::max_element(usecTimestamps.begin(), usecTimestamps.end());
auto minTimestamp = *std::min_element(usecTimestamps.begin(), usecTimestamps.end());
auto durationAsUsec = durationTime.count() * 1e3;
auto speedScaleFactor = (maxTimestamp - minTimestamp) / durationAsUsec;

for (auto i = 0; i < pcapRecords.size(); i++)
{
auto targetRecord = pcapRecords[i];
auto targetUsecTimestamp = targetRecord.Ts().tv_sec * 1e6 + targetRecord.Ts().tv_usec;
auto scaledTargetUsecTimestamp = targetUsecTimestamp / speedScaleFactor;
auto nextUsecTimeStamp = (i + 1 < pcapRecords.size())
? pcapRecords[i + 1].Ts().tv_sec * 1e6 + pcapRecords[i + 1].Ts().tv_usec
: maxTimestamp;
auto scaledNextUsecTimestamp = nextUsecTimeStamp / speedScaleFactor;

auto scaledChronoNano = std::chrono::nanoseconds(
static_cast<long long>((scaledNextUsecTimestamp - scaledTargetUsecTimestamp) * 1e3));

auto trafficRecord = TrafficRecord(targetRecord.Data(), scaledChronoNano);
trafficRecords.push_back(trafficRecord);
}

return trafficRecords;
return speedScaleFactor;
}

} // namespace TrafficMaker
9 changes: 5 additions & 4 deletions src/TrafficMaker/CustomDurationReplayTrafficMaker.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#ifndef TRAFFIC_MAKER__CUSTOM_DURATION_REPLAY_TRAFFIC_MAKER_HPP
#define TRAFFIC_MAKER__CUSTOM_DURATION_REPLAY_TRAFFIC_MAKER_HPP

#include <TrafficMaker/ITrafficMaker.hpp>
#include <chrono>
#include <TrafficMaker/AbstractTrafficMaker.hpp>

namespace TrafficMaker
{
class CustomDurationReplayTrafficMaker : public ITrafficMaker
class CustomDurationReplayTrafficMaker : public AbstractTrafficMaker
{
public:
CustomDurationReplayTrafficMaker(const std::string &pcapFilePath, std::chrono::milliseconds durationTime);
std::vector<TrafficRecord> Make() override;

protected:
double CalculateSpeedScaleFactor(const std::vector<PcapRecord> &pcapRecords) override;

private:
std::chrono::milliseconds _DurationTime;
Expand Down
41 changes: 0 additions & 41 deletions src/TrafficMaker/ITrafficMaker.cpp

This file was deleted.

28 changes: 0 additions & 28 deletions src/TrafficMaker/ITrafficMaker.hpp

This file was deleted.

43 changes: 9 additions & 34 deletions src/TrafficMaker/PacketsPerSecondTrafficMaker.cpp
Original file line number Diff line number Diff line change
@@ -1,50 +1,25 @@
#include <TrafficMaker/PacketsPerSecondTrafficMaker.hpp>
#include <spdlog/spdlog.h>

namespace TrafficMaker
{
PacketsPerSecondTrafficMaker::PacketsPerSecondTrafficMaker(std::string pcapFilePath, double packetsPerSecond)
: ITrafficMaker(pcapFilePath), _PacketsPerSecond(packetsPerSecond)
: AbstractTrafficMaker(pcapFilePath), _PacketsPerSecond(packetsPerSecond)
{
}

std::vector<TrafficRecord> PacketsPerSecondTrafficMaker::Make()
double PacketsPerSecondTrafficMaker::CalculateSpeedScaleFactor(const std::vector<PcapRecord> &pcapRecords)
{
auto pcapRecords = ReadPcapFile(Path());
auto trafficRecords = std::vector<TrafficRecord>();
auto packetsPerSecond = _PacketsPerSecond;

auto usecTimestamps = std::vector<uint64_t>();
std::transform(pcapRecords.begin(), pcapRecords.end(), std::back_inserter(usecTimestamps),
[](const PcapRecord &record) { return record.Ts().tv_sec * 1e6 + record.Ts().tv_usec; });
auto timestamps = GetTimestamps(pcapRecords);
auto maxTimestamp = *std::max_element(timestamps.begin(), timestamps.end());
auto minTimestamp = *std::min_element(timestamps.begin(), timestamps.end());

auto maxTimestamp = *std::max_element(usecTimestamps.begin(), usecTimestamps.end());
auto minTimestamp = *std::min_element(usecTimestamps.begin(), usecTimestamps.end());
auto packetNumber = pcapRecords.size();
auto actualDuration = (maxTimestamp - minTimestamp) / 1e6;
auto expectedDuration = packetNumber / packetsPerSecond;
auto speedScaleFactor = actualDuration / expectedDuration;
auto actualDuration = maxTimestamp - minTimestamp;
auto expectedDuration = (packetNumber / packetsPerSecond) * 1e9;
auto speedScaleFactor = actualDuration.count() / expectedDuration;

spdlog::info("Actual duration: {} usec, Expected duration: {} usec, Speed scale factor: {}", actualDuration,
expectedDuration, speedScaleFactor);

for (auto i = 0; i < pcapRecords.size(); i++)
{
auto targetRecord = pcapRecords[i];
auto targetUsecTimestamp = targetRecord.Ts().tv_sec * 1e6 + targetRecord.Ts().tv_usec;
auto scaledTargetUsecTimestamp = targetUsecTimestamp / speedScaleFactor;
auto nextUsecTimeStamp = (i + 1 < pcapRecords.size())
? pcapRecords[i + 1].Ts().tv_sec * 1e6 + pcapRecords[i + 1].Ts().tv_usec
: maxTimestamp;
auto scaledNextUsecTimestamp = nextUsecTimeStamp / speedScaleFactor;

auto scaledChronoNano = std::chrono::nanoseconds(
static_cast<long long>((scaledNextUsecTimestamp - scaledTargetUsecTimestamp) * 1e3));

auto trafficRecord = TrafficRecord(targetRecord.Data(), scaledChronoNano);
trafficRecords.push_back(trafficRecord);
}

return trafficRecords;
return speedScaleFactor;
}
} // namespace TrafficMaker
Loading

0 comments on commit e0007e8

Please sign in to comment.