This change is functional no-op, but it change way of representing and processing dynamic states in IPFW.
New code is OOP-like and creates states from set of structures, such "header", "IPv4 addresses", "state data", which are assembled to state size by enclosing struct. It looks like ipfw_insn_* structures we have now. It allows to have more generic code and save several pointer dereferences, as all data now stored in state structure itself, and not in separately allocated structures referenced by state.
Also, this code is more type-safe, as there are less void * casts.
Unfortunately, not all indirections and void * casts are eliminated, some data is still passed as pointer-to-struct into leaf functions.
All data, needed for state look-up is packed into front of state struct and is always fit into 64 bytes (typical cache line) in worst case: IPv6 on 64 bit system.
Together this changes provide small but visible performance boost in case when buckets are full and contains more than one state. My measurements on low-end hardware shows, that single-rule firewall allow udp from any to any keep-state have forwarding performance (numbers are KPps) under traffic with 17780 UDP flows like this:
Buckets | Default | Patched |
---|---|---|
16384 | 305 | 307 |
8192 | 303 | 307 |
4096 | 292 | 299 |
2048 | 281 | 288 |
Results on high-end systems, where memory accesses are more expensive relative to CPU work, results could be even better for new code.
I want to land these changes because IMHO, this code after this refactoring is easier to extend with new state types. I plan to add NAT implementation in near future, and it looks much simpler with this code.