Re: Lua in-kernel (lbuf library)

2013-11-04 Thread Lourival Vieira Neto
Hi Christoph,

Firstly, thanks for your comments. I really appreciated that =).

BTW, I renamed lbuf to Lua bitwiser and removed support for unamed
array access (buf:mask(alignment [, offset, length]) and buf:mask{
length_pos1, length_pos2, ... }). Instead, I introduced a new way to
provide array access (see below).

On Sun, Oct 20, 2013 at 8:05 PM, Christoph Badura b...@bsd.de wrote:
 On Tue, Oct 15, 2013 at 06:01:29PM -0300, Lourival Vieira Neto wrote:
  Also, having to switch mentally between zero-based arrays in the kernel C
  code and 1-based arrays in the Lua code make my head ache.
 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.

 When you create your own data structures, I guess it is a wash.  You have
 to adjust +/-1 in infrequent circumstances in either scenario.

 But in this case you are creating a special purpose language that operates
 in universe of zero-based array.  And that's not only the kernel code.
 Every Internet protocol specification that I remember is using zero-based
 indexing.  For someone dealing with both sides (the world and your lua
 library), it makes the difference between constantly having to be alert
 to remember to do the offset adjustment.  That is a lot more mental work
 for anyone working with this library.

 If you use 1-based indices talking to protocol people will be funny too:

 ``Anyone know why the flags in byte 6 of this packet are funny?''
 ``Sure, that's most likely because the flags are in byte 5.''

 I think it is worth thinking hard about this.

Yes.. I'll keep think on this. By now, I'm using 1-based indices to
Lua array-access on buffers and 0-based offsets to bitmask
definitions.

  I what is buffer and how does it relate to mbufs?
 Note, non-contiguous buffer still an open problem in lbuf. I don't
 know if should use a ptrdiff_t  to pass the distance to 'next' field,
 a 'next()' to return 'next' field or something else.

 You seem to be talking about implementation.  I was talking about the
 interface of the library.

Yes, sorry. In that stage, sometimes, it is a little difficult to
separate these things.

 However, you could create a lbuf from a mbuf header as follows:
   lbuf_new(L, mbuf-m_data, mbuf-m_len, NULL, true);

 I don't think that is a good way.  You say you want to inspect packet
 data in the kernel.  Well, the packet's data can be spread over a
 chain of mbufs.  Also, mbufs may have internal or externel storage.
 You don't want to deal with that as the user of your library.

 As a user, I want an interface like this:
   lbuf_from_mbuf(L, mbuf, NULL, true);

I'm thinking in providing an interface like this in an adapter layer.
Thus, we could use Lua bitwiser library in other areas. I was just
giving an example of how to use it with the current implementation
(again, sorry for don't separate interface discussion from
implementation).

 Yes, mea culpa =(. I wasn't clear about that. 'net' flag was the way I
 found to 'record' the buffer endianness. What means, true if the
 buffer uses BE and false if it uses HE. It has the same semantics of
 hton* and ntoh* functions. Don't know if it is better to pass the
 endianness itself as a flag (e.g., enum { BIG_ENDIAN, LITTLE_ENDIAN,
 HOST_ENDIAN }). What do you think?

 For me the the most convenient interface would be if I didn't have to
 mention the host byteorder.  Just record what byteorder the buffer is in,
 and convert when appropriate.  Alan made a good point.  It maybe be
 convenient and/or necessary to specify a different byteorder in a mask.

I'm working on it; thinking in the following form:

bitwiser.mask{ field = { offset, length, sign, endian, step }}, where
sign is a boolean, endian is a string like 'host', 'h', 'big', 'b',
'little', 'l', 'net' or 'n', and step is a number between [1, 64].

And (to allow omitting or non-ordering of parameters):

bitwiser.mask{ field =
  { __offset = offset, __length = length, __sign = sign, __endian =
endian, __step = step }}

defaults are __sign = true, __endian = 'host' and __step = undef. If
step is present or length is omitted, the lib assumes that it is a
segment field, what means that it should return a bitwiser.buffer
userdatum if accessed, which can be accessed like an array (using
step, if it is defined, or else the step of the original buffer to
determine the length of each field). It also could be masked to use
field access. For example:

m = bitwiser.mask{
  type  = { 0, 4 },
  flags = { 4, 4, __step = 1 },
  payload = { 8 }
}

b = bitwiser.buffer{ 0xff, 0, 0xff, 0 } -- new buffers have step = 8, by default
b[1] -- 0xff

b:mask(m)

b.flags[1] = false -- unsets bit-4 (0-based)
b.flags[4] -- returns bit-7 (0-based), 1 in this case

b.payload:mask{ padding = { 0, 8 }, data = { 8, __step = 16 } }
b.payload.data[1] -- returns 2 bytes from bit-16 (0-based) of the
original buffer,
  -- 0x00ff or 0xff00 depending on platform
endianess, in this case

   

Re: Lua in-kernel (lbuf library)

2013-11-04 Thread Lourival Vieira Neto
Hi Artem,

On Wed, Oct 23, 2013 at 5:10 PM, Artem Falcon lo...@gero.in wrote:
 On Tue, Oct 15, 2013 at 06:01:29PM -0300, Lourival Vieira Neto wrote:
   Also, having to switch mentally between zero-based arrays in the
   kernel C
   code and 1-based arrays in the Lua code make my head ache.

 Above this well-discussed inconvenience there is a thing which may hurt
 more. It's the Lua's stack-based C API and all the stack composition
 pottering it imposes on you. This may be customary for those having an
 experience with concatenative languages, but it'll be a source of errors
 for the others. See [1]'s Stack based API is harder for more on it.

 [1] http://julien.danjou.info/blog/2011/why-not-lua

 --
 dukzcry

Here is another nice discussion about C APIs of scripting languages:
www.inf.puc-rio.br/~roberto/docs/jucs-c-apis.pdf

Regards,
-- 
Lourival Vieira Neto


Re: Lua in-kernel (lbuf library)

2013-10-24 Thread Marc Balmer
Am 21.10.13 00:05, schrieb Christoph Badura:
 On Tue, Oct 15, 2013 at 06:01:29PM -0300, Lourival Vieira Neto wrote:
 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.
 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.
 
 When you create your own data structures, I guess it is a wash.  You have
 to adjust +/-1 in infrequent circumstances in either scenario.
 
 But in this case you are creating a special purpose language that operates
 in universe of zero-based array.  And that's not only the kernel code.
 Every Internet protocol specification that I remember is using zero-based
 indexing.  For someone dealing with both sides (the world and your lua
 library), it makes the difference between constantly having to be alert
 to remember to do the offset adjustment.  That is a lot more mental work
 for anyone working with this library.
 
 If you use 1-based indices talking to protocol people will be funny too:
 
 ``Anyone know why the flags in byte 6 of this packet are funny?''
 ``Sure, that's most likely because the flags are in byte 5.''
 
 I think it is worth thinking hard about this.
 
 From a cursory reading of the Wireshark Lua API, it seems to me they are
 using 0-based indices too.

It probably depends whether you are access a Lua table (where you'd
expect 1-based) or if you are accessin an in-kernel datastructure that
is not strictly a Lua table.  If a Lua function is to mimick an existing
C function, it might be better indeed to use 0-based access, to not
confuse developers who are probably familiar with the corresponding C
function.

As this is mostly a matter of taste/source of confusion, it should be
documented.  A man page for a Lua function that offers the same or
similar functionality as a C function should state whether it's 0-based
or 1-based, imo.

[...]




Re: Lua in-kernel (lbuf library)

2013-10-24 Thread Marc Balmer
Am 19.10.13 00:51, schrieb John Nemeth:

 } kern.lua.autoload is a safety barrier. One may wish not allow any lua kernel
 } script to load any given lua kernel module.
 
  The lua(4) implementers can certainly do this if they want.
 However, module_autoload() won't be looking at this flag and will
 continue to refuse to autoload any module that has the noautoload
 flag set.  Also, there is the kern.module.autoload sysctl that can
 prevent any module from autoloading.

