1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
-- SPDX-License-Identifier: GPL-3.0-or-later
local ffi = require('ffi')
local kr_cach = kres.context().cache
local charset = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'}
local function gen_bytes(len)
local bytes = {}
for _ = 1,len do
table.insert(bytes, charset[math.random(1, #charset)])
end
local result = table.concat(bytes)
assert(#result == len)
return result
end
local function gen_ttl()
return math.random(0, 2^31-1)
end
local function gen_rrtype()
return math.random(1024, 61000)
end
local function gen_rdata(len)
assert(len >= 1 and len <= 65535)
return gen_bytes(len)
end
local function gen_label(len) -- in bytes including the length byte
assert(len >= 2 and len <= 64)
local bytes = {string.char(len - 1), gen_bytes(len - 1)}
return table.concat(bytes)
end
local function gen_dname()
local target_len -- length 2 bytes does not make sense
while target_len == nil or target_len == 2 do
target_len = math.random(1, 255)
end
local labels = {string.char(0)}
local cur_len = 1
while target_len > cur_len do
local new_len = math.random(
2,
math.min(target_len - cur_len,
64))
if (target_len - cur_len - new_len) == 1 then
-- it is a trap, single-byte label is allowed only at the end
-- we cannot leave room for single-byte label in the next round
if new_len == 64 then
goto continue -- we are at max label length, try again
end
new_len = new_len + 1
end
table.insert(labels, 1, gen_label(new_len))
cur_len = cur_len + new_len
::continue::
end
assert(target_len == cur_len)
local dname = table.concat(labels)
assert(#dname >= 1 and #dname <= 255)
assert(string.byte(dname, #dname) == 0)
return dname
end
local function gen_rrset()
local rrs = {}
local maxsize = 300 -- RR data size in bytes per RR set, does not include owner etc.
local target_len = math.random(1, maxsize)
local cur_len = 0
while target_len > cur_len do
local new_len = math.random(1, target_len - cur_len)
local new_rr = gen_rdata(new_len)
cur_len = cur_len + #new_rr
table.insert(rrs, new_rr)
end
assert(target_len == cur_len)
return rrs, cur_len
end
local function add_random_rrset()
local owner = gen_dname()
local ttl = gen_ttl()
local rr_type = gen_rrtype()
local rdata_set = gen_rrset()
local kr_rrset = kres.rrset(owner, rr_type, kres.class.IN, ttl)
for _, rr in ipairs(rdata_set) do
assert(kr_rrset:add_rdata(rr, #rr))
end
assert(kr_cach:insert(kr_rrset, nil, ffi.C.KR_RANK_SECURE))
end
ffi.cdef('int usleep(uint32_t usec);') -- at least in current glibc it's always 32-bit
local rr_count = 0
local function gen_batch()
for _ = 1,math.random(1,10) do
add_random_rrset()
rr_count = rr_count + 1
if rr_count % 100 == 0 then
print('cache usage ', cache.stats()['usage_percent'], '%')
end
end
kr_cach:commit()
ffi.C.usleep(15) -- stop *whole process* to give better chance to GC executing
local delay
if math.random(1,4) == 1 then
delay = 1 -- give a chance to DNS resolving
else
delay = 0
end
event.after(delay, gen_batch)
end
return {
add_random_rrset=add_random_rrset,
gen_batch=gen_batch,
gen_bytes=gen_bytes,
gen_dname=gen_dname,
gen_label=gen_label,
gen_rdata=gen_rdata,
gen_rrset=gen_rrset,
gen_rrtype=gen_rrtype,
gen_ttl=gen_ttl
}
|