tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Lua in-kernel (lbuf library)
Hi folks,
It has been a long time since my GSoC project and though I have tried
to come back, I've experienced some personal issues. However, now I'm
coding again.
I'm developing a library to handle buffers in Lua, named lbuf. It is
been developed as part of my efforts to perform experimentation in
kernel network stack using Lua. Initially, I intended to bind mbuf to
allow, for example, to write protocols dissectors in Lua. For example,
calling a Lua function to inspect network packets:
function filter(packet)
if packet.field == value then return DROP end
return PASS
end
Thus, I started to design a Lua binding to mbuf inspired by '#pragma
pack' and bitfields of C lang. Then, I realized that this Lua library
could be useful to other kernel (and user-space) areas, such as device
drivers and user-level protocols. So, I started to develop this
binding generically as a independent library to give random access to
bits in a buffer. It is just in the early beginning, but I want to
share some thoughts.
Here are a draft of the lbuf API:
C API:
lbuf_new(lua_State L, void * buffer, size_t length, lua_Alloc free, bool net);
* creates a new lbuf userdatum and pushes it on the Lua stack. The net
flag indicates if it is necessary to perform endianness conversion.
Lua API:
- array access (1)
lbuf:mask(alignment [, offset, length])
buf[ix] ~> accesses 'alignment' bits from 'alignment*(ix -1)+offset' position
e.g.:
buf:mask(3)
buf[3] ~> accesses 3 bits from bit-6 position
- array access (2)
buf:mask{ length_pos1, length_pos2, ... }
buf[ix] ~> accesses 'length_pos(ix)' bits from 'length_pos1 + ...
length_pos(ix-1)' position
e.g.:
buf:mask{ 2, 2, 32, 9 }
buf[2] ~> accesses 2 bits from bit-2 position
- fields access
buf:mask{ field = { offset, length }, ... }
buf.field ~> 'field.length' bits from 'offset' position
e.g.:
buf:mask{
type = { 0, 2 },
-- 1 bit padding
flag = { 4, 1 },
xyz = { 15, 17 },
seg = {
flagX = { 32, 1 },
flagY = { 33, 1 },
flagZ = { 34, 1 },
}
}
buf.flag ~> 1 bit from bit-4 position
buf.xyz ~> 17 bits from bit-15 position
buf.seg.flagY ~> 1 bit from bit-34 position
- raw access
buf:rawget(3, 30) ~> gets 30 bits from bit-3 position
buf:rawset(3, 30, value) <~ sets 'value' into 30 bits from bit-3 position
- segment
buf:segment(offset [, length])
returns a new lbuf corresponding a 'buf' segment.
- mask reusing
lbuf.mask{ ... }
creates a mask without associating a specific buffer. Thus, you can
call buf:mask() passing a already created mask. For example:
ethernet_mask = lbuf.mask{ type = { ethertype_offset, ethertype_len }}
lldp_mask = lbuf.mask{ version = { version_offset, version_len }}
function filter(packet)
packet:mask(ethernet_mask)
if packet.type == 0x88CC then
lldp_pdu = packet.segment(payload_offset):mask(lldp_mask)
if packet.version < 1 return DROP end
end
return PASS
end
The code is hosted in https://github.com/lneto/lbuf. Currently, only
array and raw access are working (partially).
I think this API could be useful for device-driver and protocol
prototyping. Looking forward to hearing from you.
Regards,
--
Lourival Vieira Neto
Home |
Main Index |
Thread Index |
Old Index