And I think that is a good thing.  If kern.module.autoload is used to
prevent module autoloading, then lua(4) must not be a way to circumvent
this.

For clarification:  The kern.lua.autoload sysctl merely controls whether
lua(4) *tries* to autload a module when it encounters the require
statement.  If it is set to false, it will not try it.





Re: Lua in-kernel (lbuf library)

2013-10-23 Thread Artem Falcon
 On Tue, Oct 15, 2013 at 06:01:29PM -0300, Lourival Vieira Neto wrote:
   Also, having to switch mentally between zero-based arrays in the
   kernel C
   code and 1-based arrays in the Lua code make my head ache.

Above this well-discussed inconvenience there is a thing which may hurt
more. It's the Lua's stack-based C API and all the stack composition
pottering it imposes on you. This may be customary for those having an
experience with concatenative languages, but it'll be a source of errors
for the others. See [1]'s Stack based API is harder for more on it.

[1] http://julien.danjou.info/blog/2011/why-not-lua

--
dukzcry



Re: Lua in-kernel (lbuf library)

2013-10-20 Thread Christoph Badura
On Tue, Oct 15, 2013 at 06:01:29PM -0300, Lourival Vieira Neto wrote:
  Also, having to switch mentally between zero-based arrays in the kernel C
  code and 1-based arrays in the Lua code make my head ache.
 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.

When you create your own data structures, I guess it is a wash.  You have
to adjust +/-1 in infrequent circumstances in either scenario.

But in this case you are creating a special purpose language that operates
in universe of zero-based array.  And that's not only the kernel code.
Every Internet protocol specification that I remember is using zero-based
indexing.  For someone dealing with both sides (the world and your lua
library), it makes the difference between constantly having to be alert
to remember to do the offset adjustment.  That is a lot more mental work
for anyone working with this library.

If you use 1-based indices talking to protocol people will be funny too:

``Anyone know why the flags in byte 6 of this packet are funny?''
``Sure, that's most likely because the flags are in byte 5.''

I think it is worth thinking hard about this.

From a cursory reading of the Wireshark Lua API, it seems to me they are
using 0-based indices too.

  I what is buffer and how does it relate to mbufs?
 Note, non-contiguous buffer still an open problem in lbuf. I don't
 know if should use a ptrdiff_t  to pass the distance to 'next' field,
 a 'next()' to return 'next' field or something else.

You seem to be talking about implementation.  I was talking about the
interface of the library.

 However, you could create a lbuf from a mbuf header as follows:
   lbuf_new(L, mbuf-m_data, mbuf-m_len, NULL, true);

I don't think that is a good way.  You say you want to inspect packet
data in the kernel.  Well, the packet's data can be spread over a
chain of mbufs.  Also, mbufs may have internal or externel storage.
You don't want to deal with that as the user of your library.

As a user, I want an interface like this:
  lbuf_from_mbuf(L, mbuf, NULL, true);

