pflua icon indicating copy to clipboard operation
pflua copied to clipboard

Document pflua API

Open wingo opened this issue 10 years ago • 2 comments

The pflua API needs documentation.

wingo avatar Aug 08 '14 09:08 wingo

Any preferred format/location for the documentation? @andywingo

kbara avatar Jun 11 '15 16:06 kbara

Here's an initial draft. It uses the convert_ssa/convert_anf APIs with the extra optimize flag, although those are still in a PR.


The pflua API

Pflua compiles pflang (libpcap filter expressions), and matches packets accordingly.

Compilation is done with pf.compile_filter.
For examples of the API in use, see https://github.com/Igalia/pflua/tree/master/tools

Compilation: external API
pf.compile_filter(filter_str, opts)
filter_str is a pflang expression, such as "ip" or "tcp port 80 or udp".
opts is a lua table. It can specify none or any combination of:
 - optimize: a boolean. Enables or disables optimization; true by default
 - source: emit human-readable output rather than a normal Lua function
 - dlt: 'EN10MB' by default.
 - libpcap or bpf: select the compilation pipeline. If both are false, use
    the native pflua pipeline. If libpcap is true, use libpcap. If BPF is true,
    compile traditional BPF bytecode to Lua.

 If 'opts.source' is not true, the result is a lua predicate. See 'matching packets'.

Matching packets:
Get a predicate/matching function from pf.compile_filter. Then:
your_lua_predicate(packet, packet_len)
This will return true if the filter matches the packet, and false otherwise.

Getting packets:
The mechanism for getting packets can vary. The simplest way with a pcap file
and standalone pflua is to use savefile.load_packets(pcap_filename).

To use pflua within Snabb, from packet captures or interfaces, read the Snabb
documentation and see main.lua files under apps/ in the source tree for
configuration examples.

-----------------------------------------
Pflua internals: these may change without warning.

Pflua has two main compilation pipelines which emit Lua code. One takes bpf
bytecode as input; the other takes pflang. Additionally, a third pipeline is a
thin wrapper around libpcap.

Libpcap pipeline:
   Compile to BPF: libpcap.compile(filter_string, dlt, optimize)
     Example: libpcap.compile("tcp", "EN10MB", true)
   BPF to Lua source code: bpf.disassemble(bytecode)
   Compile pflang to a lua predicate: libpcap.offline_filter(bpf, header, pkt)
       - See libpcap.lua for details about the arguments.

BPF pipeline:
   Get bytecode: libpcap.compile(filter_string, dlt, optimize)
     Example: libpcap.compile("tcp", "EN10MB", true)
   Compile bytecode to Lua source: bpf.compile_lua(bytecode)
   Compile bytecode to a Lua predicate: bpf.compile(bytecode)

Pure-lua pipeline: this is the default, and most interesting.
   Parse a pflang expression: parse.parse(filter_str); returns an AST
   Expand the parse: expand.expand(ast, dlt); returns an (unnamed) IR
   Optimize the expanded parse: optimize.optimize(ir); returns the same type
      of IR, but optimized.
   Convert the unnamed IR to ANF: anf.convert_anf(ir, optimize)
   Convert ANF to SSA: ssa.convert_ssa(anf, optimize)
   Convert SSA to lua source: backend.emit_lua(ssa)
   Convert SSA to a Lua predicate: backend.emit_and_load(ssa, filter_str)

kbara avatar Jun 22 '15 12:06 kbara