Commit Graph

82 Commits (3bba671273dfadb82e8497c219ebdb8b4ed55adb)

Author SHA1 Message Date
Victor Julien 5e583f3a12 flow: fix global variable use 6 years ago
Victor Julien 7cabb025ea ips: fix wrong thread for bridge ips modes 6 years ago
Eric Leblond 53a62953e9 bypass: introduce CAPTURE_OFFLOAD
This define is used to remove reference to capture bypass in case
no capture method implementing this is active.

This patch also introduces CAPTURE_OFFLOAD_MANAGER that is defined
if we need the flow bypass manager code.
6 years ago
Eric Leblond 094d28d40e flow-hash: generalize function
THis patch generalizes the function to get a flow by its flowkey
by removing the call setting it to capture bypassed state.
6 years ago
Victor Julien 255ab1528b flow: minor formatting updates 6 years ago
Max Fillinger cef9961f59 flow hash: Mask vlan_id if not used for tracking
If vlan.use-for-tracking is disabled, set the vlan_id fields to 0 when
hashing or comparing flows. This is done using a bitmask as suggested by
Victor Julien in IRC, in order to avoid adding more branches to this
code.

Currently, suricata does not fill in vlan_id fields if
vlan.use-for-tracking is disabled and instead leaves them at the default
0 value, so this commit makes no functional change. This change is in
preparation for future commits where the vlan_ids will be always filled
in.

Related to https://redmine.openinfosecfoundation.org/issues/3076
6 years ago
Max Fillinger 38731d30da flow hash: Make CMP_FLOW macro an inline function 6 years ago
Eric Leblond 3e8fd26ee3 flow-hash: real hash computation for FlowKey 7 years ago
Eric Leblond 69d2c8eb75 ebpf: get rid of hash in map value 7 years ago
Eric Leblond d239e0f2d5 flow-hash: doc and code cleaning 7 years ago
Eric Leblond 04c65a309e flow-hash: new function to get flow from flowkey 7 years ago
Eric Leblond 315c29a8e6 ebpf: change the logic to avoid ktime usage
Kernel time is not available (and/or costly) on NIC such as
Netronome so we update the logic to detect dead flows based on a
lack of update of packets counters. This way, the XDP filter will
be usable by network card.

This patch also updates the ebpf code to support per CPU and
regular mapping. Netronome is not supporting it and the structure
is using atomic for counter so the cost of simultaneous update
is really low.

This patch also updates the xdp_filter to be able to select if the
flow table is per CPU on shared. Second option will be used for
hardward offload. To deactivate the per cpu hash, you need to set
USE_PERCPU_HASH to 0.

This patch also adds an new option to af-packet named no-percpu-hash
If this option is set to yes then the Flow bypassed manager thread
will use one CPU instead of the number of cores. By doing that
we are able to handle the case where USE_PERCPU_HASH is unset (so
hardware offload for Netronome).

This patch also remove aligment indications in the eBPF filter. This
was not really needed and it seems it is causing problem with
some recent version of LLVM toolchain.
7 years ago
Victor Julien c662383b53 flow: track flow for ICMP
Change packet layout to allow for expected counterpart type.
8 years ago
Victor Julien 11be9bd971 mingw: add SCNtohl and SCNtohs macro's
On MinGW the result of ntohl needs to be casted to uint32_t and
the result of ntohs to uint16_t. To avoid doing this everywhere
add SCNtohl and SCNtohs macros.
8 years ago
Victor Julien f702e6c33d flow-hash: optimize to avoid branch misses
Profiling showed a lot of branch misses in flow hashing. Restructure
code to avoid branching.
9 years ago
Victor Julien f18c976a8e flow: counters for total number of flows
flow.tcp
flow.udp
flow.icmpv4
flow.icmpv6
9 years ago
Eric Leblond 4cf887b4f7 flow: update lastts in FlowHandlePacketUpdate
This allows to make it conditional to the state of packet and
then trigger modified behavior.
9 years ago
Eric Leblond 39c8786a8e flow: get bypass info in get used flow function 9 years ago
Victor Julien 70c16f50e7 flow-manager: optimize hash walking
Until now the flow manager would walk the entire flow hash table on an
interval. It would thus touch all flows, leading to a lot of memory
and cache pressure. In scenario's where the number of tracked flows run
into the hundreds on thousands, and the memory used can run into many
hundreds of megabytes or even gigabytes, this would lead to serious
performance degradation.

This patch introduces a new approach. A timestamp per flow bucket
(hash row) is maintained by the flow manager. It holds the timestamp
of the earliest possible timeout of a flow in the list. The hash walk
skips rows with timestamps beyond the current time.

As the timestamp depends on the flows in the hash row's list, and on
the 'state' of each flow in the list, any addition of a flow or
changing of a flow's state invalidates the timestamp. The flow manager
then has to walk the list again to set a new timestamp.