That would make the contents of the mbuf chain starting at mbuf
available in an array-of-bytes like fashion.  Length isn't needed as
it is computed from the mbuf chain.

 Yes, mea culpa =(. I wasn't clear about that. 'net' flag was the way I
 found to 'record' the buffer endianness. What means, true if the
 buffer uses BE and false if it uses HE. It has the same semantics of
 hton* and ntoh* functions. Don't know if it is better to pass the
 endianness itself as a flag (e.g., enum { BIG_ENDIAN, LITTLE_ENDIAN,
 HOST_ENDIAN }). What do you think?

For me the the most convenient interface would be if I didn't have to
mention the host byteorder.  Just record what byteorder the buffer is in,
and convert when appropriate.  Alan made a good point.  It maybe be
convenient and/or necessary to specify a different byteorder in a mask.

   buf:rawget(0, 9) ~ if net flag is *true*: takes 16 bits from

You know, I think rawget is badly named.  Raw implies unmodified.
And byteswapping is a form of modification.  Maybe you can find a better
name.

  buf:mask(3)
  buf[3] ~ accesses 3 bits from bit-6 position
 
  What does that mean? Does it return the top-most 2 bits from the first
  byte plus the least significant bit fom the second byte of the buffer?
 
 It means the least-most 2 bits from the first byte and the LSB from the 
 second.

I don't know what least-most means.  But since you don't seem to
agree with my questions I assume you intend that to be the opposite of
top-most then your statement doesn't make sense to me.  Translated
into normal terms it would return bits 0 and 1 of the first byte and bit
0 of the second one.  They are not even contigous.

  What is 'length' for?
 
 Offset and length could be used to impose boundaries to the mask.

Don't tell it to me.  Write it into the documentation. :-)

  buf:mask{ 2, 2, 32, 9 }
  buf[2] ~ accesses 2 bits from bit-2 position
 
  What exactly would buf[3] return.  Please be explicit in whether you are
  counting byte offsets or bit offsets.  I can't figure that out from your
  description.
 
 It would return 32 bits (converted or not, depending on 'net' flag)
 from bit-4 (MSB-ordered).

From bit-4? From your own use of 1-based indices don't you mean the
5th bit?

  Personally, the idea of making array access to the buffer depend on
  state stored in the buffer does not look appealing to me.  It prevents
  buffers to be passed around because consumers don't know what they will
  get back on array access.
 
 I think it could be useful to access nonaligned and aligned data
 easily without caring about naming fields.

I guess I did not make myself understandable.  Storing that state globally
means that every function you hand an lbuf too has to set the global
mask before it accesses the lbuf, because it can't know if the current
mask is compatible with its own use.  And after call to a function, the
caller has to 

Re: Lua in-kernel (lbuf library)

2013-10-19 Thread Artem Falcon
18.10.2013, в 21:03, John Nemeth jnem...@cue.bc.ca написал(а):

 On Oct 18, 11:03am, Marc Balmer wrote:
 } Am 18.10.13 10:43, schrieb Artem Falcon:
 }  Marc Balmer marc at msys.ch writes:
 }  Justin Cormack justin at specialbusservice.com writes:
 }  I have been using the luajit ffi and luaffi, which let you directly
 }  use C structs (with bitfields) in Lua to do this. It makes it easier
 }  to reuse stuff that is already defined in C. (luaffi is not in its
 }  current state portable but my plan is to strip out the non portable
 }  bits, which are the function call support).
 } 
 }  Justin
 }  
 }  I had successfully used more lightweight solution called Lua AutoC [1] 
 with
 }  Marc's lua(4).
 }  Pros: light in comparison to other FFI libs, joy in use, easy to adopt to 
 be
 }  used in kernel, does the things in runtime, which gives the flexibility.
 }  Cons: not widely tested, again does the things in runtime, which on other
 }  side may give performance penalty.
 }  
 } 
 }  I never used luaffi. It sounds very interesting and I think it could
 }  be very useful to bind already defined C structs, but my purpose is to
 }  dynamically define data layouts using Lua syntax (without parsing C
 }  code).
 } 
 }  FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
 }  for code, but with an FFI a Lua script can access almost anything in the
 }  kernel.  One has to think twice if one wants that.
 } 
 }  Well, assuming it would be module, so I would not have to load it if I
 }  don't want to.
 }  
 }  It's desirable if you're writing a device driver in Lua, as you can do
 }  most of work from Lua code (e.g. call C methods of NetBSD driver API
 }  and feed them with C structs and pointers).
 }  States and explicit exports of a certain foreign functions makes things
 }  a bit less dangerous.
 }  But in general you're right, one should do this with care.
 } 
 } lua(4) has a mechanism for Lua's 'require' statement.  Normally, when
 } you require 'foo', it looks up wheter a kernel module name luafoo exists
 } and loads it.  This automatic loading of modules can be turned off, to
 } make a module available to a state, it has to be specifically assigned.
 }  So when you turn autoloading off, a script could not simply call a ffi
 } module by requiring it.
 } 
 } Maybe Lua kernel modules should carry a flag whether they should allow
 } autoloading or not?  This way, an ffi module would still be loaded into
 } the kernel when Lua code requires it, but lua(4) would detect the don't
 } autoload flag and would then not_ assign the module to the Lua state.

Probably. It should be named as 'auto assign' for clarity, as module loading
occurs anyway.

 There is already a mechanism for this, see module_autoload(9).
 You should always be using module_autoload() to load a module from
 inside the kernel.  If the no autoload flag is set, then the call
 will fail.  

This is exactly what lua(4) does on 'requiring'.

 Thus, there is no need for lua(4) to try managing this
 itself.  It should just attempt to load the module.  If successful,
 great.  If not, then the feature being requested isn't available.

kern.lua.autoload is a safety barrier. One may wish not allow any lua kernel
script to load any given lua kernel module.

 
 }  [1] https://github.com/orangeduck/LuaAutoC
 } 
 }-- End of excerpt from Marc Balmer


--
dukzcry







Re: Lua in-kernel (lbuf library)

2013-10-19 Thread Alexander Nasonov
Terry Moore wrote:
 Just to clarify a bit
 
  Indeed, we started with Lua because AWK was not embeddable and because of
  the 1-origin issue. 
 
 We thought, mistakenly, that a language that didn't look very much like C
 would cause fewer problems because of the 0-origin / 1-origin difference.
 Apparently, however, it's a deeper habit of thought. Ditto for the string
 escape sequences. Apparently the '[' and ']' for indexing, and the '\' for
 character escapes, trigger very deeply seated patterns.

While I agree that 0-1 switch is mentally hard [*] but if you often need
to access arrays by index in Lua code then you either solving a wrong
problem of doing something a wrong way.

Lua is designed to be a glue language. If you need arrays (as opposite
to collections which can be iterated over with ipairs/pairs/iterators),
then you're likely doing low-level C stuff in Lua.

Data structures in kernel are often organized as linked lists. To
iterate from Lua, you probably want to write an iterator and also
a lookup function.

Lets say you want to iterate over all ps processes from ddb (if gdb
has python support, why can't we have a cooler thing?). You do this:

ddb lua on
ddb for p in processes:match(ps) do print(p.pid) end
906
2245
4935
...
ddb =processes:find(1).path
/sbin/init
ddb lua off

You can do a lot without ever accessing elements by integer indices.

 Based on our experience, it seems risky to use Lua to implement code that
 interoperates with kernel-like C code in security-critical contexts. We
 found this risk to be insurmountable. Engineers who are used to zero-origin
 code, and who are looking at zero-origin code for reference, will make
 zero-origin mistakes. 

Again, don't do C stuff in Lua. However, there is a different kind of
risk when developing security code in Lua: it's the layers of Lua
itselft. Any complex layer introduces a non-neglidgible risk.

[*] I found it out while developing mixed Lua-C module which could also
detect LuaJIT and use its zero-based FFI structures.

Alex


Re: Lua in-kernel (lbuf library)

2013-10-19 Thread Marc Balmer
Am 19.10.13 14:02, schrieb Alexander Nasonov:

[...]

 Lets say you want to iterate over all ps processes from ddb (if gdb
 has python support, why can't we have a cooler thing?). You do this:
 
 ddb lua on
 ddb for p in processes:match(ps) do print(p.pid) end
 906
 2245
 4935
 ...
 ddb =processes:find(1).path
 /sbin/init
 ddb lua off
 
 You can do a lot without ever accessing elements by integer indices.

Actually it would be quite nice to have a 'lua' command in ddb (instead
of 'lua on' that drops you in an interactive Lua mode, like the 'lua'
command line command.  As the system is perhaps in a weird state when
ddb is entered, it would be a good idea when the Lua state for ddb would
have been created e.g. during system startup, and maybe during normal
system operation, luactl(8) could be used to load scripts into it, which
can define functions that will be available once ddb is entered.

for those planning to tinker which such stuff, don't only look at the
Lua C API, but especially try to understand Lua's metatable concept.
This is where the real strength and power of Lua comes from.  You can
e.g. define what 'foo.bar' or 'bla.foo = 42' really means.


Re: Lua in-kernel (lbuf library)

2013-10-18 Thread Artem Falcon
Marc Balmer marc at msys.ch writes:
  Justin Cormack justin at specialbusservice.com writes:
  I have been using the luajit ffi and luaffi, which let you directly
  use C structs (with bitfields) in Lua to do this. It makes it easier
  to reuse stuff that is already defined in C. (luaffi is not in its
  current state portable but my plan is to strip out the non portable
  bits, which are the function call support).
 
  Justin

I had successfully used more lightweight solution called Lua AutoC [1] with
Marc's lua(4).
Pros: light in comparison to other FFI libs, joy in use, easy to adopt to be
used in kernel, does the things in runtime, which gives the flexibility.
Cons: not widely tested, again does the things in runtime, which on other
side may give performance penalty.

  
  I never used luaffi. It sounds very interesting and I think it could
  be very useful to bind already defined C structs, but my purpose is to
  dynamically define data layouts using Lua syntax (without parsing C
  code).
 
 FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
 for code, but with an FFI a Lua script can access almost anything in the
 kernel.  One has to think twice if one wants that.
 
 Well, assuming it would be module, so I would not have to load it if I
 don't want to.

It's desirable if you're writing a device driver in Lua, as you can do
most of work from Lua code (e.g. call C methods of NetBSD driver API
and feed them with C structs and pointers).
States and explicit exports of a certain foreign functions makes things
a bit less dangerous.
But in general you're right, one should do this with care.

[1] https://github.com/orangeduck/LuaAutoC



Re: Lua in-kernel (lbuf library)

2013-10-18 Thread Artem Falcon
Lourival Vieira Neto lourival.neto at gmail.com writes:

 
 On Wed, Oct 16, 2013 at 11:45 AM, Justin Cormack
 justin at specialbusservice.com wrote:
 (...)
  Yes absolutely it makes more sense if already defined in C. For parsing
  binary stuff I would look at Erlang for inspiration too, it is one of the
  nicer designs.
 
  Justin
 
 I never gone that far in Erlang. It looks really interesting [1]. I'll
 take a deeper look later. Thanks!
 
 Regards,

I think a hybrid approach with mutable C-like data structs for holding
of binary data and Erlang's binary pattern matching would be cool.

--
dukzcry



Re: Lua in-kernel (lbuf library)

2013-10-18 Thread Marc Balmer
Am 18.10.13 10:43, schrieb Artem Falcon:
 Marc Balmer marc at msys.ch writes:
 Justin Cormack justin at specialbusservice.com writes:
 I have been using the luajit ffi and luaffi, which let you directly
 use C structs (with bitfields) in Lua to do this. It makes it easier
 to reuse stuff that is already defined in C. (luaffi is not in its
 current state portable but my plan is to strip out the non portable
 bits, which are the function call support).

 Justin
 
 I had successfully used more lightweight solution called Lua AutoC [1] with
 Marc's lua(4).
 Pros: light in comparison to other FFI libs, joy in use, easy to adopt to be
 used in kernel, does the things in runtime, which gives the flexibility.
 Cons: not widely tested, again does the things in runtime, which on other
 side may give performance penalty.
 

 I never used luaffi. It sounds very interesting and I think it could
 be very useful to bind already defined C structs, but my purpose is to
 dynamically define data layouts using Lua syntax (without parsing C
 code).

 FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
 for code, but with an FFI a Lua script can access almost anything in the
 kernel.  One has to think twice if one wants that.

 Well, assuming it would be module, so I would not have to load it if I
 don't want to.
 
 It's desirable if you're writing a device driver in Lua, as you can do
 most of work from Lua code (e.g. call C methods of NetBSD driver API
 and feed them with C structs and pointers).
 States and explicit exports of a certain foreign functions makes things
 a bit less dangerous.
 But in general you're right, one should do this with care.

lua(4) has a mechanism for Lua's 'require' statement.  Normally, when
you require 'foo', it looks up wheter a kernel module name luafoo exists
and loads it.  This automatic loading of modules can be turned off, to
make a module available to a state, it has to be specifically assigned.
 So when you turn autoloading off, a script could not simply call a ffi
module by requiring it.

Maybe Lua kernel modules should carry a flag whether they should allow
autoloading or not?  This way, an ffi module would still be loaded into
the kernel when Lua code requires it, but lua(4) would detect the don't
autoload flag and would then not_ assign the module to the Lua state.

 
 [1] https://github.com/orangeduck/LuaAutoC
 



Re: Lua in-kernel (lbuf library)

2013-10-18 Thread John Nemeth
On Oct 18, 11:03am, Marc Balmer wrote:
} Am 18.10.13 10:43, schrieb Artem Falcon:
}  Marc Balmer marc at msys.ch writes:
}  Justin Cormack justin at specialbusservice.com writes:
}  I have been using the luajit ffi and luaffi, which let you directly
}  use C structs (with bitfields) in Lua to do this. It makes it easier
}  to reuse stuff that is already defined in C. (luaffi is not in its
}  current state portable but my plan is to strip out the non portable
}  bits, which are the function call support).
} 
}  Justin
}  
}  I had successfully used more lightweight solution called Lua AutoC [1] 
with
}  Marc's lua(4).
}  Pros: light in comparison to other FFI libs, joy in use, easy to adopt to be
}  used in kernel, does the things in runtime, which gives the flexibility.
}  Cons: not widely tested, again does the things in runtime, which on other
}  side may give performance penalty.
}  
} 
}  I never used luaffi. It sounds very interesting and I think it could
}  be very useful to bind already defined C structs, but my purpose is to
}  dynamically define data layouts using Lua syntax (without parsing C
}  code).
} 
}  FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
}  for code, but with an FFI a Lua script can access almost anything in the
}  kernel.  One has to think twice if one wants that.
} 
}  Well, assuming it would be module, so I would not have to load it if I
}  don't want to.
}  
}  It's desirable if you're writing a device driver in Lua, as you can do
}  most of work from Lua code (e.g. call C methods of NetBSD driver API
}  and feed them with C structs and pointers).
}  States and explicit exports of a certain foreign functions makes things
}  a bit less dangerous.
}  But in general you're right, one should do this with care.
} 
} lua(4) has a mechanism for Lua's 'require' statement.  Normally, when
} you require 'foo', it looks up wheter a kernel module name luafoo exists
} and loads it.  This automatic loading of modules can be turned off, to
} make a module available to a state, it has to be specifically assigned.
}  So when you turn autoloading off, a script could not simply call a ffi
} module by requiring it.
} 
} Maybe Lua kernel modules should carry a flag whether they should allow
} autoloading or not?  This way, an ffi module would still be loaded into
} the kernel when Lua code requires it, but lua(4) would detect the don't
} autoload flag and would then not_ assign the module to the Lua state.

 There is already a mechanism for this, see module_autoload(9).
