Page MenuHomeFreeBSD

Refactor ipfw dynamic states in preparation for new features (and slighlty optimize)
Needs ReviewPublic

Authored by lev on Jul 6 2019, 6:39 PM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, Nov 17, 2:30 AM
Unknown Object (File)
Tue, Nov 12, 9:14 PM
Unknown Object (File)
Tue, Nov 12, 6:33 PM
Unknown Object (File)
Tue, Nov 12, 7:40 AM
Unknown Object (File)
Mon, Nov 11, 1:32 PM
Unknown Object (File)
Mon, Nov 11, 12:44 PM
Unknown Object (File)
Dec 20 2023, 3:26 AM
Unknown Object (File)
Dec 10 2023, 4:03 PM
Subscribers

Details

Summary

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:

BucketsDefaultPatched
16384305307
8192303307
4096292299
2048281288

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.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

Regenerate against new git repository