Skip to content

Instantly share code, notes, and snippets.

@pchaigno
Last active January 16, 2020 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pchaigno/d180eb5de5cc31e0596761b2bfb80c97 to your computer and use it in GitHub Desktop.
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.
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