You should always be using module_autoload() to load a module from
inside the kernel.  If the no autoload flag is set, then the call
will fail.  Thus, there is no need for lua(4) to try managing this
itself.  It should just attempt to load the module.  If successful,
great.  If not, then the feature being requested isn't available.

}  [1] https://github.com/orangeduck/LuaAutoC
} 
}-- End of excerpt from Marc Balmer


Re: Lua in-kernel (lbuf library)

2013-10-18 Thread Mindaugas Rasiukevicius
Terry Moore t...@mcci.com wrote:
 ...
 
 But it was really, really difficult for our embedded C programmers to use.
 
 We found the following areas of constant problem:
 
 1) zero origin versus 1-origin arrays were a constant source of bugs,
 particularly when interoperating with C code. 
 
 2) the string escape sequences are almost but not completely compatible
 with C. In particular, in C, \123 is interpreted as octal, but in Lua
 \123 is decimal. This was a constant source of trouble.
 
 3) the fact that a reference uninitialized variable or missing array
 element returns nil instead of throwing an exception is problematic for
 writing significant code that is intended to be reliable -- errors are
 hidden.
 
 4) the Lua APIs are not a platform -- they change from version to version.
 (Working with Lua APIs and trying to track current is like working with
 certain open-source kernels -- you really can't maintain your investment.)
 
 And so forth. All of these decisions are actually fine, in context of a
 scripting language that's a world unto itself. But as a tool to give C
 programmers, they collectively were a real barrier to adoption.
 
 To address this, and to make it more palatable to our developers, after
 two years or so of experience (in 2002) MCCI forked the Lua interpreter
 and created a C-like variant (with renamed, stable APIs to address #4, and
 C-like syntax).  There was a paper on this at the Lua conference in 2008:
 http://www.lua.org/wshop08.html#moore
 
 With that, we've been happily using something based on Lua, and I can
 agree with all the Lua enthusiasts: it's a great tool.  If we weren't an
 entirely C-based company, we would not have bothered with the language
 changes (though we might have created stable APIs with non-clashing
 names).
 
 I'm not promoting our version as a solution. I am, however, pointing out
 that items #1 and #2 above merit careful consideration before putting Lua
 into a security-critical environment; C programmers won't like reviewing
 the code (and will tend to miss things).

Yet again, this whole story just makes me wonder why AWK has never
evolved to be more powerful language for this kind of purpose (Perl is
not the direction I am talking about).  Certainly, simplicity of AWK
is valued.  However, it does not mean that it should have just stopped
evolving at some point in history.

Even if its functions use 1-origin for arrays, the language itself is
much more natural for the C programmers and the UNIX world.  Personally,
I would love to see more advanced AWK with just-in-time compilation..

-- 
Mindaugas


Re: Lua in-kernel (lbuf library)

2013-10-18 Thread John Nemeth
On Oct 19, 12:13am, Artem Falcon wrote:
} 18.10.2013, × 21:03, John Nemeth jnem...@cue.bc.ca wrote:
}  On Oct 18, 11:03am, Marc Balmer wrote:
}  } Am 18.10.13 10:43, schrieb Artem Falcon:
}  }  Marc Balmer marc at msys.ch writes:
}  }  Justin Cormack justin at specialbusservice.com writes:
}  }  I have been using the luajit ffi and luaffi, which let you directly
}  }  use C structs (with bitfields) in Lua to do this. It makes it easier
}  }  to reuse stuff that is already defined in C. (luaffi is not in its
}  }  current state portable but my plan is to strip out the non portable
}  }  bits, which are the function call support).
}  } 
}  }  Justin
}  }  
}  }  I had successfully used more lightweight solution called Lua AutoC 
[1] with
}  }  Marc's lua(4).
}  }  Pros: light in comparison to other FFI libs, joy in use, easy to adopt 
to be
}  }  used in kernel, does the things in runtime, which gives the flexibility.
}  }  Cons: not widely tested, again does the things in runtime, which on 
other
}  }  side may give performance penalty.
}  }  
}  } 
}  }  I never used luaffi. It sounds very interesting and I think it could
}  }  be very useful to bind already defined C structs, but my purpose is to
}  }  dynamically define data layouts using Lua syntax (without parsing C
}  }  code).
}  } 
}  }  FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
}  }  for code, but with an FFI a Lua script can access almost anything in 
the
}  }  kernel.  One has to think twice if one wants that.
}  } 
}  }  Well, assuming it would be module, so I would not have to load it if I
}  }  don't want to.
}  }  
}  }  It's desirable if you're writing a device driver in Lua, as you can do
}  }  most of work from Lua code (e.g. call C methods of NetBSD driver API
}  }  and feed them with C structs and pointers).
}  }  States and explicit exports of a certain foreign functions makes things
}  }  a bit less dangerous.
}  }  But in general you're right, one should do this with care.
}  } 
}  } lua(4) has a mechanism for Lua's 'require' statement.  Normally, when
}  } you require 'foo', it looks up wheter a kernel module name luafoo exists
}  } and loads it.  This automatic loading of modules can be turned off, to
}  } make a module available to a state, it has to be specifically assigned.
}  }  So when you turn autoloading off, a script could not simply call a ffi
}  } module by requiring it.
}  } 
}  } Maybe Lua kernel modules should carry a flag whether they should allow
}  } autoloading or not?  This way, an ffi module would still be loaded into
}  } the kernel when Lua code requires it, but lua(4) would detect the don't
}  } autoload flag and would then not_ assign the module to the Lua state.
} 
} Probably. It should be named as 'auto assign' for clarity, as module loading
} occurs anyway.
} 
}  There is already a mechanism for this, see module_autoload(9).
}  You should always be using module_autoload() to load a module from
}  inside the kernel.  If the noautoload flag is set, then the call
}  will fail.  
} 
} This is exactly what lua(4) does on 'requiring'.
} 
}  Thus, there is no need for lua(4) to try managing this
}  itself.  It should just attempt to load the module.  If successful,
}  great.  If not, then the feature being requested isn't available.
} 
} kern.lua.autoload is a safety barrier. One may wish not allow any lua kernel
} script to load any given lua kernel module.

 The lua(4) implementers can certainly do this if they want.
However, module_autoload() won't be looking at this flag and will
continue to refuse to autoload any module that has the noautoload
flag set.  Also, there is the kern.module.autoload sysctl that can
prevent any module from autoloading.

}-- End of excerpt from Artem Falcon


RE: Lua in-kernel (lbuf library)

2013-10-18 Thread Terry Moore
 Yet again, this whole story just makes me wonder why AWK has never
 evolved to be more powerful language for this kind of purpose (Perl is
 not the direction I am talking about).  Certainly, simplicity of AWK
 is valued.  However, it does not mean that it should have just stopped
 evolving at some point in history.
 
 Even if its functions use 1-origin for arrays, the language itself is
 much more natural for the C programmers and the UNIX world.  Personally,
 I would love to see more advanced AWK with just-in-time compilation..

Indeed, we started with Lua because AWK was not embeddable and because of
the 1-origin issue. (Also, because Lua supports closures; closures are
really a very economical way of expressing certain kinds of operations.) But
we had 10 years or so of using AWK, wrapped by sh, as a cross UNIX platform.
Unfortunately, it didn't work well for Windows in those days.  And sh
scripts still don't, Cygwin notwithstanding.

But for many things we still use AWK.

--Terry



RE: Lua in-kernel (lbuf library)

2013-10-18 Thread Terry Moore
Just to clarify a bit

 Indeed, we started with Lua because AWK was not embeddable and because of
 the 1-origin issue. 

We thought, mistakenly, that a language that didn't look very much like C
would cause fewer problems because of the 0-origin / 1-origin difference.
Apparently, however, it's a deeper habit of thought. Ditto for the string
escape sequences. Apparently the '[' and ']' for indexing, and the '\' for
character escapes, trigger very deeply seated patterns.

Based on our experience, it seems risky to use Lua to implement code that
interoperates with kernel-like C code in security-critical contexts. We
found this risk to be insurmountable. Engineers who are used to zero-origin
code, and who are looking at zero-origin code for reference, will make
zero-origin mistakes. 

This is not an argument against using Lua in user mode. However, given that
the motto of NetBSD for kernel work is read the source, I worry that this
human-factors issue will be hard to mitigate when using Lua in kernel mode.

--Terry



RE: Lua in-kernel (lbuf library)

2013-10-17 Thread Terry Moore
HI,

I'm replying to a message that was on tech-userlevel@.  I'm not sure why a
discussion of in-kernel Lua was on tech-userlevel@. I see that other related
messages were on tech-kern@, so I'm posting my reply there.

My company has quite a bit of experience using Lua as a scripting language
-- since 2000.  Lua has many advantages and I like it very much. 

But it was really, really difficult for our embedded C programmers to use.

We found the following areas of constant problem:

1) zero origin versus 1-origin arrays were a constant source of bugs,
particularly when interoperating with C code. 

2) the string escape sequences are almost but not completely compatible with
C. In particular, in C, \123 is interpreted as octal, but in Lua \123 is
decimal. This was a constant source of trouble.

3) the fact that a reference uninitialized variable or missing array element
returns nil instead of throwing an exception is problematic for writing
significant code that is intended to be reliable -- errors are hidden.

4) the Lua APIs are not a platform -- they change from version to version.
(Working with Lua APIs and trying to track current is like working with
certain open-source kernels -- you really can't maintain your investment.)

And so forth. All of these decisions are actually fine, in context of a
scripting language that's a world unto itself. But as a tool to give C
programmers, they collectively were a real barrier to adoption.

To address this, and to make it more palatable to our developers, after two
years or so of experience (in 2002) MCCI forked the Lua interpreter and
created a C-like variant (with renamed, stable APIs to address #4, and
C-like syntax).  There was a paper on this at the Lua conference in 2008:
http://www.lua.org/wshop08.html#moore

With that, we've been happily using something based on Lua, and I can agree
with all the Lua enthusiasts: it's a great tool.  If we weren't an entirely
C-based company, we would not have bothered with the language changes
(though we might have created stable APIs with non-clashing names).

I'm not promoting our version as a solution. I am, however, pointing out
that items #1 and #2 above merit careful consideration before putting Lua
into a security-critical environment; C programmers won't like reviewing the
code (and will tend to miss things).

Best regards,
--Terry

 -Original Message-
 From: tech-userlevel-ow...@netbsd.org [mailto:tech-userlevel-
 ow...@netbsd.org] On Behalf Of Mouse
 Sent: Wednesday, October 16, 2013 13:18
 To: tech-userle...@netbsd.org
 Subject: Re: Lua in-kernel (lbuf library)
 
  [...0-origin vs 1-origin arrays...]
  It is hard to tell what is the least astonishing here.
 
 Well, least astonishing to whom, is really the question, it seems to
 me.  Certainly I, as a C coder with no Lua experience, would find
 0-origin arrays less astonishing.  Someone with the converse experience
 would presumably have the opposite reaction.
 
  You propose Lua as a language embedded into C rather than separate
  one.  I'd say that Lua designers made wrong decision here.
 
 Only if you think of Lua as being designed for embedding in C.  It's
 just as coherent to think of the mistake as being trying to wed a
 language with 1-origin arrays with a language with 0-origin arrays.
 
 /~\ The ASCII   Mouse
 \ / Ribbon Campaign
  X  Against HTML  mo...@rodents-montreal.org
 / \ Email! 7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B



Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Marc Balmer
Am 15.10.13 23:01, schrieb Lourival Vieira Neto:

[...]

 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.
 
 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.

In C an array index is actually an offset from the top, so 0 is the
natural way to denote element nr. 1 in C.  In Lua, a numeric array index
is not an offset, but the ordinal array position.  So 1 is the natural
way to denote the first element.

Strictly speaking, it's actually C that is weird:  Index n denotes array
element n + 1...

Following the principle of least astonishment, I would not recommend
starting to do 0 based stuff in Lua, a Lua programmer certainly expects
things to start at 1.

[...]


Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Lourival Vieira Neto
Hi Justin,

On Tue, Oct 15, 2013 at 7:38 PM, Justin Cormack
jus...@specialbusservice.com wrote:
 On Thu, Oct 10, 2013 at 7:15 PM, Lourival Vieira Neto
 lourival.n...@gmail.com wrote:
 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.

 I have been using the luajit ffi and luaffi, which let you directly
 use C structs (with bitfields) in Lua to do this. It makes it easier
 to reuse stuff that is already defined in C. (luaffi is not in its
 current state portable but my plan is to strip out the non portable
 bits, which are the function call support).

 Justin

I never used luaffi. It sounds very interesting and I think it could
be very useful to bind already defined C structs, but my purpose is to
dynamically define data layouts using Lua syntax (without parsing C
code).

Regards,
-- 
Lourival Vieira Neto


Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Lourival Vieira Neto
On Wed, Oct 16, 2013 at 3:50 AM, Marc Balmer m...@msys.ch wrote:
 Am 15.10.13 23:01, schrieb Lourival Vieira Neto:

 [...]

 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.

 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.

 In C an array index is actually an offset from the top, so 0 is the
 natural way to denote element nr. 1 in C.  In Lua, a numeric array index
 is not an offset, but the ordinal array position.  So 1 is the natural
 way to denote the first element.

 Strictly speaking, it's actually C that is weird:  Index n denotes array
 element n + 1...

 Following the principle of least astonishment, I would not recommend
 starting to do 0 based stuff in Lua, a Lua programmer certainly expects
 things to start at 1.

 [...]

Indeed.
-- 
Lourival Vieira Neto


Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Justin Cormack
On 16 Oct 2013 15:41, Lourival Vieira Neto lourival.n...@gmail.com
wrote:

 Hi Justin,

 On Tue, Oct 15, 2013 at 7:38 PM, Justin Cormack
 jus...@specialbusservice.com wrote:
  On Thu, Oct 10, 2013 at 7:15 PM, Lourival Vieira Neto
  lourival.n...@gmail.com wrote:
  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.
 
  I have been using the luajit ffi and luaffi, which let you directly
  use C structs (with bitfields) in Lua to do this. It makes it easier
  to reuse stuff that is already defined in C. (luaffi is not in its
  current state portable but my plan is to strip out the non portable
  bits, which are the function call support).
 
  Justin

 I never used luaffi. It sounds very interesting and I think it could
 be very useful to bind already defined C structs, but my purpose is to
 dynamically define data layouts using Lua syntax (without parsing C
 code).


Yes absolutely it makes more sense if already defined in C. For parsing
binary stuff I would look at Erlang for inspiration too, it is one of the
nicer designs.

Justin


Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Marc Balmer
Am 16.10.13 16:41, schrieb Lourival Vieira Neto:
 Hi Justin,
 
 On Tue, Oct 15, 2013 at 7:38 PM, Justin Cormack
 jus...@specialbusservice.com wrote:
 On Thu, Oct 10, 2013 at 7:15 PM, Lourival Vieira Neto
 lourival.n...@gmail.com wrote:
 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.

 I have been using the luajit ffi and luaffi, which let you directly
 use C structs (with bitfields) in Lua to do this. It makes it easier
 to reuse stuff that is already defined in C. (luaffi is not in its
 current state portable but my plan is to strip out the non portable
 bits, which are the function call support).

 Justin
 
 I never used luaffi. It sounds very interesting and I think it could
 be very useful to bind already defined C structs, but my purpose is to
 dynamically define data layouts using Lua syntax (without parsing C
 code).

FFI in the kernel can be dangerous.  Pure Lua is a perfect confinment
for code, but with an FFI a Lua script can access almost anything in the
kernel.  One has to think twice if one wants that.

Well, assuming it would be module, so I would not have to load it if I
don't want to.





Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Aleksej Saushev
Marc Balmer m...@msys.ch writes:

 Am 15.10.13 23:01, schrieb Lourival Vieira Neto:

 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.
 
 It's something that doesn't bug me so much.. But, if necessary it
 could be changed to 0-based in this userdata.

 In C an array index is actually an offset from the top, so 0 is the
 natural way to denote element nr. 1 in C.  In Lua, a numeric array index
 is not an offset, but the ordinal array position.  So 1 is the natural
 way to denote the first element.

 Strictly speaking, it's actually C that is weird:  Index n denotes array
 element n + 1...

This depends on your background. If you studied or dealt with mathematical 
logic,
set theory, or foundations of mathematics, then you start counting natural 
numbers
(ordinals) from 0. In this respect C is more logical (pun intended) than Lua.

 Following the principle of least astonishment, I would not recommend
 starting to do 0 based stuff in Lua, a Lua programmer certainly expects
 things to start at 1.

It is hard to tell what is the least astonishing here. You propose Lua
as a language embedded into C rather than separate one. I'd say that Lua
designers made wrong decision here.


-- 
BCE HA MOPE!



Re: Lua in-kernel (lbuf library)

2013-10-16 Thread Lourival Vieira Neto
On Wed, Oct 16, 2013 at 11:45 AM, Justin Cormack
jus...@specialbusservice.com wrote:
(...)
 Yes absolutely it makes more sense if already defined in C. For parsing
 binary stuff I would look at Erlang for inspiration too, it is one of the
 nicer designs.

 Justin

I never gone that far in Erlang. It looks really interesting [1]. I'll
take a deeper look later. Thanks!

Regards,
-- 
Lourival Vieira Neto


Re: Lua in-kernel (lbuf library)

2013-10-15 Thread Lourival Vieira Neto
Hi Christoph,

On Mon, Oct 14, 2013 at 10:02 AM, Christoph Badura b...@bsd.de wrote:
 First, I find the usage of the buf terminology confusing.  In kernel
 context I associate buf with the file system buffe cache buf structure.
 Packet buffers a called mbufs.  I would appreciate it if the terminology
 was consistent with the kernel or at least not confusing.

This is due my lack of creativeness =).. I'm quite open for naming suggestions.

 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.

It's something that doesn't bug me so much.. But, if necessary it
could be changed to 0-based in this userdata.

 On Thu, Oct 10, 2013 at 03:15:54PM -0300, Lourival Vieira Neto wrote:
 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.

 I what is buffer and how does it relate to mbufs?  How do I create a new
 lbuf from an mbuf? Or from an array of bytes?

Note, non-contiguous buffer still an open problem in lbuf. I don't
know if should use a ptrdiff_t  to pass the distance to 'next' field,
a 'next()' to return 'next' field or something else.

However, you could create a lbuf from a mbuf header as follows:

  lbuf_new(L, mbuf-m_data, mbuf-m_len, NULL, true);

or from an array:

  uint8_t array[ N ];
  lbuf_new(L, (void *) array, N, NULL, false); // 'false' means 'use
the platform endianess'

Then, you could call a Lua function passing this lbuf, for example:

  lua_getglobal(L, handler);
  lbuf_new(L, mbuf-m_data, mbuf-m_len, NULL, true);
  lua_pcall(L, 1, 0, 0);

 In order to indicate that endianness conversion is necessary I need to
 know the future uses of the buffer.  Clairvoyance excepted, that is kinda
 hard.

It's a generic data structure that could be used to handle bit fields
or nonaligned data.

 If you are going to make the buffers endianness aware, why not record the
 endianness that the packet is encoded in.  And byteswapping can be
 performed automatically depending on the consumers endianness.  I think
 this way a lot of redundant code can be avoided.

 And you don't describe under what circumstances endianness convresion is
 performed.