A utility function FlowUpdateState is introduced to change Flow states,
taking care of the bucket timestamp invalidation while at it.

Empty flow buckets use a special value so that we don't have to take
the flow bucket lock to find out the bucket is empty.

This patch also adds more performance counters:

flow_mgr.flows_checked         | Total    | 929
flow_mgr.flows_notimeout       | Total    | 391
flow_mgr.flows_timeout         | Total    | 538
flow_mgr.flows_removed         | Total    | 277
flow_mgr.flows_timeout_inuse   | Total    | 261
flow_mgr.rows_checked          | Total    | 1000000
flow_mgr.rows_skipped          | Total    | 998835
flow_mgr.rows_empty            | Total    | 290
flow_mgr.rows_maxlen           | Total    | 2

flow_mgr.flows_checked: number of flows checked for timeout in the
                        last pass
flow_mgr.flows_notimeout: number of flows out of flow_mgr.flows_checked
                        that didn't time out
flow_mgr.flows_timeout: number of out of flow_mgr.flows_checked that
                        did reach the time out
flow_mgr.flows_removed: number of flows out of flow_mgr.flows_timeout
                        that were really removed
flow_mgr.flows_timeout_inuse: number of flows out of flow_mgr.flows_timeout
                        that were still in use or needed work

flow_mgr.rows_checked: hash table rows checked
flow_mgr.rows_skipped: hash table rows skipped because non of the flows
                        would time out anyway

The counters below are only relating to rows that were not skipped.

flow_mgr.rows_empty:   empty hash rows
flow_mgr.rows_maxlen:  max number of flows per hash row. Best to keep low,
                        so increase hash-size if needed.
flow_mgr.rows_busy:    row skipped because it was locked by another thread
9 years ago
Victor Julien aee1f0bb99 flow: simplify timeout logic
Instead of a single big FlowProto array containing timeouts separately
for normal and emergency cases, plus the 'Free' pointer for the
protoctx, split up these arrays.

An array made of FlowProtoTimeout for just the normal timeouts and an
mirror of that for emergency timeouts are used through a pointer that
will be set at init and by swapped by the emergency logic. It's swapped
back when the emergency is over.

The free funcs are moved to their own array.

This simplifies the timeout lookup code and shrinks the data that is
commonly used.
9 years ago
Victor Julien 78ecfe8780 autofp: update queue handlers
Now that the flow lookup is done in the worker threads the flow
queue handlers running after the capture thread(s) no longer have
access to the flow. This limits the options of how flow balancing
can be done.

This patch removes all code that is now useless. The only 2 methods
that still make sense are 'hash' and 'ippair'.
10 years ago
Victor Julien 2f0e0f17db flow: move flow handling into worker threads
Instead of handling the packet update during flow lookup, handle
it in the stream/detect threads. This lowers the load of the
capture thread(s) in autofp mode.

The decoders now set a flag in the packet if the packet needs a
flow lookup. Then the workers will take care of this. The decoders
also already calculate the raw flow hash value. This is so that
this value can be used in flow balancing in autofp.

Because the flow lookup/creation is now done in the worker threads,
the flow balancing can no longer use the flow. It's not yet
available. Autofp load balancing uses raw hash values instead.

In the same line, move UDP AppLayer out of the DecodeUDP module,
and also into the stream/detect threads.

Handle TCP session reuse inside the flow engine itself. If a looked up
flow matches the packet, but is a TCP stream starter, check if the
ssn needs to be reused. If that is the case handle it within the
lookup function. Simplies the locking and removes potential race
conditions.
10 years ago
Victor Julien ae7aae81dc flow: get flow reference during lookup
Update Flow lookup functions to get a flow reference during lookup.

This reference is set under the FlowBucket lock.

This paves the way to not getting a flow lock during lookups.
10 years ago
Victor Julien ba64069b35 flow: remove unused debug code 10 years ago
Jason Ish 8edbc20a07 flow: record the flow hash for use as the output flow id
Provides a consistent hash for a flow, as well as a better
distribution than using a memory address.
10 years ago
Giuseppe Longo 769722101e decode: add flow memcap counter
This adds a counter indicating how many times
the flow max memcap has been reached

Since there is no always a reference to FlowManagerThreadData,
the counter is put in DecodeThreadVars.

Currently when there is no counter increase in one call of FlowGetNew
because we don't have tv or dtv at the time of the call.

The following is a snippet of the generated EVE entry:
"flow":{"memcap":0,"spare":10000,"emerg_mode_entered":0,"emerg_mode_over":0,"tcp_reuse":0,"memuse":7085248}
10 years ago
Victor Julien fc7f090cd3 flow: add missing storage size to checks, output 10 years ago
Victor Julien 7426a9c645 flow: make TCP reuse handling in flow engine optional
In case of autofp (or more general, when flow and stream engine
run in different threads) the flow engine should not trigger a flow
reuse as this can lead to race conditions between the flow and the
stream engine.

