1
0
Fork 0

Adding upstream version 1.1.0+debian.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 08:30:48 +01:00
parent f890831723
commit 8d1b12293d
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
261 changed files with 31196 additions and 0 deletions

21
examples/Makefile.am Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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