Adding upstream version 1.1.0+debian.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f890831723
commit
8d1b12293d
261 changed files with 31196 additions and 0 deletions
21
examples/Makefile.am
Normal file
21
examples/Makefile.am
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) 2018-2021, OARC, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of dnsjit.
|
||||
#
|
||||
# dnsjit 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.
|
||||
#
|
||||
# dnsjit 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 dnsjit. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
dist_doc_DATA = capture.lua dumpdns2pcap.lua dumpdns.lua dumpdns-qr.lua \
|
||||
filter_rcode.lua qr-multi-pcap-state.lua readme.lua replay.lua \
|
||||
replay_multicli.lua respdiff.lua test_pcap_read.lua test_throughput.lua
|
47
examples/capture.lua
Executable file
47
examples/capture.lua
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local interface = arg[2]
|
||||
|
||||
if interface == nil then
|
||||
print("usage: "..arg[1].." <interface or any/all>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
|
||||
input:create(interface)
|
||||
input:activate()
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
local transport = obj.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
local protocol = obj.obj_prev
|
||||
while protocol ~= nil do
|
||||
if protocol.obj_type == object.UDP or protocol.obj_type == object.TCP then
|
||||
break
|
||||
end
|
||||
protocol = protocol.obj_prev
|
||||
end
|
||||
|
||||
dns.obj_prev = obj
|
||||
if transport ~= nil and protocol ~= nil then
|
||||
transport = transport:cast()
|
||||
protocol = protocol:cast()
|
||||
print(protocol:type().." "..transport:source()..":"..tonumber(protocol.sport).." -> "..transport:destination()..":"..tonumber(protocol.dport))
|
||||
dns:print()
|
||||
end
|
||||
end
|
||||
end
|
50
examples/count-pkts-per-ip.lua
Executable file
50
examples/count-pkts-per-ip.lua
Executable file
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
-- count-pkts-per-ip.lua: count number of packets received from each IP/IPv6 address
|
||||
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local object = require("dnsjit.core.objects")
|
||||
local ip = require("dnsjit.lib.ip")
|
||||
local trie = require("dnsjit.lib.trie").new("uint64_t", true)
|
||||
local getopt = require("dnsjit.lib.getopt").new({})
|
||||
|
||||
local pcap = unpack(getopt:parse())
|
||||
if pcap == nil then
|
||||
print("usage: "..arg[1].." <pcap>")
|
||||
end
|
||||
|
||||
-- Set up input
|
||||
input:open_offline(pcap)
|
||||
layer:producer(input)
|
||||
local produce, pctx = layer:produce()
|
||||
|
||||
-- Read input and count packets
|
||||
while true do
|
||||
local obj = produce(pctx)
|
||||
if obj == nil then break end
|
||||
local pkt = obj:cast_to(object.IP) or obj:cast_to(object.IP6)
|
||||
|
||||
if pkt ~= nil then
|
||||
local iplen = 4
|
||||
if pkt:type() == "ip6" then
|
||||
iplen = 16
|
||||
end
|
||||
|
||||
local node = trie:get_ins(pkt.src, iplen)
|
||||
node:set(node:get() + 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Print statistics
|
||||
local iter = trie:iter()
|
||||
local node = iter:node()
|
||||
|
||||
while node ~= nil do
|
||||
local npkts = tonumber(node:get())
|
||||
local key = node:key()
|
||||
local ipstr = ip.tostring(key, true)
|
||||
|
||||
print(ipstr.." sent "..npkts.." packets")
|
||||
iter:next()
|
||||
node = iter:node()
|
||||
end
|
85
examples/dumpdns-qr.lua
Executable file
85
examples/dumpdns-qr.lua
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local pcap = arg[2]
|
||||
|
||||
if pcap == nil then
|
||||
print("usage: "..arg[1].." <pcap>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
local label = require("dnsjit.core.object.dns.label")
|
||||
|
||||
local ffi = require("ffi")
|
||||
local labels = require("dnsjit.core.object.dns.label").new(16)
|
||||
local q = require("dnsjit.core.object.dns.q").new()
|
||||
|
||||
input:open_offline(pcap)
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
local queries = {}
|
||||
local responses = {}
|
||||
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
local transport = obj.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
local protocol = obj.obj_prev
|
||||
while protocol ~= nil do
|
||||
if protocol.obj_type == object.UDP or protocol.obj_type == object.TCP then
|
||||
break
|
||||
end
|
||||
protocol = protocol.obj_prev
|
||||
end
|
||||
|
||||
dns.obj_prev = obj
|
||||
if transport ~= nil and protocol ~= nil and dns:parse_header() == 0 then
|
||||
transport = transport:cast()
|
||||
protocol = protocol:cast()
|
||||
|
||||
if dns.qr == 1 then
|
||||
table.insert(responses, {
|
||||
src = transport:source(),
|
||||
sport = protocol.sport,
|
||||
dst = transport:destination(),
|
||||
dport = protocol.dport,
|
||||
id = dns.id,
|
||||
rcode = dns.rcode_tostring(dns.rcode),
|
||||
})
|
||||
else
|
||||
if dns.qdcount > 0 and dns:parse_q(q, labels, 16) == 0 then
|
||||
table.insert(queries, {
|
||||
src = transport:source(),
|
||||
sport = protocol.sport,
|
||||
dst = transport:destination(),
|
||||
dport = protocol.dport,
|
||||
id = dns.id,
|
||||
qname = label.tooffstr(dns, labels, 16),
|
||||
qtype = dns.type_tostring(q.type)
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("src", "dst", "id", "rcode", "qname", "qtype")
|
||||
local q, r
|
||||
for _, q in pairs(queries) do
|
||||
for _, r in pairs(responses) do
|
||||
if q.id == r.id and q.sport == r.dport and q.dport == r.sport and q.src == r.dst and q.dst == r.src then
|
||||
print(q.src, q.dst, q.id, r.rcode, q.qname, q.qtype)
|
||||
end
|
||||
end
|
||||
end
|
46
examples/dumpdns.lua
Executable file
46
examples/dumpdns.lua
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local pcap = arg[2]
|
||||
|
||||
if pcap == nil then
|
||||
print("usage: "..arg[1].." <pcap>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
|
||||
input:open_offline(pcap)
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
local transport = obj.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
local protocol = obj.obj_prev
|
||||
while protocol ~= nil do
|
||||
if protocol.obj_type == object.UDP or protocol.obj_type == object.TCP then
|
||||
break
|
||||
end
|
||||
protocol = protocol.obj_prev
|
||||
end
|
||||
|
||||
dns.obj_prev = obj
|
||||
if transport ~= nil and protocol ~= nil then
|
||||
transport = transport:cast()
|
||||
protocol = protocol:cast()
|
||||
print(protocol:type().." "..transport:source()..":"..tonumber(protocol.sport).." -> "..transport:destination()..":"..tonumber(protocol.dport))
|
||||
dns:print()
|
||||
end
|
||||
end
|
||||
end
|
38
examples/dumpdns2pcap.lua
Executable file
38
examples/dumpdns2pcap.lua
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local pcap_in = arg[2]
|
||||
local pcap_out = arg[3]
|
||||
|
||||
if pcap_in == nil or pcap_out == nil then
|
||||
print("usage: "..arg[1].." <pcap in> <pcap out>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
local output = require("dnsjit.output.pcap").new()
|
||||
|
||||
input:open_offline(pcap_in)
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
output:open(pcap_out, input:linktype(), input:snaplen())
|
||||
local receiver, rctx = output:receive()
|
||||
|
||||
local n = 0
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
dns.obj_prev = obj
|
||||
if dns:parse_header() == 0 then
|
||||
receiver(rctx, obj)
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
output:close()
|
||||
print(n, "DNS packets dumped")
|
38
examples/filter_rcode.lua
Executable file
38
examples/filter_rcode.lua
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local pcap = arg[2]
|
||||
local rcode = tonumber(arg[3])
|
||||
|
||||
if pcap == nil or rcode == nil then
|
||||
print("usage: "..arg[1].." <pcap> <rcode>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
|
||||
input:open_offline(pcap)
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
local transport = obj.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
|
||||
dns.obj_prev = obj
|
||||
if transport and dns and dns:parse_header() == 0 and dns.have_rcode == 1 and dns.rcode == rcode then
|
||||
transport = transport:cast()
|
||||
print(dns.id, transport:source().." -> "..transport:destination())
|
||||
end
|
||||
end
|
||||
end
|
270
examples/qr-multi-pcap-state.lua
Executable file
270
examples/qr-multi-pcap-state.lua
Executable file
|
@ -0,0 +1,270 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
{ "r", "read-state", "", "File to read state from before processing", "?" },
|
||||
{ "w", "write-state", "", "File to write state to after processing", "?" },
|
||||
})
|
||||
local pcap = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if pcap == nil then
|
||||
print("usage: "..arg[1].." <pcap>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.mmpcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
local label = require("dnsjit.core.object.dns.label")
|
||||
local ffi = require("ffi")
|
||||
local labels = require("dnsjit.core.object.dns.label").new(16)
|
||||
local q = require("dnsjit.core.object.dns.q").new()
|
||||
local bit = require("bit")
|
||||
|
||||
hash_u32 = ffi.new("uint32_t[2]")
|
||||
hash_u32p = ffi.cast("uint32_t*", hash_u32)
|
||||
function hashkey(dns, transport, protocol)
|
||||
if transport.obj_type == object.IP then
|
||||
ffi.copy(hash_u32p, transport.src, 4)
|
||||
hash_u32[1] = hash_u32[0]
|
||||
ffi.copy(hash_u32p, transport.dst, 4)
|
||||
hash_u32[1] = bit.bxor(hash_u32[0], hash_u32[1])
|
||||
else
|
||||
local srcp = ffi.cast("uint8_t*", transport.src)
|
||||
ffi.copy(hash_u32p, srcp, 4)
|
||||
hash_u32[1] = hash_u32[0]
|
||||
ffi.copy(hash_u32p, srcp+4, 4)
|
||||
hash_u32[1] = bit.bxor(hash_u32[0], hash_u32[1])
|
||||
srcp = ffi.cast("uint8_t*", transport.dst)
|
||||
ffi.copy(hash_u32p, srcp, 4)
|
||||
hash_u32[1] = bit.bxor(hash_u32[0], hash_u32[1])
|
||||
ffi.copy(hash_u32p, srcp+4, 4)
|
||||
hash_u32[1] = bit.bxor(hash_u32[0], hash_u32[1])
|
||||
end
|
||||
if dns.qr == 1 then
|
||||
hash_u32[0] = protocol.dport + bit.lshift(protocol.sport, 16)
|
||||
else
|
||||
hash_u32[0] = protocol.sport + bit.lshift(protocol.dport, 16)
|
||||
end
|
||||
hash_u32[1] = bit.bxor(hash_u32[0], hash_u32[1])
|
||||
hash_u32[0] = dns.id + bit.lshift(dns.id, 16)
|
||||
return bit.bxor(hash_u32[0], hash_u32[1])
|
||||
end
|
||||
|
||||
function dump_inflight(hkey, obj)
|
||||
return string.format("return %d, { qsec = %d, qnsec = %d, rsec = %d, rnsec = %d, src = %q, sport = %d, dst = %q, dport = %d, id = %d, qname = %q, qtype = %q, rcode = %d }",
|
||||
hkey,
|
||||
tonumber(obj.qsec), tonumber(obj.qnsec),
|
||||
tonumber(obj.rsec), tonumber(obj.rnsec),
|
||||
obj.src, obj.sport,
|
||||
obj.dst, obj.dport,
|
||||
obj.id,
|
||||
obj.qname, obj.qtype,
|
||||
obj.rcode
|
||||
)
|
||||
end
|
||||
|
||||
function qrout(res)
|
||||
local tsq = tonumber(res.qsec) + (tonumber(res.qnsec)/1000000000)
|
||||
local tsr = tonumber(res.rsec) + (tonumber(res.rnsec)/1000000000)
|
||||
print(tsq, tsr, math.floor(((tsr-tsq)*1000000)+0.5),
|
||||
res.src, res.dst, res.id, res.rcode, res.qname, res.qtype)
|
||||
end
|
||||
|
||||
input:open(pcap)
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
local inflight = {}
|
||||
|
||||
if getopt:val("read-state") > "" then
|
||||
local f, _ = io.open(getopt:val("read-state"))
|
||||
local inflights = 0
|
||||
if f ~= nil then
|
||||
for chunk in f:lines() do
|
||||
local hkey, query = assert(loadstring(chunk))()
|
||||
if hkey and query then
|
||||
if not inflight[hkey] then
|
||||
inflight[hkey] = {
|
||||
queries = {},
|
||||
size = 0,
|
||||
}
|
||||
end
|
||||
|
||||
table.insert(inflight[hkey].queries, query)
|
||||
inflight[hkey].size = inflight[hkey].size + 1
|
||||
inflights = inflights + 1
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
print(string.format("== read %d inflight states from %q", inflights, getopt:val("read-state")))
|
||||
end
|
||||
end
|
||||
|
||||
local stat = {
|
||||
packets = 0,
|
||||
queries = 0,
|
||||
responses = 0,
|
||||
dropped = 0,
|
||||
}
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
while true do
|
||||
local obj = producer(ctx)
|
||||
if obj == nil then break end
|
||||
stat.packets = stat.packets + 1
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
local protocol = obj.obj_prev
|
||||
while protocol ~= nil do
|
||||
if protocol.obj_type == object.UDP or protocol.obj_type == object.TCP then
|
||||
break
|
||||
end
|
||||
protocol = protocol.obj_prev
|
||||
end
|
||||
local transport = protocol.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
local pcap = transport.obj_prev
|
||||
while pcap ~= nil do
|
||||
if pcap.obj_type == object.PCAP then
|
||||
break
|
||||
end
|
||||
pcap = pcap.obj_prev
|
||||
end
|
||||
|
||||
dns.obj_prev = obj
|
||||
if pcap ~= nil and transport ~= nil and protocol ~= nil and dns:parse_header() == 0 then
|
||||
transport = transport:cast()
|
||||
protocol = protocol:cast()
|
||||
pcap = pcap:cast()
|
||||
|
||||
local hkey = hashkey(dns, transport, protocol)
|
||||
|
||||
if dns.qr == 1 then
|
||||
stat.responses = stat.responses + 1
|
||||
if inflight[hkey] then
|
||||
for k, n in pairs(inflight[hkey].queries) do
|
||||
if n.id == dns.id
|
||||
and n.sport == protocol.dport
|
||||
and n.dport == protocol.sport
|
||||
and n.src == transport:destination()
|
||||
and n.dst == transport:source()
|
||||
then
|
||||
n.rsec = pcap.ts.sec
|
||||
n.rnsec = pcap.ts.nsec
|
||||
n.rcode = dns.rcode
|
||||
qrout(n)
|
||||
inflight[hkey].queries[k] = nil
|
||||
inflight[hkey].size = inflight[hkey].size - 1
|
||||
if inflight[hkey].size < 1 then
|
||||
inflight[hkey] = nil
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
print("== dropped",
|
||||
tonumber(pcap.ts.sec) + (tonumber(pcap.ts.nsec) / 1000000000),
|
||||
transport:source(),
|
||||
transport:destination(),
|
||||
dns.id,
|
||||
label.tooffstr(dns, labels, 16),
|
||||
dns.type_tostring(q.type)
|
||||
)
|
||||
stat.dropped = stat.dropped + 1
|
||||
end
|
||||
else
|
||||
stat.queries = stat.queries + 1
|
||||
if dns.qdcount > 0 and dns:parse_q(q, labels, 16) == 0 then
|
||||
if not inflight[hkey] then
|
||||
inflight[hkey] = {
|
||||
queries = {},
|
||||
size = 0,
|
||||
}
|
||||
end
|
||||
|
||||
table.insert(inflight[hkey].queries, {
|
||||
qsec = pcap.ts.sec,
|
||||
qnsec = pcap.ts.nsec,
|
||||
rsec = -1,
|
||||
rnsec = -1,
|
||||
src = transport:source(),
|
||||
sport = protocol.sport,
|
||||
dst = transport:destination(),
|
||||
dport = protocol.dport,
|
||||
id = dns.id,
|
||||
qname = label.tooffstr(dns, labels, 16),
|
||||
qtype = dns.type_tostring(q.type),
|
||||
rcode = -1,
|
||||
})
|
||||
inflight[hkey].size = inflight[hkey].size + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print("== runtime", runtime)
|
||||
print("== packets", stat.packets, stat.packets/runtime)
|
||||
print("== queries", stat.queries, stat.queries/runtime)
|
||||
print("== responses", stat.responses, stat.responses/runtime)
|
||||
print("== dropped", stat.dropped, stat.dropped/runtime)
|
||||
|
||||
if getopt:val("write-state") > "" then
|
||||
local f, _ = io.open(getopt:val("write-state"), "w+")
|
||||
local inflights = 0
|
||||
if f ~= nil then
|
||||
for hkey, unanswered in pairs(inflight) do
|
||||
for _, query in pairs(unanswered.queries) do
|
||||
f:write(dump_inflight(hkey, query), "\n")
|
||||
inflights = inflights + 1
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
print(string.format("== wrote %d inflight states to %q", inflights, getopt:val("write-state")))
|
||||
end
|
||||
else
|
||||
inflights = 0
|
||||
for hkey, unanswered in pairs(inflight) do
|
||||
inflights = inflights + unanswered.size
|
||||
end
|
||||
if inflights > 0 then
|
||||
print("== inflight queries (tsq, src, dst, id, qname, qtype)")
|
||||
for hkey, unanswered in pairs(inflight) do
|
||||
for _, query in pairs(unanswered.queries) do
|
||||
print(tonumber(query.qsec) + (tonumber(query.qnsec)/1000000000), query.src, query.dst, query.id, query.qname, query.qtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
20
examples/readme.lua
Executable file
20
examples/readme.lua
Executable file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.pcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
|
||||
input:open_offline(arg[2])
|
||||
layer:producer(input)
|
||||
local producer, ctx = layer:produce()
|
||||
|
||||
while true do
|
||||
local object = producer(ctx)
|
||||
if object == nil then break end
|
||||
if object:type() == "payload" then
|
||||
dns.obj_prev = object
|
||||
if dns:parse_header() == 0 then
|
||||
print(dns.id)
|
||||
end
|
||||
end
|
||||
end
|
119
examples/replay.lua
Executable file
119
examples/replay.lua
Executable file
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
{ "R", "responses", false, "Wait for responses to the queries and print both", "?" },
|
||||
{ "t", "tcp", false, "Use TCP instead of UDP", "?"},
|
||||
{ "T", "tls", false, "Use TLS instead of UDP/TCP", "?"},
|
||||
})
|
||||
local pcap, host, port = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if pcap == nil or host == nil or port == nil then
|
||||
print("usage: "..arg[1].." <pcap> <host> <port>")
|
||||
return
|
||||
end
|
||||
|
||||
local ffi = require("ffi")
|
||||
|
||||
require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.mmpcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
|
||||
input:open(pcap)
|
||||
layer:producer(input)
|
||||
|
||||
local query = require("dnsjit.core.object.dns").new()
|
||||
local response = require("dnsjit.core.object.dns").new()
|
||||
|
||||
local dnscli = require("dnsjit.output.dnscli")
|
||||
local output
|
||||
if getopt:val("t") then
|
||||
output = dnscli.new(dnscli.TCP)
|
||||
response.includes_dnslen = 1
|
||||
elseif getopt:val("T") then
|
||||
output = dnscli.new(dnscli.TLS)
|
||||
response.includes_dnslen = 1
|
||||
else
|
||||
output = dnscli.new(dnscli.UDP)
|
||||
end
|
||||
output:connect(host, port)
|
||||
|
||||
local printdns = false
|
||||
if getopt:val("responses") then
|
||||
printdns = true
|
||||
end
|
||||
|
||||
local prod, pctx = layer:produce()
|
||||
local recv, rctx = output:receive()
|
||||
local oprod, opctx = output:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
|
||||
while true do
|
||||
local obj = prod(pctx)
|
||||
if obj == nil then break end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
query.obj_prev = obj
|
||||
|
||||
local trs = pl.obj_prev:cast()
|
||||
if trs:type() == "tcp" then
|
||||
query.includes_dnslen = 1
|
||||
else
|
||||
query.includes_dnslen = 0
|
||||
end
|
||||
|
||||
if query:parse_header() == 0 and query.qr == 0 then
|
||||
recv(rctx, query:uncast())
|
||||
|
||||
if printdns then
|
||||
print("query:")
|
||||
query:print()
|
||||
|
||||
local pobj = oprod(opctx)
|
||||
if pobj == nil then
|
||||
log.fatal("producer error")
|
||||
end
|
||||
local rpl = pobj:cast()
|
||||
if rpl.len == 0 then
|
||||
print("timed out")
|
||||
else
|
||||
response.obj_prev = pobj
|
||||
print("response:")
|
||||
response:print()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print("runtime", runtime)
|
||||
print("packets", input:packets(), input:packets()/runtime, "/pps")
|
||||
print("queries", output:packets(), output:packets()/runtime, "/qps")
|
||||
print("errors", output:errors())
|
192
examples/replay_multicli.lua
Executable file
192
examples/replay_multicli.lua
Executable file
|
@ -0,0 +1,192 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "c", "clients", 10, "Number of clients run", "?" },
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
{ "R", "responses", false, "Wait for responses to the queries and print both", "?" },
|
||||
{ "t", "tcp", false, "Use TCP instead of UDP", "?"},
|
||||
{ "T", "tls", false, "Use TLS instead of UDP/TCP", "?"},
|
||||
})
|
||||
local pcap, host, port = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if pcap == nil or host == nil or port == nil then
|
||||
print("usage: "..arg[1].." <pcap> <host> <port>")
|
||||
return
|
||||
end
|
||||
|
||||
local ffi = require("ffi")
|
||||
|
||||
require("dnsjit.core.objects")
|
||||
local input = require("dnsjit.input.mmpcap").new()
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
|
||||
input:open(pcap)
|
||||
layer:producer(input)
|
||||
|
||||
local query = require("dnsjit.core.object.dns").new()
|
||||
local response = require("dnsjit.core.object.dns").new()
|
||||
|
||||
local dnscli = require("dnsjit.output.dnscli")
|
||||
|
||||
local clients = {}
|
||||
local last_client = nil
|
||||
local num_clients = getopt:val("c")
|
||||
for n = 1, num_clients do
|
||||
local output
|
||||
if getopt:val("t") then
|
||||
output = dnscli.new(dnscli.TCP + dnscli.NONBLOCKING)
|
||||
elseif getopt:val("T") then
|
||||
output = dnscli.new(dnscli.TLS + dnscli.NONBLOCKING)
|
||||
else
|
||||
output = dnscli.new(dnscli.UDP + dnscli.NONBLOCKING)
|
||||
end
|
||||
output:connect(host, port)
|
||||
|
||||
local recv, rctx = output:receive()
|
||||
local prod, pctx = output:produce()
|
||||
local client = {
|
||||
output = output,
|
||||
last = last_client,
|
||||
busy = false,
|
||||
recv = recv, rctx = rctx,
|
||||
prod = prod, pctx = pctx,
|
||||
id = nil,
|
||||
done = false,
|
||||
}
|
||||
table.insert(clients, client)
|
||||
last_client = client
|
||||
end
|
||||
local output = clients[1]
|
||||
output.last = last_client
|
||||
|
||||
if getopt:val("t") then
|
||||
response.includes_dnslen = 1
|
||||
elseif getopt:val("T") then
|
||||
response.includes_dnslen = 1
|
||||
end
|
||||
|
||||
local printdns = false
|
||||
if getopt:val("responses") then
|
||||
printdns = true
|
||||
end
|
||||
|
||||
local prod, pctx = layer:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
|
||||
local done = false
|
||||
while true do
|
||||
output = output.last
|
||||
if printdns and output.busy then
|
||||
local pobj = output.prod(output.pctx)
|
||||
if pobj == nil then
|
||||
log.fatal("producer error")
|
||||
end
|
||||
local rpl = pobj:cast()
|
||||
if rpl.len == 0 then
|
||||
-- print(output, "busy")
|
||||
else
|
||||
response.obj_prev = pobj
|
||||
if response:parse_header() == 0 and response.qr == 1 and response.id == output.id then
|
||||
print("response:")
|
||||
response:print()
|
||||
output.busy = false
|
||||
end
|
||||
end
|
||||
end
|
||||
if not output.busy then
|
||||
while true do
|
||||
local obj = prod(pctx)
|
||||
if obj == nil then
|
||||
done = true
|
||||
break
|
||||
end
|
||||
local pl = obj:cast()
|
||||
if obj:type() == "payload" and pl.len > 0 then
|
||||
query.obj_prev = obj
|
||||
|
||||
local trs = pl.obj_prev:cast()
|
||||
if trs:type() == "tcp" then
|
||||
query.includes_dnslen = 1
|
||||
else
|
||||
query.includes_dnslen = 0
|
||||
end
|
||||
|
||||
if query:parse_header() == 0 and query.qr == 0 then
|
||||
output.recv(output.rctx, query:uncast())
|
||||
if printdns then
|
||||
print("query:")
|
||||
query:print()
|
||||
output.busy = true
|
||||
output.id = query.id
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if done then break end
|
||||
end
|
||||
|
||||
local queries, timeouts, errors = 0, 0, 0
|
||||
done = 0
|
||||
while true do
|
||||
output = output.last
|
||||
if printdns and output.busy then
|
||||
local pobj = output.prod(output.pctx)
|
||||
if pobj == nil then
|
||||
log.fatal("producer error")
|
||||
end
|
||||
local rpl = pobj:cast()
|
||||
if rpl.len == 0 then
|
||||
-- print(output, "busy")
|
||||
else
|
||||
response.obj_prev = pobj
|
||||
if response:parse_header() == 0 and response.qr == 1 and response.id == output.id then
|
||||
print("response:")
|
||||
response:print()
|
||||
output.busy = false
|
||||
end
|
||||
end
|
||||
end
|
||||
if not output.busy and not output.done then
|
||||
output.done = true
|
||||
done = done + 1
|
||||
queries = queries + output.output:packets()
|
||||
timeouts = timeouts + output.output:timeouts()
|
||||
errors = errors + output.output:errors()
|
||||
end
|
||||
if done >= num_clients then break end
|
||||
end
|
||||
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print("runtime", runtime)
|
||||
print("packets", input:packets(), input:packets()/runtime, "/pps")
|
||||
print("queries", queries, queries/runtime, "/qps")
|
||||
print("timeouts", timeouts)
|
||||
print("errors", errors)
|
160
examples/respdiff.lua
Executable file
160
examples/respdiff.lua
Executable file
|
@ -0,0 +1,160 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local ffi = require("ffi")
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
log.display_file_line(true)
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
})
|
||||
local pcap, host, port, path, origname, recvname = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if pcap == nil or host == nil or port == nil or path == nil or origname == nil or recvname == nil then
|
||||
print("usage: "..arg[1].." <pcap> <host> <port> <LMDB path> <origname> <recvname>")
|
||||
return
|
||||
end
|
||||
|
||||
local object = require("dnsjit.core.objects")
|
||||
local dns = require("dnsjit.core.object.dns").new()
|
||||
local input = require("dnsjit.input.mmpcap").new()
|
||||
input:open(pcap)
|
||||
local layer = require("dnsjit.filter.layer").new()
|
||||
layer:producer(input)
|
||||
|
||||
local udpcli, tcpcli
|
||||
local udprecv, udpctx, tcprecv, tcpctx
|
||||
local udpprod, tcpprod
|
||||
|
||||
local prod, pctx = layer:produce()
|
||||
local queries = {}
|
||||
local clipayload = ffi.new("core_object_payload_t")
|
||||
clipayload.obj_type = object.PAYLOAD
|
||||
local cliobject = ffi.cast("core_object_t*", clipayload)
|
||||
|
||||
local respdiff = require("dnsjit.output.respdiff").new(path, origname, recvname)
|
||||
local resprecv, respctx = respdiff:receive()
|
||||
local query_payload, original_payload, response_payload = ffi.new("core_object_payload_t"), ffi.new("core_object_payload_t"), ffi.new("core_object_payload_t")
|
||||
query_payload.obj_type = object.PAYLOAD
|
||||
original_payload.obj_type = object.PAYLOAD
|
||||
response_payload.obj_type = object.PAYLOAD
|
||||
local query_payload_obj = ffi.cast("core_object_t*", query_payload)
|
||||
query_payload.obj_prev = ffi.cast("core_object_t*", original_payload)
|
||||
original_payload.obj_prev = ffi.cast("core_object_t*", response_payload)
|
||||
|
||||
local start_sec, start_nsec = clock:realtime()
|
||||
while true do
|
||||
local obj = prod(pctx)
|
||||
if obj == nil then break end
|
||||
local payload = obj:cast()
|
||||
if obj:type() == "payload" and payload.len > 0 then
|
||||
dns.obj_prev = obj
|
||||
if dns:parse_header() == 0 then
|
||||
local transport = obj.obj_prev
|
||||
while transport ~= nil do
|
||||
if transport.obj_type == object.IP or transport.obj_type == object.IP6 then
|
||||
break
|
||||
end
|
||||
transport = transport.obj_prev
|
||||
end
|
||||
local protocol = obj.obj_prev
|
||||
while protocol ~= nil do
|
||||
if protocol.obj_type == object.UDP or protocol.obj_type == object.TCP then
|
||||
break
|
||||
end
|
||||
protocol = protocol.obj_prev
|
||||
end
|
||||
|
||||
if transport ~= nil and protocol ~= nil then
|
||||
transport = transport:cast()
|
||||
protocol = protocol:cast()
|
||||
|
||||
if dns.qr == 0 then
|
||||
local k = string.format("%s %d %s %d", transport:source(), protocol.sport, transport:destination(), protocol.dport)
|
||||
local q = {
|
||||
id = dns.id,
|
||||
proto = protocol:type(),
|
||||
payload = ffi.new("uint8_t[?]", payload.len),
|
||||
len = tonumber(payload.len)
|
||||
}
|
||||
ffi.copy(q.payload, payload.payload, payload.len)
|
||||
queries[k] = q
|
||||
else
|
||||
local k = string.format("%s %d %s %d", transport:destination(), protocol.dport, transport:source(), protocol.sport)
|
||||
local q = queries[k]
|
||||
if q then
|
||||
queries[k] = nil
|
||||
clipayload.payload = q.payload
|
||||
clipayload.len = q.len
|
||||
|
||||
local prod, pctx
|
||||
|
||||
if q.proto == "udp" then
|
||||
if not udpcli then
|
||||
udpcli = require("dnsjit.output.udpcli").new()
|
||||
udpcli:connect(host, port)
|
||||
udprecv, udpctx = udpcli:receive()
|
||||
udpprod, _ = udpcli:produce()
|
||||
end
|
||||
udprecv(udpctx, cliobject)
|
||||
prod = udpprod
|
||||
pctx = udpctx
|
||||
elseif q.proto == "tcp" then
|
||||
if not tcpcli then
|
||||
tcpcli = require("dnsjit.output.tcpcli").new()
|
||||
tcpcli:connect(host, port)
|
||||
tcprecv, tcpctx = tcpcli:receive()
|
||||
tcpprod, _ = tcpcli:produce()
|
||||
end
|
||||
tcprecv(tcpctx, cliobject)
|
||||
prod = tcpprod
|
||||
pctx = tcpctx
|
||||
end
|
||||
|
||||
while true do
|
||||
local response = prod(pctx)
|
||||
if response == nil then
|
||||
log.fatal("producer error")
|
||||
end
|
||||
local rpl = response:cast()
|
||||
if rpl.len == 0 then
|
||||
log.info("timed out")
|
||||
else
|
||||
dns.obj_prev = response
|
||||
if dns:parse_header() == 0 and dns.id == q.id then
|
||||
query_payload.payload = q.payload
|
||||
query_payload.len = q.len
|
||||
original_payload.payload = payload.payload
|
||||
original_payload.len = payload.len
|
||||
response_payload.payload = rpl.payload
|
||||
response_payload.len = rpl.len
|
||||
|
||||
resprecv(respctx, query_payload_obj)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local end_sec, end_nsec = clock:realtime()
|
||||
|
||||
respdiff:commit(start_sec, end_sec)
|
149
examples/test_pcap_read.lua
Executable file
149
examples/test_pcap_read.lua
Executable file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
{ "l", "layer", false, "Test also with dnsjit.filter.layer", "?" },
|
||||
{ "p", "producer", false, "Test with the producer interface rather then receiver interface", "?" },
|
||||
})
|
||||
local pcap, runs = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if pcap == nil then
|
||||
print("usage: "..arg[1].." <pcap> [runs]")
|
||||
return
|
||||
end
|
||||
|
||||
inputs = { "fpcap", "mmpcap", "pcap" }
|
||||
result = {}
|
||||
results = {}
|
||||
highest = nil
|
||||
|
||||
if runs == nil then
|
||||
runs = 10
|
||||
else
|
||||
runs = tonumber(runs)
|
||||
end
|
||||
|
||||
if getopt:val("p") then
|
||||
for _, name in pairs(inputs) do
|
||||
rt = 0.0
|
||||
p = 0
|
||||
|
||||
print("run", name)
|
||||
for n = 1, runs do
|
||||
o = require("dnsjit.output.null").new()
|
||||
i = require("dnsjit.input."..name).new()
|
||||
|
||||
if name == "pcap" then
|
||||
i:open_offline(pcap)
|
||||
else
|
||||
i:open(pcap)
|
||||
end
|
||||
|
||||
if getopt:val("l") then
|
||||
f = require("dnsjit.filter.layer").new()
|
||||
f:producer(i)
|
||||
o:producer(f)
|
||||
else
|
||||
o:producer(i)
|
||||
end
|
||||
|
||||
ss, sns = clock:monotonic()
|
||||
o:run()
|
||||
es, ens = clock:monotonic()
|
||||
|
||||
if es > ss then
|
||||
rt = rt + ((es - ss) - 1) + ((1000000000 - sns + ens)/1000000000)
|
||||
elseif es == ss and ens > sns then
|
||||
rt = rt + (ens - sns) / 1000000000
|
||||
end
|
||||
|
||||
p = p + o:packets()
|
||||
end
|
||||
|
||||
result[name] = {
|
||||
rt = rt,
|
||||
p = p
|
||||
}
|
||||
if highest == nil or rt > result[highest].rt then
|
||||
highest = name
|
||||
end
|
||||
table.insert(results, name)
|
||||
end
|
||||
else
|
||||
for _, name in pairs(inputs) do
|
||||
rt = 0.0
|
||||
p = 0
|
||||
|
||||
print("run", name)
|
||||
for n = 1, runs do
|
||||
o = require("dnsjit.output.null").new()
|
||||
i = require("dnsjit.input."..name).new()
|
||||
|
||||
if name == "pcap" then
|
||||
i:open_offline(pcap)
|
||||
else
|
||||
i:open(pcap)
|
||||
end
|
||||
|
||||
if getopt:val("l") then
|
||||
f = require("dnsjit.filter.layer").new()
|
||||
f:receiver(o)
|
||||
i:receiver(f)
|
||||
else
|
||||
i:receiver(o)
|
||||
end
|
||||
|
||||
ss, sns = clock:monotonic()
|
||||
if name == "pcap" then
|
||||
i:dispatch()
|
||||
else
|
||||
i:run()
|
||||
end
|
||||
es, ens = clock:monotonic()
|
||||
|
||||
if es > ss then
|
||||
rt = rt + ((es - ss) - 1) + ((1000000000 - sns + ens)/1000000000)
|
||||
elseif es == ss and ens > sns then
|
||||
rt = rt + (ens - sns) / 1000000000
|
||||
end
|
||||
|
||||
p = p + o:packets()
|
||||
end
|
||||
|
||||
result[name] = {
|
||||
rt = rt,
|
||||
p = p
|
||||
}
|
||||
if highest == nil or rt > result[highest].rt then
|
||||
highest = name
|
||||
end
|
||||
table.insert(results, name)
|
||||
end
|
||||
end
|
||||
|
||||
print("name", "runtime", "pps", "x", "pkts")
|
||||
print(highest, result[highest].rt, result[highest].p/result[highest].rt, 1.0, result[highest].p)
|
||||
for _, name in pairs(results) do
|
||||
if name ~= highest then
|
||||
local f = result[name].p / result[highest].p
|
||||
print(name, result[name].rt, result[name].p/result[name].rt, (result[highest].rt/result[name].rt)*f, result[name].p)
|
||||
end
|
||||
end
|
539
examples/test_throughput.lua
Executable file
539
examples/test_throughput.lua
Executable file
|
@ -0,0 +1,539 @@
|
|||
#!/usr/bin/env dnsjit
|
||||
local ffi = require("ffi")
|
||||
local object = require("dnsjit.core.objects")
|
||||
local clock = require("dnsjit.lib.clock")
|
||||
local log = require("dnsjit.core.log")
|
||||
local getopt = require("dnsjit.lib.getopt").new({
|
||||
{ "v", "verbose", 0, "Enable and increase verbosity for each time given", "?+" },
|
||||
{ "s", "split", false, "Test also with dnsjit.filter.split", "?" },
|
||||
{ "t", "thread", false, "Test also with dnsjit.core.thread using dnsjit.core.channel", "?" },
|
||||
})
|
||||
local num, runs = unpack(getopt:parse())
|
||||
if getopt:val("help") then
|
||||
getopt:usage()
|
||||
return
|
||||
end
|
||||
local v = getopt:val("v")
|
||||
if v > 0 then
|
||||
log.enable("warning")
|
||||
end
|
||||
if v > 1 then
|
||||
log.enable("notice")
|
||||
end
|
||||
if v > 2 then
|
||||
log.enable("info")
|
||||
end
|
||||
if v > 3 then
|
||||
log.enable("debug")
|
||||
end
|
||||
|
||||
if num == nil then
|
||||
print("usage: "..arg[1].." <num> [runs]")
|
||||
return
|
||||
else
|
||||
num = tonumber(num)
|
||||
end
|
||||
|
||||
if runs == nil then
|
||||
runs = 1
|
||||
else
|
||||
runs = tonumber(runs)
|
||||
end
|
||||
|
||||
print("zero:receiver() -> null:receive()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local o = require("dnsjit.output.null").new()
|
||||
|
||||
i:receiver(o)
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
i:run(num)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o:packets())
|
||||
end
|
||||
|
||||
print("lua -> null:receive()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local o = require("dnsjit.output.null").new()
|
||||
local recv, rctx = o:receive()
|
||||
local pkt = ffi.new("core_object_null_t")
|
||||
pkt.obj_type = object.NULL
|
||||
local obj = ffi.cast("core_object_t*", pkt)
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num do
|
||||
recv(rctx, obj)
|
||||
end
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o:packets())
|
||||
end
|
||||
|
||||
-- TODO: use core.thread
|
||||
|
||||
print("zero:produce() <- null:producer()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local o = require("dnsjit.output.null").new()
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
o:producer(i)
|
||||
o:run(num)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o:packets())
|
||||
end
|
||||
|
||||
print("zero:produce() <- lua")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local prod, pctx = i:produce()
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num do
|
||||
prod(pctx)
|
||||
end
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", num)
|
||||
end
|
||||
|
||||
print("zero:produce() <- lua -> null:receive()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local o = require("dnsjit.output.null").new()
|
||||
local prod, pctx = i:produce()
|
||||
local recv, rctx = o:receive()
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num do
|
||||
recv(rctx, prod(pctx))
|
||||
end
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", num)
|
||||
end
|
||||
|
||||
if getopt:val("s") then
|
||||
print("zero:receiver() -> split:receiver() -> null:receive() x1")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local s = require("dnsjit.filter.split").new()
|
||||
local o1 = require("dnsjit.output.null").new()
|
||||
|
||||
s:receiver(o1)
|
||||
i:receiver(s)
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
i:run(num)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o1:packets(), o1:packets())
|
||||
end
|
||||
|
||||
print("zero:receiver() -> split:receiver() -> null:receive() x2")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local s = require("dnsjit.filter.split").new()
|
||||
local o1 = require("dnsjit.output.null").new()
|
||||
local o2 = require("dnsjit.output.null").new()
|
||||
|
||||
s:receiver(o1)
|
||||
s:receiver(o2)
|
||||
i:receiver(s)
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
i:run(num)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o1:packets() + o2:packets(), o1:packets(), o2:packets())
|
||||
end
|
||||
|
||||
print("zero:receiver() -> split:receiver() -> null:receive() x4")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local s = require("dnsjit.filter.split").new()
|
||||
local o1 = require("dnsjit.output.null").new()
|
||||
local o2 = require("dnsjit.output.null").new()
|
||||
local o3 = require("dnsjit.output.null").new()
|
||||
local o4 = require("dnsjit.output.null").new()
|
||||
|
||||
s:receiver(o1)
|
||||
s:receiver(o2)
|
||||
s:receiver(o3)
|
||||
s:receiver(o4)
|
||||
i:receiver(s)
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
i:run(num)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o1:packets() + o2:packets() + o3:packets() + o4:packets(), o1:packets(), o2:packets(), o3:packets(), o4:packets())
|
||||
end
|
||||
|
||||
print("zero:receiver() -> lua split table -> null:receive() x4")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local o1 = require("dnsjit.output.null").new()
|
||||
local o2 = require("dnsjit.output.null").new()
|
||||
local o3 = require("dnsjit.output.null").new()
|
||||
local o4 = require("dnsjit.output.null").new()
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local recv, rctx = {}, {}
|
||||
|
||||
local f, c = o1:receive()
|
||||
table.insert(recv, f)
|
||||
table.insert(rctx, c)
|
||||
f, c = o2:receive()
|
||||
table.insert(recv, f)
|
||||
table.insert(rctx, c)
|
||||
f, c = o3:receive()
|
||||
table.insert(recv, f)
|
||||
table.insert(rctx, c)
|
||||
f, c = o4:receive()
|
||||
table.insert(recv, f)
|
||||
table.insert(rctx, c)
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
local idx = 1
|
||||
for n = 1, num do
|
||||
local f, c = recv[idx], rctx[idx]
|
||||
if not f then
|
||||
idx = 1
|
||||
f, c = recv[1], rctx[1]
|
||||
end
|
||||
f(c, prod(pctx))
|
||||
idx = idx + 1
|
||||
end
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o1:packets() + o2:packets() + o3:packets() + o4:packets(), o1:packets(), o2:packets(), o3:packets(), o4:packets())
|
||||
end
|
||||
|
||||
print("zero:receiver() -> lua split gen code -> null:receive() x4")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local o1 = require("dnsjit.output.null").new()
|
||||
local o2 = require("dnsjit.output.null").new()
|
||||
local o3 = require("dnsjit.output.null").new()
|
||||
local o4 = require("dnsjit.output.null").new()
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local f1, c1 = o1:receive()
|
||||
local f2, c2 = o2:receive()
|
||||
local f3, c3 = o3:receive()
|
||||
local f4, c4 = o4:receive()
|
||||
|
||||
local code = "return function (num, prod, pctx, f1, c1, f2, c2, f3, c3, f4, c4)\nlocal n = 0\nwhile n < num do\n"
|
||||
code = code .. "f1(c1,prod(pctx))\n"
|
||||
code = code .. "n = n + 1\n"
|
||||
code = code .. "f2(c2,prod(pctx))\n"
|
||||
code = code .. "n = n + 1\n"
|
||||
code = code .. "f3(c3,prod(pctx))\n"
|
||||
code = code .. "n = n + 1\n"
|
||||
code = code .. "f4(c4,prod(pctx))\n"
|
||||
code = code .. "n = n + 1\n"
|
||||
code = code .. "end\n"
|
||||
code = code .. "end"
|
||||
local f = assert(loadstring(code))()
|
||||
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
f(num, prod, pctx, f1, c1, f2, c2, f3, c3, f4, c4)
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec", o1:packets() + o2:packets() + o3:packets() + o4:packets(), o1:packets(), o2:packets(), o3:packets(), o4:packets())
|
||||
end
|
||||
end
|
||||
|
||||
if getopt:val("t") then
|
||||
print("zero:receiver() -> thread lua x1")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local c = require("dnsjit.core.channel").new()
|
||||
local t = require("dnsjit.core.thread").new()
|
||||
|
||||
t:start(function(t)
|
||||
local c = t:pop()
|
||||
|
||||
while true do
|
||||
local o = c:get()
|
||||
if o == nil then break end
|
||||
end
|
||||
end)
|
||||
t:push(c)
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num do
|
||||
c:put(prod(pctx))
|
||||
end
|
||||
c:close()
|
||||
t:stop()
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec")
|
||||
end
|
||||
|
||||
print("zero:receiver() -> thread lua x2")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local c = require("dnsjit.core.channel").new()
|
||||
local c2 = require("dnsjit.core.channel").new()
|
||||
local t = require("dnsjit.core.thread").new()
|
||||
local t2 = require("dnsjit.core.thread").new()
|
||||
|
||||
local f = function(t)
|
||||
local c = t:pop()
|
||||
|
||||
while true do
|
||||
local o = c:get()
|
||||
if o == nil then break end
|
||||
end
|
||||
end
|
||||
|
||||
t:start(f)
|
||||
t2:start(f)
|
||||
t:push(c)
|
||||
t2:push(c2)
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num/2 do
|
||||
c:put(prod(pctx))
|
||||
c2:put(prod(pctx))
|
||||
end
|
||||
c:close()
|
||||
c2:close()
|
||||
t:stop()
|
||||
t2:stop()
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec")
|
||||
end
|
||||
|
||||
print("zero:receiver() -> thread lua x4")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local c = require("dnsjit.core.channel").new()
|
||||
local c2 = require("dnsjit.core.channel").new()
|
||||
local c3 = require("dnsjit.core.channel").new()
|
||||
local c4 = require("dnsjit.core.channel").new()
|
||||
local t = require("dnsjit.core.thread").new()
|
||||
local t2 = require("dnsjit.core.thread").new()
|
||||
local t3 = require("dnsjit.core.thread").new()
|
||||
local t4 = require("dnsjit.core.thread").new()
|
||||
|
||||
local f = function(t)
|
||||
local c = t:pop()
|
||||
|
||||
while true do
|
||||
local o = c:get()
|
||||
if o == nil then break end
|
||||
end
|
||||
end
|
||||
|
||||
t:start(f)
|
||||
t2:start(f)
|
||||
t3:start(f)
|
||||
t4:start(f)
|
||||
t:push(c)
|
||||
t2:push(c2)
|
||||
t3:push(c3)
|
||||
t4:push(c4)
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num/4 do
|
||||
c:put(prod(pctx))
|
||||
c2:put(prod(pctx))
|
||||
c3:put(prod(pctx))
|
||||
c4:put(prod(pctx))
|
||||
end
|
||||
c:close()
|
||||
c2:close()
|
||||
c3:close()
|
||||
c4:close()
|
||||
t:stop()
|
||||
t2:stop()
|
||||
t3:stop()
|
||||
t4:stop()
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec")
|
||||
end
|
||||
|
||||
print("zero:receiver() -> thread lua x1 -> null:receiver()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local c = require("dnsjit.core.channel").new()
|
||||
local t = require("dnsjit.core.thread").new()
|
||||
|
||||
t:start(function(t)
|
||||
local c = t:pop()
|
||||
local o = require("dnsjit.output.null").new()
|
||||
|
||||
local recv, rctx = o:receive()
|
||||
while true do
|
||||
local obj = c:get()
|
||||
if obj == nil then break end
|
||||
recv(rctx, obj)
|
||||
end
|
||||
end)
|
||||
t:push(c)
|
||||
|
||||
local prod, pctx = i:produce()
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
for n = 1, num do
|
||||
c:put(prod(pctx))
|
||||
end
|
||||
c:close()
|
||||
t:stop()
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec")
|
||||
end
|
||||
|
||||
print("zero:receiver() -> thread x1 -> null:receiver()")
|
||||
local run
|
||||
for run = 1, runs do
|
||||
local i = require("dnsjit.input.zero").new()
|
||||
local c = require("dnsjit.core.channel").new()
|
||||
local t = require("dnsjit.core.thread").new()
|
||||
|
||||
t:start(function(t)
|
||||
local c = t:pop()
|
||||
local o = require("dnsjit.output.null").new()
|
||||
|
||||
c:receiver(o)
|
||||
c:run()
|
||||
end)
|
||||
t:push(c)
|
||||
|
||||
i:receiver(c)
|
||||
local start_sec, start_nsec = clock:monotonic()
|
||||
i:run(num)
|
||||
c:close()
|
||||
t:stop()
|
||||
local end_sec, end_nsec = clock:monotonic()
|
||||
|
||||
local runtime = 0
|
||||
if end_sec > start_sec then
|
||||
runtime = ((end_sec - start_sec) - 1) + ((1000000000 - start_nsec + end_nsec)/1000000000)
|
||||
elseif end_sec == start_sec and end_nsec > start_nsec then
|
||||
runtime = (end_nsec - start_nsec) / 1000000000
|
||||
end
|
||||
|
||||
print(run, "runtime", runtime, num/runtime, "/sec")
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue