Last active
January 16, 2020 13:06
-
-
Save pchaigno/d180eb5de5cc31e0596761b2bfb80c97 to your computer and use it in GitHub Desktop.
A MoonGen script that attemps to achieve the highest throughput supported by DUT while minimizing packet losses.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local mg = require "moongen" | |
local lm = require "libmoon" | |
local memory = require "memory" | |
local device = require "device" | |
local stats = require "stats" | |
local limiter = require "software-ratecontrol" | |
local pcap = require "pcap" | |
function configure(parser) | |
parser:description("Attemps to achieve the highest throughput supported by DUT while minimizing packet losses.") | |
parser:argument("dev", "Device to transmit/receive from."):convert(tonumber) | |
parser:option("-r --rate", "Transmit rate in Mbit/s."):default(0.2):convert(tonumber) | |
parser:option("-f --file", "Filename of pcap.") | |
parser:option("-c --cores", "Nb of cores"):default(1):convert(tonumber) | |
end | |
function master(args) | |
local dev = device.config({port = args.dev, rxQueues = args.cores, txQueues = args.cores}) | |
device.waitForLinks() | |
for i = 0, args.cores - 1, 1 do | |
local queue = dev:getTxQueue(i) | |
local rateLimiter = limiter:new(queue, "custom", 1 / args.rate * 1000) | |
if args.file then | |
mg.startTask("pcapSlave", queue, args.rate, rateLimiter, dev, i == 0, args.file) | |
else | |
mg.startTask("loadSlave", queue, args.rate, rateLimiter, dev, i == 0) | |
end | |
end | |
mg.startTask("counterSlave", dev:getRxQueue(0)) | |
mg.waitForTasks() | |
end | |
function pcapSlave(queue, rate, rateLimiter, dev, displayStats, file) | |
local pcapFile = pcap:newReader(file) | |
local mem = memory.createMemPool() | |
local bufs = mem:bufArray(128) | |
local linkSpeed = dev:getLinkStatus().speed | |
local txCtr = stats:newDevTxCounter(dev, "plain") | |
local rxCtr = stats:newDevRxCounter(dev, "plain") | |
local lastTs = 0 | |
while mg.running() do | |
local n = pcapFile:read(bufs) | |
if n == 0 then | |
pcapFile:reset() | |
else | |
for i = 1, n do | |
local buf = bufs[i] | |
buf:setDelay(rate * linkSpeed / 8) | |
end | |
rateLimiter:sendN(bufs, n) | |
if displayStats then | |
txCtr:update() | |
rxCtr:update() | |
end | |
tx = txCtr.mpps[#txCtr.mpps] | |
rx = rxCtr.mpps[#rxCtr.mpps] | |
-- Wait 2s for throughput to stabilize before changing rate again. | |
local ts = lm.getTime() | |
if tx and rx and ts >= lastTs + 2 then | |
lastTs = ts | |
local factor = 0.002 | |
-- We're far from target throughput, let's speed things up! | |
if tx - rx > 0.5 then | |
factor = 0.03 | |
end | |
if tx > rx + 0.05 then | |
rate = rate + factor | |
else | |
rate = rate - factor | |
end | |
end | |
end | |
end | |
print(rate) | |
print(tx) | |
print(rx) | |
if displayStats then | |
txCtr:finalize() | |
rxCtr:finalize() | |
end | |
end | |
function loadSlave(queue, rate, rateLimiter, dev, displayStats) | |
local mem = memory.createMemPool(function(buf) | |
buf:getUdpPacket():fill{ | |
ethSrc = txDev, | |
ethDst = "00:15:4d:13:15:2b", | |
ip4Src = "192.168.1.3", | |
ip4Dst = "192.168.1.2", | |
udpSrc = 2000, | |
udpDst = 3000, | |
pktLength = 60 | |
} | |
end) | |
local linkSpeed = dev:getLinkStatus().speed | |
local bufs = mem:bufArray(128) | |
local txCtr = stats:newDevTxCounter(dev, "plain") | |
local rxCtr = stats:newDevRxCounter(dev, "plain") | |
local lastTs = 0 | |
while mg.running() do | |
bufs:alloc(60) | |
for _, buf in ipairs(bufs) do | |
buf:setDelay(rate * linkSpeed / 8) | |
end | |
bufs:offloadUdpChecksums() | |
rateLimiter:send(bufs) | |
if displayStats then | |
txCtr:update() | |
rxCtr:update() | |
end | |
tx = txCtr.mpps[#txCtr.mpps] | |
rx = rxCtr.mpps[#rxCtr.mpps] | |
-- Wait 2s for throughput to stabilize before changing rate again. | |
local ts = lm.getTime() | |
if tx and rx and ts >= lastTs + 2 then | |
lastTs = ts | |
local factor = 0.002 | |
-- We're far from target throughput, let's speed things up! | |
if tx - rx > 0.5 then | |
factor = 0.03 | |
end | |
if tx > rx + 0.05 then | |
rate = rate + factor | |
else | |
rate = rate - factor | |
end | |
end | |
end | |
print(rate) | |
print(tx) | |
print(rx) | |
if displayStats then | |
txCtr:finalize() | |
rxCtr:finalize() | |
end | |
end | |
function counterSlave(queue) | |
local bufs = memory.bufArray() | |
while mg.running() do | |
local rx = queue:tryRecv(bufs, 100) | |
bufs:free(rx) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment