Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimization/defrag rbtree/v3 #3475

Closed
wants to merge 15 commits into from

Conversation

jasonish
Copy link
Member

Previous PR:

Changes:

  • Fix performance issue with Linux profile.
  • Add missing locks around pool return.

PRscript:

victorjulien and others added 15 commits August 31, 2018 21:35
To improve worst case performance turn the segments list into a rbtree.
This greatly improves inserts, lookups and removals if the number of
segments gets very large.

The tree is sorted by the segment sequence number as its primary key.
If 2 segments have the same seq, the payload_len (segment length) is
used. Then the larger segment will be places after the smaller segment.
Exact matches are not added to the tree.
Now that with the RBTREE we have a properly sorted Segment tree,
where with exact SEQ matches the tree is sorted by payload_len
smallest to largest, we can avoid walking backwards when checking
for overlaps. Our direct RB_PREV either overlaps or not and that
is a reliable verdict for the rest of the tree.
Don't try to do a 'fast path' by checking RB_MAX. RB_MAX walks the
tree which means it can be quite expensive. This cost would be paid
for virtually every data segment. The actual insert that follows would
walk the tree again.

Instead, simply insert it. There is a slight cost of the unnecessary
overlap check, but this is much less than the tree walk in a full
tree.
Use this in places where we need to use the outer right
edge of our sequence space.

This way we can avoid walking the tree to find this, which
is a potentially expensive operation.
Convert to rbtree from linked list. These ranges, of which there can
be multiple per packet, are fully controlled by an attacked. The
attacker could craft a stream of packet in such a way that the list
would grow very large. This would make inserts/removals very expensive,
as well as the list walk that is done and size calculation and pruning
operations.

The RBTREE makes inserts/removals much cheaper, at a slight overhead
for 'normal' operations and slightly higher per record memory use.
Optimize by keeping count during insert/remove instead of
walking the tree per check.
Switch StreamBufferBlocks implementation to use RBTREE instead of
a list. This makes inserts/removals and lookups a lot cheaper if
the number of data gaps is large.

Use separate compare functions for inserts and regular lookups.
Inserts care about the offset, while lookups care about the blocks
right edge as well.
Change the way fields are ordered to reduce TcpSegment structure
with 8 bytes.
Instead of just marking fragments that have been completely
overlapped and won't be part of the assembled packet, remove
them from the fragment tree when detected.
@jasonish jasonish requested a review from a team as a code owner September 14, 2018 14:36
@victorjulien victorjulien mentioned this pull request Sep 17, 2018
@victorjulien
Copy link
Member

Merged into #3479, thanks Jason!

@jasonish jasonish deleted the optimization/defrag-rbtree/v3 branch September 18, 2018 02:43
catenacyber added a commit to catenacyber/suricata that referenced this pull request Jan 15, 2021
victorjulien pushed a commit to victorjulien/suricata that referenced this pull request Feb 23, 2021
Add AndX support for SMB1. Finishes OISF#3475.

[Updated by Victor Julien to split functions]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants