mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-10-10 08:12:21 +03:00
Initial commit of Hyperscan
This commit is contained in:
229
src/rose/catchup.h
Normal file
229
src/rose/catchup.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Intel Corporation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ROSE_CATCHUP_H
|
||||
#define ROSE_CATCHUP_H
|
||||
|
||||
#include "hwlm/hwlm.h"
|
||||
#include "runtime.h"
|
||||
#include "scratch.h"
|
||||
#include "rose_common.h"
|
||||
#include "rose_internal.h"
|
||||
#include "ue2common.h"
|
||||
#include "nfa/nfa_internal.h"
|
||||
#include "util/bitutils.h"
|
||||
#include "util/multibit.h"
|
||||
|
||||
/*
|
||||
* Rose has several components which run behind the main (floating table) clock
|
||||
* and need to be caught up before we report matches.
|
||||
*
|
||||
* Currently we have to deal with:
|
||||
* 1) Stored matches from the anchored matcher
|
||||
* 2) Suffix/Outfix nfas
|
||||
* 3) a single MPV nfa (chained) (which may also be triggered by (1) and (2)).
|
||||
*
|
||||
* The approach is to:
|
||||
* A) build a priority queue of the suffix/outfixes based on their first match
|
||||
* location
|
||||
* B) process the matches from the anchored matches in order
|
||||
* C) As we report a match from (B) we interleave matches from the suffixes
|
||||
* D) As we report matches from (B) and (C) we interleave matches from the
|
||||
* mpv if it exists.
|
||||
*/
|
||||
|
||||
/* Callbacks, defined in catchup.c */
|
||||
|
||||
hwlmcb_rv_t roseCatchUpSufAndChains(s64a loc, struct hs_scratch *scratch);
|
||||
|
||||
hwlmcb_rv_t roseCatchUpAll(s64a loc, struct hs_scratch *scratch);
|
||||
|
||||
hwlmcb_rv_t roseCatchUpAnchoredOnly(s64a loc, struct hs_scratch *scratch);
|
||||
|
||||
|
||||
/* will only catch mpv upto last reported external match */
|
||||
hwlmcb_rv_t roseCatchUpSuf(s64a loc, struct hs_scratch *scratch);
|
||||
|
||||
/* will only catch mpv upto last reported external match */
|
||||
hwlmcb_rv_t roseCatchUpAnchoredAndSuf(s64a loc, struct hs_scratch *scratch);
|
||||
|
||||
|
||||
hwlmcb_rv_t roseCatchUpMPV_i(const struct RoseEngine *t, u8 *state, s64a loc,
|
||||
struct hs_scratch *scratch);
|
||||
|
||||
void blockInitSufPQ(const struct RoseEngine *t, u8 *state,
|
||||
struct hs_scratch *scratch, char is_small_block);
|
||||
void streamInitSufPQ(const struct RoseEngine *t, u8 *state,
|
||||
struct hs_scratch *scratch);
|
||||
|
||||
static really_inline
|
||||
hwlmcb_rv_t roseCatchUpMPV(const struct RoseEngine *t, u8 *state,
|
||||
s64a loc, struct hs_scratch *scratch) {
|
||||
u64a cur_offset = loc + scratch->core_info.buf_offset;
|
||||
assert(cur_offset >= scratch->tctxt.minMatchOffset);
|
||||
|
||||
if (0) {
|
||||
quick_exit:
|
||||
updateMinMatchOffsetFromMpv(&scratch->tctxt, cur_offset);
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
if (!has_chained_nfas(t)) {
|
||||
goto quick_exit;
|
||||
}
|
||||
|
||||
/* note: we may have to run at less than tctxt.minMatchOffset as we may
|
||||
* have a full queue of postponed events that we need to flush */
|
||||
if (cur_offset < scratch->tctxt.next_mpv_offset) {
|
||||
DEBUG_PRINTF("skipping cur_offset %lld min %lld, mpv %lld\n",
|
||||
cur_offset, scratch->tctxt.minMatchOffset,
|
||||
scratch->tctxt.next_mpv_offset);
|
||||
goto quick_exit;
|
||||
}
|
||||
|
||||
assert(t->activeArrayCount);
|
||||
|
||||
DEBUG_PRINTF("cur offset offset: %lld\n", cur_offset);
|
||||
DEBUG_PRINTF("min match offset %llu\n", scratch->tctxt.minMatchOffset);
|
||||
|
||||
DEBUG_PRINTF("roseCatchUpMPV to %lld\n", loc);
|
||||
|
||||
assert(t->outfixBeginQueue == 1); /* if it exists mpv is queue 0 */
|
||||
|
||||
u8 *aa = getActiveLeafArray(t, state);
|
||||
u32 aaCount = t->activeArrayCount;
|
||||
|
||||
if (!mmbit_isset(aa, aaCount, 0)){
|
||||
goto quick_exit;
|
||||
}
|
||||
|
||||
/* Note: chained tails MUST not participate in the priority queue as
|
||||
* they may have events pushed on during this process which may be before
|
||||
* the catch up point */
|
||||
|
||||
return roseCatchUpMPV_i(t, state, loc, scratch);
|
||||
}
|
||||
|
||||
static really_inline
|
||||
u64a currentAnchoredEnd(const struct RoseEngine *t, struct RoseContext *tctxt) {
|
||||
if (tctxt->curr_anchored_loc == MMB_INVALID) {
|
||||
return ANCHORED_MATCH_SENTINEL;
|
||||
} else {
|
||||
return tctxt->curr_anchored_loc + t->maxSafeAnchoredDROffset + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* catches up nfas, anchored matches and the mpv */
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseCatchUpTo(const struct RoseEngine *t, u8 *state, u64a end,
|
||||
struct hs_scratch *scratch, char in_anchored) {
|
||||
/* no need to catch up if we are at the same offset as last time */
|
||||
if (end <= scratch->tctxt.minMatchOffset) {
|
||||
/* we must already be up to date */
|
||||
DEBUG_PRINTF("skip\n");
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
s64a loc = end - scratch->core_info.buf_offset;
|
||||
|
||||
if (end <= scratch->tctxt.minNonMpvMatchOffset) {
|
||||
/* only need to catch up the mpv */
|
||||
return roseCatchUpMPV(t, state, loc, scratch);
|
||||
}
|
||||
|
||||
assert(t == scratch->tctxt.t);
|
||||
assert(scratch->tctxt.minMatchOffset >= scratch->core_info.buf_offset);
|
||||
u64a curr_anchored_end = currentAnchoredEnd(t, &scratch->tctxt);
|
||||
hwlmcb_rv_t rv;
|
||||
if (in_anchored
|
||||
|| curr_anchored_end == ANCHORED_MATCH_SENTINEL
|
||||
|| curr_anchored_end > end) {
|
||||
if (!t->activeArrayCount
|
||||
|| !mmbit_any(getActiveLeafArray(t, state), t->activeArrayCount)) {
|
||||
updateMinMatchOffset(&scratch->tctxt, end);
|
||||
rv = HWLM_CONTINUE_MATCHING;
|
||||
} else {
|
||||
rv = roseCatchUpSufAndChains(loc, scratch);
|
||||
}
|
||||
} else {
|
||||
if (!t->activeArrayCount) {
|
||||
rv = roseCatchUpAnchoredOnly(loc, scratch);
|
||||
} else {
|
||||
rv = roseCatchUpAll(loc, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
assert(rv != HWLM_CONTINUE_MATCHING
|
||||
|| scratch->tctxt.minMatchOffset == end);
|
||||
assert(rv != HWLM_CONTINUE_MATCHING
|
||||
|| scratch->tctxt.minNonMpvMatchOffset == end);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Catches up anything which may add triggers on the mpv: anchored matches
|
||||
* and suf/outfixes. The MPV will be run only to intersperse matches in
|
||||
* the output match stream if external matches are raised. */
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseCatchUpMpvFeeders(const struct RoseEngine *t, u8 *state,
|
||||
u64a end, struct hs_scratch *scratch,
|
||||
char in_anchored) {
|
||||
/* no need to catch up if we are at the same offset as last time */
|
||||
if (end <= scratch->tctxt.minNonMpvMatchOffset) {
|
||||
/* we must already be up to date */
|
||||
DEBUG_PRINTF("skip\n");
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
s64a loc = end - scratch->core_info.buf_offset;
|
||||
|
||||
assert(t == scratch->tctxt.t);
|
||||
assert(t->activeArrayCount); /* mpv is in active array */
|
||||
assert(scratch->tctxt.minMatchOffset >= scratch->core_info.buf_offset);
|
||||
u64a curr_anchored_end = currentAnchoredEnd(t, &scratch->tctxt);
|
||||
if (in_anchored
|
||||
|| curr_anchored_end == ANCHORED_MATCH_SENTINEL
|
||||
|| curr_anchored_end > end) {
|
||||
if (!t->mpvTriggeredByLeaf) {
|
||||
/* no need to check as they never put triggers onto the mpv */
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
/* sadly, this branch rarely gets taken as the mpv itself is usually
|
||||
* alive. */
|
||||
if (!mmbit_any(getActiveLeafArray(t, state), t->activeArrayCount)) {
|
||||
scratch->tctxt.minNonMpvMatchOffset = end;
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
return roseCatchUpSuf(loc, scratch);
|
||||
} else {
|
||||
return roseCatchUpAnchoredAndSuf(loc, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user