In such cases, the flow engine can be far ahead of the stream engine
as packets are in a queue between the threads.

Observed:

Flow engine tags packet 10 as start of new flow. Flow is tagged as
'reused'.

Stream engine evaluates packet 5 which belongs to the old flow. It
rejects the flow as it's tagged 'reused'. Attaches packet 5 to the
new flow which is wrong.

Solution:

This patch connects the flow engines handling of reuse cases to
the runmode. It hooks into the RunmodeSetFlowStreamAsync() call to
notify the flow engine that it shouldn't handle the reuse.
11 years ago
Victor Julien c88cbb39fe tcp reuse: enable stream handling based on runmode
Add a way for runmodes to state that flow and stream run asynchorously.

In the stream engine, enable the TCP reuse handling only if that flag
is set.
11 years ago
Victor Julien 11e3f25de3 tcp reuse: unify autofp and single/workers check 11 years ago
Victor Julien 29f70bad34 tcp reuse: handle reuse in stream engine
For the autofp case, handling TCP reuse in the flow engine didn't work.

The problem is the mismatch between the moment the flow engine looks at
packets and the stream, and the moment the stream engine runs. Flow engine
is invoked in the packet capture thread(s), while the stream engine runs
as part of the stream/detect thread(s). Because of the queues between
those threads the flow manager may already inspect a new SYN while the
stream engine still has to process the previous session.

Moving the flow engine to the stream/detect thread(s) wasn't an option
as the 'autofp' load balancing depends on the flow already being
available in the packet.

The solution here is to add a check for this condition to the stream
engine. At this point the TCP state is up to date. If a TCP reuse case
is encountered, this is the global logic:

- detach packet for old flow
- get a new flow and attach it to the packet
- flag the old flow that it is now obsolete

Additional logic makes sure that the packets already in the queue
between the flow thread(s) and the stream thread are reassigned the
new flow.

Some special handling:

Apply previous 'reuse' before checking for a new reuse. Otherwise we're
tagging the wrong flow in some cases (multiple reuses in the same tuple).

When in a flow/ssn reuse condition, properly remove the packet from
the flow.

Don't 'reuse' if packet is a SYN retransmission.

The old flow is timed out normally by the flow manager.
11 years ago
Victor Julien fb1b03c471 flow: handle TCP session reuse in flow engine
Until now, TCP session reuse was handled in the TCP stream engine.
If the state was TCP_CLOSED, a new SYN packet was received and a few
other conditions were met, the flow was 'reset' and reused for the
'new' TCP session.

There are a number of problems with this approach:
- it breaks the normal flow lifecycle wrt timeout, detection, logging
- new TCP sessions could come in on different threads due to mismatches
  in timeouts between suricata and flow balancing hw/nic/drivers
- cleanup code was often causing problems
- it complicated locking because of the possible thread mismatch

This patch implements a different solution, where a new TCP session also
gets a new flow. To do this 2 main things needed to be done:

1. the flow engine needed to be aware of when the TCP reuse case was
   happening
2. the flow engine needs to be able to 'skip' the old flow once it was
   replaced by a new one

To handle (1), a new function TcpSessionPacketSsnReuse() is introduced
to check for the TCP reuse conditions. It's called from 'FlowCompare()'
for TCP packets / TCP flows that are candidates for reuse. FlowCompare
returns FALSE for the 'old' flow in the case of TCP reuse.

This in turn will lead to the flow engine not finding a flow for the TCP
SYN packet, resulting in the creation of a new flow.

To handle (2), FlowCompare flags the 'old' flow. This flag causes future
FlowCompare calls to always return FALSE on it. In other words, the flow
can't be found anymore. It can only be accessed by:

1. existing packets with a reference to it
2. flow timeout handling as this logic gets the flows from walking the
   hash directly
3. flow timeout pseudo packets, as they are set up by (2)

The old flow will time out normally, as governed by the "tcp closed"
flow timeout setting. At timeout, the normal detection, logging and
cleanup code will process it.

The flagging of a flow making it 'unfindable' in the flow hash is a bit
of a hack. The reason for this approach over for example putting the
old flow into a forced timeout queue where it could be timed out, is
that such a queue could easily become a contention point. The TCP
session reuse case can easily be created by an attacker. In case of
multiple packet handlers, this could lead to contention on such a flow
timeout queue.
11 years ago
Victor Julien 5587372ce1 flow: modify lastts update logic
In the lastts timeval struct field in the flow the timestamp of the
last packet to update is recorded. This allows for tracking the timeout
of the flow. So far, this value was updated under the flow lock and also
read under the flow lock.

