In a BDD, each node is an implicit predicate, "variable = true". In a FDD, each node is a test of a field against a particular value, as in EthSrc = "FE:89:00:12:34:12". The edges are either true or false just like in a BDD. But we also use values in modifcations - as in "port := 2". Note only Const and Mask are really used by OpenFlow. Both Pipe and Query are translated to the pseudoport Controller.
Each packet field can take on a certain range of values that in general have a lattice structure. This sometimes enables multiple tests on fields to be compressed into a single test. This module implements the Lattice signature from Vlr.
All integer bit widths are represented by an Int64.t and will be cast to the appropriate bit width for use during final translation to flowtables.
A simple bitmask variant is also supported. Mask(n, m) indicates that the first m bits of the value n are fixed, while the rest should be treated as wildcards.
Because this is a big union of possible value types, it's possible for the programmer to construct (Field.t, Value.t) pairs that do not make any sense, e.g., (Field.EthSrc, Value.Pipe "learn"). This will be detected during flowtable generation, though the syntax of the NetKAT language will prevent programs from generating these ill-formed predicates.