Yes, mea culpa =(. I wasn't clear about that. 'net' flag was the way I
found to 'record' the buffer endianness. What means, true if the
buffer uses BE and false if it uses HE. It has the same semantics of
hton* and ntoh* functions. Don't know if it is better to pass the
endianness itself as a flag (e.g., enum { BIG_ENDIAN, LITTLE_ENDIAN,
HOST_ENDIAN }). What do you think?

So, if you set net flag true when you access a bit field, the
conversion to and from big endian, if needed, is done automatically
taking the smaller aligned set of bits. For example:

  buf:rawget(0, 9) ~ if net flag is *true*: takes 16 bits from
beginning of the buffer (as is); convert these 2 bytes from BE to HE
(if necessary); and returns these 2 bytes masked to preserve only the
most significant 9 bits (zeroing the remaining bits) and shifted to
LSB. If net is *false*: just returns the first 2 bytes masked and
shifted (without conversion). Then these 2 bytes are expanded to
lua_Number type (int64_t in kernel)

That is:

a) If net flag is _true_ and the platform is LE:
1- Takes 16 bits:
[ b0  | b1  | b2  | b3  | b4  | b5  | b6  | b7  ][ b8  | b9  | b10 |
b11 | b12 | b13 | b14 | b15 ]

2- Convert it to LE:
[ b8  | b9  | b10 | b11 | b12 | b13 | b14 | b15 ][ b0  | b1  | b2  |
b3  | b4  | b5  | b6  | b7  ]

3- Returns the first 2 bytes masked and shifted:
[ b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 ][ 0 | 0 | 0 | 0 | 0 | 0 | 0 | b0 ]

b) If net flag is _false_ and the platform is LE:
1- Takes 16 bits:
[ b0  | b1  | b2  | b3  | b4  | b5  | b6  | b7  ][ b8  | b9  | b10 |
b11 | b12 | b13 | b14 | b15 ]

2- Returns the first 2 bytes masked and shifted:
[ b9  | b10 | b11 | b12 | b13 | b14 | b15 | b0  ][  0  | 0  | 0  | 0
| 0  | 0  | 0  | b8  ]

c) If net flag is _true or false_ and platform is BE:
1- Takes 16 bits:
[ b0  | b1  | b2  | b3  | b4  | b5  | b6  | b7  ][ b8  | b9  | b10 |
b11 | b12 | b13 | b14 | b15 ]

2- Returns the first 2 bytes masked and shifted:
[  0  | 0  | 0  | 0  | 0  | 0  | 0  | b0  ][ b1  | b2  | b3  | b4  |
b5  | b6  | b7  | b8  ]

 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

 What does that mean? Does it return the top-most 2 bits from the first
 byte plus the least significant bit fom the second byte of the buffer?

It means the least-most 2 bits from the first byte and the LSB from the second.

 What is 'length' for?

Offset and length could be used to impose boundaries to the mask. For
example, if you want to analyse a segment of the buffer that is
organized 

Re: Lua in-kernel (lbuf library)

2013-10-15 Thread Alexander Nasonov
Christoph Badura wrote:
 Also, having to switch mentally between zero-based arrays in the kernel C
 code and 1-based arrays in the Lua code make my head ache.

Yeah, I totally agree here. There are several other reasons why Lua will
not become same league player with C in the kernel. But for some
projects, the classical module (in C) and scripting (in Lua) separation
works extremely well. This includes complex configurations where you
need to orchestrate many calls to C code or some complex tasks like
generating code for bpf or now defunct npf opcode.

Alex


Re: Lua in-kernel (lbuf library)

2013-10-15 Thread Alexander Nasonov
Lourival Vieira Neto wrote:
 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.

I wonder if you looked at Lua support in Wireshark [1]? Unfortunately,
it's GPL and they even have a special section 'Beware the GPL' on wiki.

[1] http://wiki.wireshark.org/Lua

Alex


Re: Lua in-kernel (lbuf library)

2013-10-15 Thread Lourival Vieira Neto
On Tue, Oct 15, 2013 at 7:22 PM, Alexander Nasonov al...@yandex.ru wrote:
 Lourival Vieira Neto wrote:
 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.

 I wonder if you looked at Lua support in Wireshark [1]? Unfortunately,
 it's GPL and they even have a special section 'Beware the GPL' on wiki.

 [1] http://wiki.wireshark.org/Lua

 Alex

Yes. In fact, I have already implemented a Wireshark dissector in Lua
for a proprietary protocol that I was designing, inspired in ERP, to
detect network loops. WS Lua dissectors also served as inspiration.
However, I just used the API; I never looked at the binding
implementation.

Wireshark Lua dissectors is a good example of what can be done with
Lua in that sense. But I'm looking for a more generic API that could
allow random bit access in a buffer using Lua table notation, that
could also be used to communicate with devices, for example. I think
(IMHO) that lbuf masks is more straight forward.

Regards,
-- 
Lourival Vieira Neto


Re: Lua in-kernel (lbuf library)

2013-10-14 Thread Christoph Badura
First, I find the usage of the buf terminology confusing.  In kernel
context I associate buf with the file system buffe cache buf structure.
Packet buffers a called mbufs.  I would appreciate it if the terminology
was consistent with the kernel or at least not confusing.

Also, having to switch mentally between zero-based arrays in the kernel C
code and 1-based arrays in the Lua code make my head ache.

On Thu, Oct 10, 2013 at 03:15:54PM -0300, Lourival Vieira Neto wrote:
 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.

I what is buffer and how does it relate to mbufs?  How do I create a new
lbuf from an mbuf? Or from an array of bytes?

In order to indicate that endianness conversion is necessary I need to
know the future uses of the buffer.  Clairvoyance excepted, that is kinda
hard.

If you are going to make the buffers endianness aware, why not record the
endianness that the packet is encoded in.  And byteswapping can be
performed automatically depending on the consumers endianness.  I think
this way a lot of redundant code can be avoided.

And you don't describe under what circumstances endianness convresion is
performed.

 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

What does that mean? Does it return the top-most 2 bits from the first
byte plus the least significant bit fom the second byte of the buffer?
What is 'length' for?
How does endianness conversion fit in?

 - 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

What exactly would buf[3] return.  Please be explicit in whether you are
counting byte offsets or bit offsets.  I can't figure that out from your
description.

Personally, the idea of making array access to the buffer depend on
state stored in the buffer does not look appealing to me.  It prevents
buffers to be passed around because consumers don't know what they will
get back on array access.

 
 buf:mask{ field = { offset, length }, ... }
 buf.field ~ 'field.length' bits from 'offset' position

This actually makes some sense to me.

 buf:segment(offset [, length])
 returns a new lbuf corresponding a 'buf' segment.

What is a a 'segment' actually?

 - mask reusing
 lbuf.mask{ ... }

This makes sense again...

 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

... except the code seems to be not runnable. Where does 'payload_offset'
come from? And don't you mean lldp_pdu.version?

I find it not helpful when the examples do not actually work.

--chris