This patch moves the updating of this field to the FlowGetFlowFromHash
function, where it updated at the point where both the Flow and the
Flow Hash Row lock are held. This guarantees that the field is only
updated when both locks are held.

This makes reading the field safe when either lock is held, which is the
purpose of this patch.

The flow manager, while holding the flow hash row lock, can now safely
read the lastts value. This allows it to do the flow timeout check
without actually locking the flow.
11 years ago
Victor Julien a0732d3db2 flow: change flow state logic
A flow has 3 states: NEW, ESTABLISHED and CLOSED.

For all protocols except TCP, a flow is in state NEW as long as just one
side of the conversation has been seen. When both sides have been
observed the state is moved to ESTABLISHED.

TCP has a different logic, controlled by the stream engine. Here the TCP
state is leading.

Until now, when parts of the engine needed to know the flow state, it
would invoke a per protocol callback 'GetProtoState'. For TCP this would
return the state based on the TcpSession.

This patch changes this logic. It introduces an atomic variable in the
flow 'flow_state'. It defaults to NEW and is set to ESTABLISHED for non-
TCP protocols when we've seen both sides of the conversation.

For TCP, the state is updated from the TCP engine directly.

The goal is to allow for access to the state without holding the Flow's
main mutex lock. This will later allow the Flow Manager(s) to evaluate
the Flow w/o interupting it.
11 years ago
Victor Julien 9f55ca0057 flow: add flow_end_flags field, add logging
The flow end flags field is filled by the flow manager or the flow
hash (in case of forced timeout of a flow) to record the timeout
conditions in the flow:
- emergency mode
- state
- reason (timed out or forced)

Add logging to the flow logger.
11 years ago
Victor Julien de034f1867 flow: prepare flow forced reuse logging
Most flows are marked for clean up by the flow manager, which then
passes them to the recycler. The recycler logs and cleans up. However,
under resource stress conditions, the packet threads can recycle
existing flow directly. So here the recycler has no role to play, as
the flow is immediately used.

For this reason, the packet threads need to be able to invoke the
flow logger directly.

The flow logging thread ctx will stored in the DecodeThreadVars
stucture. Therefore, this patch makes the DecodeThreadVars an argument
to FlowHandlePacket.
11 years ago
Ken Steele d12834769a Add const for Packet * in flow functions.
By moving FlowReference() out of FlowGetFlowFromHash() and into the one
function that calls it, all the flow functions take const Packet * instead
of Packet *.
12 years ago
Ken Steele c1b9f0e1f4 Formatting and comment updates in flow files
Some reformatting to meet coding standards.

Added a few comments to make it more clear where p->flow gets set.
12 years ago
Victor Julien 2e82772a0a Coverity 1038098: remove dead code from flow hash 12 years ago
Ken Steele b08ddfa7f1 Support for Tile Gx atomic instructions
Tilera's GCC supports the GCC __sync_ intrinsics.

Increase the size of some atomic variables for better performance on
Tile.  The Tile-Gx architecture has native support for 32-bit and
64-bit atomic operations, but not 8-bit and 16-bit, which are emulated
using 32-bit atomics, so changing some 16-bit and 8-bit atomic into
ints improves performance.

Increasing the size of the atomic variables modified in this change
does not increase the total size of the structures in which they
reside because of existing padding requirements. The one case that
would increase the size of the structure (Flow_) was confitionalized
to only change the size on Tile.
12 years ago
Victor Julien 58ed1f2411 flow: take vlan_id's into account in the flow hash
In VLAN we can have 2 layers of encapsulation. In this patch both
layers are used in the flow hash to distinguish between encapsulated
traffic.
12 years ago
Victor Julien d1573a366d Fix GetUsed functions for Host, Flow and Defrag. 13 years ago
Victor Julien 966c731e73 flow: fix crash when flow engine under extreme stress, and unable to force free any existing flow 13 years ago
Anoop Saldanha 3d74fa964a Update all flow referencing to use the new FlowReference and FlowDeReference
macros.
13 years ago
Eric Leblond 0227a87fcb cleaning: fix warning when building with clang.
clang was issuing some warnings related to unused return in function.
This patch adds some needed error treatment and ignore the rest of the
warnings by adding a cast to void.
14 years ago
Victor Julien c10370907a flow: make flow use lookup3.c hashing algorithm. Improves hash table distribution. 14 years ago
Victor Julien 19a7e7f395 flow: create a flow lock macro API, implement it for mutex and rwlocks. Mutex remains the default. 14 years ago
Victor Julien 4157d9408d Various small flow and host table fixes. 14 years ago
Victor Julien db24258acf Undo changes from 88b8f15663. Atomic stack implementation had a-b-a problem. 14 years ago
Victor Julien 88b8f15663 Add atomic stack implementation. Convert flow spare queue to use this stack. Remove now unused flow-queue code. 14 years ago