Skip to content

Commit

Permalink
Merge PR #1493 (Release 2022-12: Balaclava) into master
Browse files Browse the repository at this point in the history
  • Loading branch information
eugeneia committed Dec 15, 2022
2 parents 94e4f19 + 8c1331e commit 885ac52
Show file tree
Hide file tree
Showing 46 changed files with 3,178 additions and 4,414 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ CSRC = $(wildcard src/c/*.c)
COBJ = $(CSRC:.c=.o)
PREFIX = /usr/local

LUAJIT_CFLAGS := -include $(CURDIR)/gcc-preinclude.h
LUAJIT_CFLAGS := -include $(CURDIR)/gcc-preinclude.h -DLUAJIT_ENABLE_LUA52COMPAT

all: $(LUAJIT) $(SYSCALL) $(PFLUA)
# LuaJIT
Expand Down
19 changes: 15 additions & 4 deletions src/apps/interlink/receiver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@ module(...,package.seeall)
local shm = require("core.shm")
local interlink = require("lib.interlink")

local Receiver = {name="apps.interlink.Receiver"}
local Receiver = {
name = "apps.interlink.Receiver",
config = {
queue = {},
size = {default=1024}
}
}

function Receiver:new (queue)
function Receiver:new (conf)
local self = {
attached = false,
queue = conf.queue,
size = conf.size
}
packet.enable_group_freelist()
return setmetatable({attached=false, queue=queue}, {__index=Receiver})
return setmetatable(self, {__index=Receiver})
end

function Receiver:link ()
local queue = self.queue or self.appname
if not self.attached then
self.shm_name = "group/interlink/"..queue..".interlink"
self.backlink = "interlink/receiver/"..queue..".interlink"
self.interlink = interlink.attach_receiver(self.shm_name)
self.interlink = interlink.attach_receiver(self.shm_name, self.size)
shm.alias(self.backlink, self.shm_name)
self.attached = true
end
Expand Down
19 changes: 15 additions & 4 deletions src/apps/interlink/transmitter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@ module(...,package.seeall)
local shm = require("core.shm")
local interlink = require("lib.interlink")

local Transmitter = {name="apps.interlink.Transmitter"}
local Transmitter = {
name = "apps.interlink.Transmitter",
config = {
queue = {},
size = {default=1024}
}
}

function Transmitter:new (queue)
function Transmitter:new (conf)
local self = {
attached = false,
queue = conf.queue,
size = conf.size
}
packet.enable_group_freelist()
return setmetatable({attached=false, queue=queue}, {__index=Transmitter})
return setmetatable(self, {__index=Transmitter})
end

function Transmitter:link ()
local queue = self.queue or self.appname
if not self.attached then
self.shm_name = "group/interlink/"..queue..".interlink"
self.backlink = "interlink/transmitter/"..queue..".interlink"
self.interlink = interlink.attach_transmitter(self.shm_name)
self.interlink = interlink.attach_transmitter(self.shm_name, self.size)
shm.alias(self.backlink, self.shm_name)
self.attached = true
end
Expand Down
44 changes: 33 additions & 11 deletions src/apps/lwaftr/binding_table.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ local ipv4_ntop = require("lib.yang.util").ipv4_ntop

local band, lshift, rshift = bit.band, bit.lshift, bit.rshift

softwire_key_t = ffi.typeof[[
struct { uint32_t ipv4; uint16_t psid; }
]]
softwire_value_t = ffi.typeof[[
struct { uint8_t b4_ipv6[16], br_address[16]; }
]]

psid_map_key_t = ffi.typeof[[
struct { uint32_t addr; }
]]
Expand Down Expand Up @@ -134,32 +141,32 @@ function BTLookupQueue:reset_queue()
end

local BindingTable = {}
local lookup_key
function BindingTable.new(psid_map, softwires)
local ret = {
psid_map = assert(psid_map),
softwires = assert(softwires),
entry = softwires.entry_type()
}
lookup_key = ret.softwires.entry_type().key
return setmetatable(ret, {__index=BindingTable})
end

function BindingTable:add_softwire_entry(entry_blob)
local entry = self.softwires.entry_type()
local entry = self.entry
assert(ffi.sizeof(entry) == ffi.sizeof(entry_blob))
ffi.copy(entry, entry_blob, ffi.sizeof(entry_blob))
ffi.copy(entry, entry_blob, ffi.sizeof(entry))
self.softwires:add(entry.key, entry.value)
end

function BindingTable:remove_softwire_entry(entry_key_blob)
local entry = self.softwires.entry_type()
local entry = self.entry
assert(ffi.sizeof(entry.key) == ffi.sizeof(entry_key_blob))
ffi.copy(entry.key, entry_key_blob, ffi.sizeof(entry_key_blob))
ffi.copy(entry.key, entry_key_blob, ffi.sizeof(entry.key))
self.softwires:remove(entry.key)
end


function BindingTable:lookup(ipv4, port)
local lookup_key = self.entry.key
local psid = self:lookup_psid(ipv4, port)
lookup_key.ipv4 = ipv4
lookup_key.psid = psid
Expand Down Expand Up @@ -226,7 +233,7 @@ function BindingTable:iterate_softwires()
end

function pack_psid_map_entry (softwire)
local port_set = assert(softwire.value.port_set)
local port_set = assert(softwire.port_set)

local psid_length = port_set.psid_length
local shift = 16 - psid_length - (port_set.reserved_ports_bit_count or 0)
Expand All @@ -235,7 +242,7 @@ function pack_psid_map_entry (softwire)
("psid_length %s + shift %s should not exceed 16"):
format(psid_length, shift))

local key = softwire.key.ipv4
local key = softwire.ipv4
local value = {psid_length = psid_length, shift = shift}

return key, value
Expand All @@ -262,18 +269,33 @@ function load (conf)
self.keys[key] = value
end

for entry in conf.softwire:iterate() do
local softwires = ctable.new{
key_type = softwire_key_t,
value_type = softwire_value_t,
max_occupancy_rate = 0.4
}

local key, value = softwire_key_t(), softwire_value_t()
for _, entry in ipairs(conf.softwire) do
-- Add entry to binding table
key.ipv4 = entry.ipv4
key.psid = entry.psid
value.b4_ipv6 = entry.b4_ipv6
value.br_address = entry.br_address
softwires:add(key, value)

-- Check that the map either hasn't been added or that
-- it's the same value as one which has.
local psid_key, psid_value = pack_psid_map_entry(entry)
if not inter_psid_map:exists(psid_key, psid_value) then
inter_psid_map:add(psid_key, psid_value)
psid_builder:add(entry.key.ipv4, psid_value)
psid_builder:add(entry.ipv4, psid_value)
end
end

local psid_map = psid_builder:build(psid_map_value_t(), true)
return BindingTable.new(psid_map, conf.softwire)

return BindingTable.new(psid_map, softwires)
end

function selftest()
Expand Down
1 change: 0 additions & 1 deletion src/apps/lwaftr/lwutil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ local S = require("syscall")
local bit = require("bit")
local ffi = require("ffi")
local lib = require("core.lib")
local cltable = require("lib.cltable")
local binary = require("lib.yang.binary")

local band = bit.band
Expand Down
86 changes: 57 additions & 29 deletions src/core/group_freelist.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ local band = bit.band
--
-- NB: assumes 32-bit wide loads/stores are atomic (as is the fact on x86_64)!

-- Group freelist holds up to SIZE chunks of chunksize packets each
-- Group freelist holds up to n chunks of chunksize packets each
chunksize = 2048

-- (SIZE=1024)*(chunksize=2048) == roughly two million packets
local SIZE = 1024 -- must be a power of two
local MAX = SIZE - 1
-- (default_size=1024)*(chunksize=2048) == roughly two million packets
local default_size = 1024 -- must be a power of two

local CACHELINE = 64 -- XXX - make dynamic
local INT = ffi.sizeof("uint32_t")
Expand All @@ -35,47 +34,53 @@ struct group_freelist_chunk {

ffi.cdef([[
struct group_freelist {
uint32_t enqueue_pos[1];
uint8_t pad_enqueue_pos[]]..CACHELINE-1*INT..[[];
uint32_t enqueue_pos[1], enqueue_mask;
uint8_t pad_enqueue_pos[]]..CACHELINE-2*INT..[[];
uint32_t dequeue_pos[1];
uint8_t pad_dequeue_pos[]]..CACHELINE-1*INT..[[];
uint32_t dequeue_pos[1], dequeue_mask;
uint8_t pad_dequeue_pos[]]..CACHELINE-2*INT..[[];
struct group_freelist_chunk chunk[]]..SIZE..[[];
uint32_t size, state[1];
uint32_t state[1];
struct group_freelist_chunk chunk[?];
} __attribute__((packed, aligned(]]..CACHELINE..[[)))]])

-- Group freelists states
local CREATE, INIT, READY = 0, 1, 2

function freelist_create (name)
local fl = shm.create(name, "struct group_freelist")
function freelist_create (name, size)
size = size or default_size
assert(band(size, size-1) == 0, "size is not a power of two")

local fl = shm.create(name, "struct group_freelist", size)
if sync.cas(fl.state, CREATE, INIT) then
for i = 0, MAX do
fl.size = size
local mask = size - 1
fl.enqueue_mask, fl.dequeue_mask = mask, mask
for i = 0, fl.size-1 do
fl.chunk[i].sequence[0] = i
end
fl.state[0] = READY
assert(sync.cas(fl.state, INIT, READY))
return fl
else
waitfor(function () return fl.state[0] == READY end)
shm.unmap(fl)
return freelist_open(name)
end
return fl
end

function freelist_open (name, readonly)
local fl = shm.open(name, "struct group_freelist", readonly)
local fl = shm.open(name, "struct group_freelist", 'read-only', 1)
waitfor(function () return fl.state[0] == READY end)
return fl
end

local function mask (i)
return band(i, MAX)
local size = fl.size
shm.unmap(fl)
return shm.open(name, "struct group_freelist", readonly, size)
end

function start_add (fl)
local pos = fl.enqueue_pos[0]
local mask = fl.enqueue_mask
while true do
local chunk = fl.chunk[mask(pos)]
local chunk = fl.chunk[band(pos, mask)]
local seq = chunk.sequence[0]
local dif = seq - pos
if dif == 0 then
Expand All @@ -93,13 +98,14 @@ end

function start_remove (fl)
local pos = fl.dequeue_pos[0]
local mask = fl.dequeue_mask
while true do
local chunk = fl.chunk[mask(pos)]
local chunk = fl.chunk[band(pos, mask)]
local seq = chunk.sequence[0]
local dif = seq - (pos+1)
if dif == 0 then
if sync.cas(fl.dequeue_pos, pos, pos+1) then
return chunk, pos+MAX+1
return chunk, pos+mask+1
end
elseif dif < 0 then
return
Expand All @@ -114,8 +120,25 @@ function finish (chunk, seq)
chunk.sequence[0] = seq
end

local function occupied_chunks (fl)
local enqueue, dequeue = fl.enqueue_pos[0], fl.dequeue_pos[0]
if dequeue > enqueue then
return enqueue + fl.size - dequeue
else
return enqueue - dequeue
end
end

-- Register struct group_freelist as an abstract SHM object type so that
-- the group freelist can be recognized by shm.open_frame and described
-- with tostring().
shm.register('group_freelist', {open=freelist_open})
ffi.metatype("struct group_freelist", {__tostring = function (fl)
return ("%d/%d"):format(occupied_chunks(fl)*chunksize, fl.size*chunksize)
end})

function selftest ()
local fl = freelist_create("test_freelist")
local fl = freelist_create("test.group_freelist")
assert(not start_remove(fl)) -- empty

local w1, sw1 = start_add(fl)
Expand All @@ -133,13 +156,13 @@ function selftest ()
finish(r2, sr2)
assert(not start_remove(fl)) -- empty

for i=1,SIZE do
for i=1,fl.size do
local w, sw = start_add(fl)
assert(w)
finish(w, sw)
end
assert(not start_add(fl)) -- full
for i=1,SIZE do
for i=1,fl.size do
local r, sr = start_remove(fl)
assert(r)
finish(r, sr)
Expand All @@ -148,7 +171,7 @@ function selftest ()

local w = {}
for _=1,10000 do
for _=1,math.random(SIZE) do
for _=1,math.random(fl.size) do
local w1, sw = start_add(fl)
if not w1 then break end
finish(w1, sw)
Expand All @@ -160,4 +183,9 @@ function selftest ()
finish(r, sr)
end
end

local flro = freelist_open("test.group_freelist", 'read-only')
assert(flro.size == fl.size)
local objsize = ffi.sizeof("struct group_freelist", fl.size)
assert(ffi.C.memcmp(fl, flro, objsize) == 0)
end
2 changes: 2 additions & 0 deletions src/core/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ function equal (x, y)
elseif x == y then
return true
elseif type(x) == 'table' then
if getmetatable(x) then return false end
if getmetatable(y) then return false end
for k, v in pairs(x) do
if not equal(v, y[k]) then return false end
end
Expand Down
12 changes: 10 additions & 2 deletions src/core/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,16 @@ function initialize ()
end

function handler (reason)
print(reason)
print(STP.stacktrace())
local ok, bt = pcall(STP.stacktrace)
if ok and bt then
io.stderr:write(reason)
io.stderr:write("\n")
io.stderr:write(bt)
io.stderr:write("\n")
else
io.stderr:write(debug.traceback(reason))
io.stderr:write("\n")
end
if debug_on_error then debug.debug() end
os.exit(1)
end
Expand Down
Loading

0 comments on commit 885ac52

Please sign in to comment.