ipfw: Rework states and tracks.
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 16 Aug 2017 03:56:45 +0000 (11:56 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 5 Sep 2017 08:58:32 +0000 (16:58 +0800)
commit2187815d4cfbe09db545787d4cbed10e31341b8c
tree916f5ebf8aa37506c6c7412c92dabe54e0e3e371
parent185b27fa8e115c7559618f5ae72cc8f449096f50
ipfw: Rework states and tracks.

- Use RB tree for states and tracks.  And put them into their own RB
  trees.  This avoid worst case hash collision.
- Make states per-cpu.  Upper limit is still shared, and is managed in
  the same fashion as our slab allocator's upper limit, i.e. loosely
  updated, which allows 5% over-allocation at most.
- Use two tiers for tracks.  The top tier is shared, which maintains
  the counter.  The second tier is per-cpu, most of the track looking
  up should be coverd by this tier.  Track counters are updated by
  atomic ops, since per-track upper limit is usually too small to use
  loose updating.
- Implement progressive state/track expiration and keepalive.  It is
  mainly intended to make the packet processing latency more smooth.
- Fix fast TCP state recycling issue by tracking the SEQs in addition
  to the ACKs.

This drastically improves performance, and reduces/stablizes latency.

For exmaple, nginx, 1KB web object, 30K concurrent connections,
1 request/connection.  ipfw is running on the server side.

ipfw non-default setting:
- Max # of states for new-ipfw is 100K (~14MB memory).
- Max # of states for old-ipfw is 500K, and # of hash buckets is 64K.

ipfw rules:
ipfw add 1 check-state
ipfw add allow tcp from any to me 80 setup keep-state
(default deny)

         |  perf-avg | lat-avg | lat-stdev | lat-99% | lat-max
         |   (tps)   |  (ms)   |   (ms)    |  (ms)   |  (ms)
---------+-----------+---------+-----------+---------+---------
no-ipfw  | 210658.80 |   58.01 |      5.20 |   68.73 |  146.46
---------+-----------+---------+-----------+---------+---------
new-ipfw | 191626.58 |   64.74 |      5.69 |   75.87 |  166.08
---------+-----------+---------+-----------+---------+---------
old-ipfw |  43481.19 |  153.76 |     47.32 |  296.61 |  425.09

If it is compared w/ no-ipfw case, the performance and latency impacts
of the ipfw after this commit are pretty small.
sys/net/ipfw/ip_fw2.c
sys/net/ipfw/ip_fw2.h
sys/net/ipfw/ip_fw2_glue.c