Go to the documentation of this file.
74 static inline int FlowHashRawAddressIPv6GtU32(
const uint32_t *a,
const uint32_t *b)
76 for (uint8_t i = 0; i < 4; i++) {
156 if (PacketIsIPv4(
p)) {
159 int ai = (
p->
src.addr_data32[0] >
p->
dst.addr_data32[0]);
160 fhk.
addrs[1 - ai] =
p->
src.addr_data32[0];
163 fhk.
ports[0] = 0xfedc;
164 fhk.
ports[1] = 0xba98;
166 FlowHashIp4Fill(&fhk,
p);
169 }
else if (PacketIsIPv6(
p)) {
171 if (FlowHashRawAddressIPv6GtU32(
p->
src.addr_data32,
p->
dst.addr_data32)) {
172 fhk.
src[0] =
p->
src.addr_data32[0];
173 fhk.
src[1] =
p->
src.addr_data32[1];
174 fhk.
src[2] =
p->
src.addr_data32[2];
175 fhk.
src[3] =
p->
src.addr_data32[3];
176 fhk.
dst[0] =
p->
dst.addr_data32[0];
177 fhk.
dst[1] =
p->
dst.addr_data32[1];
178 fhk.
dst[2] =
p->
dst.addr_data32[2];
179 fhk.
dst[3] =
p->
dst.addr_data32[3];
181 fhk.
src[0] =
p->
dst.addr_data32[0];
182 fhk.
src[1] =
p->
dst.addr_data32[1];
183 fhk.
src[2] =
p->
dst.addr_data32[2];
184 fhk.
src[3] =
p->
dst.addr_data32[3];
185 fhk.
dst[0] =
p->
src.addr_data32[0];
186 fhk.
dst[1] =
p->
src.addr_data32[1];
187 fhk.
dst[2] =
p->
src.addr_data32[2];
188 fhk.
dst[3] =
p->
src.addr_data32[3];
191 fhk.
ports[0] = 0xfedc;
192 fhk.
ports[1] = 0xba98;
194 FlowHashIp6Fill(&fhk,
p);
214 static inline uint32_t FlowGetHash(
const Packet *
p)
218 if (PacketIsIPv4(
p)) {
219 if (PacketIsTCP(
p) || PacketIsUDP(
p)) {
222 int ai = (
p->
src.addr_data32[0] >
p->
dst.addr_data32[0]);
226 const int pi = (
p->
sp >
p->
dp);
230 FlowHashIp4Fill(&fhk,
p);
239 const int ai = (psrc > pdst);
240 fhk.
addrs[1-ai] = psrc;
241 fhk.
addrs[ai] = pdst;
247 FlowHashIp4Fill(&fhk,
p);
254 const int ai = (
p->
src.addr_data32[0] >
p->
dst.addr_data32[0]);
257 if (PacketIsESP(
p)) {
260 fhk.
ports[0] = 0xfeed;
261 fhk.
ports[1] = 0xbeef;
263 FlowHashIp4Fill(&fhk,
p);
267 }
else if (PacketIsIPv6(
p)) {
269 if (FlowHashRawAddressIPv6GtU32(
p->
src.addr_data32,
p->
dst.addr_data32)) {
270 fhk.
src[0] =
p->
src.addr_data32[0];
271 fhk.
src[1] =
p->
src.addr_data32[1];
272 fhk.
src[2] =
p->
src.addr_data32[2];
273 fhk.
src[3] =
p->
src.addr_data32[3];
274 fhk.
dst[0] =
p->
dst.addr_data32[0];
275 fhk.
dst[1] =
p->
dst.addr_data32[1];
276 fhk.
dst[2] =
p->
dst.addr_data32[2];
277 fhk.
dst[3] =
p->
dst.addr_data32[3];
279 fhk.
src[0] =
p->
dst.addr_data32[0];
280 fhk.
src[1] =
p->
dst.addr_data32[1];
281 fhk.
src[2] =
p->
dst.addr_data32[2];
282 fhk.
src[3] =
p->
dst.addr_data32[3];
283 fhk.
dst[0] =
p->
src.addr_data32[0];
284 fhk.
dst[1] =
p->
src.addr_data32[1];
285 fhk.
dst[2] =
p->
src.addr_data32[2];
286 fhk.
dst[3] =
p->
src.addr_data32[3];
289 const int pi = (
p->
sp >
p->
dp);
290 if (PacketIsESP(
p)) {
296 FlowHashIp6Fill(&fhk,
p);
322 const int pi = (fk->
sp > fk->
dp);
358 const int pi = (fk->
sp > fk->
dp);
374 static inline bool CmpAddrs(
const uint32_t addr1[4],
const uint32_t addr2[4])
376 return addr1[0] == addr2[0] && addr1[1] == addr2[1] &&
377 addr1[2] == addr2[2] && addr1[3] == addr2[3];
380 static inline bool CmpAddrsAndPorts(
const uint32_t src1[4],
381 const uint32_t dst1[4],
Port src_port1,
Port dst_port1,
382 const uint32_t src2[4],
const uint32_t dst2[4],
Port src_port2,
388 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
389 src_port1 == src_port2 && dst_port1 == dst_port2) ||
390 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
391 src_port1 == dst_port2 && dst_port1 == src_port2);
394 static inline bool CmpVlanIds(
397 return ((vlan_id1[0] ^ vlan_id2[0]) &
g_vlan_mask) == 0 &&
398 ((vlan_id1[1] ^ vlan_id2[1]) &
g_vlan_mask) == 0 &&
402 static inline bool CmpLiveDevIds(
const uint16_t id1,
const uint16_t id2)
407 #define CmpFlowMisc(x, y) \
408 (((x)->proto == (y)->proto) && \
409 ((x)->recursion_level == (y)->recursion_level || g_recurlvl_mask == 0) && \
410 CmpVlanIds((x)->vlan_id, (y)->vlan_id) && ((x)->tunnel_id == (y)->tunnel_id))
414 static inline bool CmpFlowPacket(
const Flow *
f,
const Packet *
p)
420 return CmpAddrsAndPorts(f_src, f_dst,
f->
sp,
f->
dp, p_src, p_dst,
p->
sp,
p->
dp) &&
425 static inline bool CmpFlowKey(
const Flow *
f,
const FlowKey *k)
431 return CmpAddrsAndPorts(f_src, f_dst,
f->
sp,
f->
dp, k_src, k_dst, k->
sp, k->
dp) &&
436 static inline bool CmpAddrsAndICMPTypes(
const uint32_t src1[4],
437 const uint32_t dst1[4], uint8_t icmp_s_type1, uint8_t icmp_d_type1,
438 const uint32_t src2[4],
const uint32_t dst2[4], uint8_t icmp_s_type2,
439 uint8_t icmp_d_type2)
444 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
445 icmp_s_type1 == icmp_s_type2 && icmp_d_type1 == icmp_d_type2) ||
446 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
447 icmp_s_type1 == icmp_d_type2 && icmp_d_type1 == icmp_s_type2);
450 static inline bool CmpFlowICMPPacket(
const Flow *
f,
const Packet *
p)
456 return CmpAddrsAndICMPTypes(f_src, f_dst,
f->
icmp_s.type,
f->
icmp_d.type, p_src, p_dst,
471 static inline int FlowCompareICMPv4(
Flow *
f,
const Packet *
p)
501 return CmpFlowICMPPacket(
f,
p);
516 static inline int FlowCompareESP(
Flow *
f,
const Packet *
p)
523 return CmpAddrs(f_src, p_src) && CmpAddrs(f_dst, p_dst) &&
CmpFlowMisc(
f,
p) &&
536 if (
p->
proto == IPPROTO_ICMP) {
537 return FlowCompareICMPv4(
f,
p);
538 }
else if (PacketIsESP(
p)) {
539 return FlowCompareESP(
f,
p);
541 return CmpFlowPacket(
f,
p);
555 static inline bool FlowCreateCheck(
const Packet *
p,
const bool emerg)
560 if (PacketIsTCP(
p)) {
561 const TCPHdr *tcph = PacketGetTCP(
p);
571 if (PacketIsICMPv4(
p)) {
613 const Packet *
p,
const bool emerg)
616 bool spare_sync =
false;
633 if (
tv && fls->
dtv) {
657 static void FlowExceptionPolicyStatsIncr(
661 if (
tv == NULL || fls->
dtv == NULL) {
693 if (g_eps_flow_memcap != UINT64_MAX && g_eps_flow_memcap ==
PcapPacketCntGet(
p)) {
694 NoFlowHandleIPS(
tv, fls,
p);
699 if (!FlowCreateCheck(
p, emerg)) {
706 f = FlowSpareSync(
tv, fls,
p, emerg);
718 f = FlowGetUsedFlow(
tv, fls->
dtv,
p->
ts);
720 NoFlowHandleIPS(
tv, fls,
p);
722 if (
tv != NULL && fls->
dtv != NULL) {
731 if (
tv != NULL && fls->
dtv != NULL) {
746 if (
tv != NULL && fls->
dtv != NULL) {
752 NoFlowHandleIPS(
tv, fls,
p);
769 const uint32_t hash,
Packet *
p)
772 if (
tv != NULL && fls->
dtv != NULL) {
830 if (
f->
proto != IPPROTO_TCP || FlowBelongsToUs(
tv,
f)) {
837 f->
next = fb->evicted;
845 static inline bool FlowIsTimedOut(
878 tv_id = (uint16_t)
tv->
id;
881 tv_id = (uint16_t)
tv->
id;
912 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
915 if (fb->head == NULL) {
916 f = FlowGetNew(
tv, fls,
p);
931 FlowReference(dest,
f);
937 const uint16_t tv_id = GetTvId(
tv);
939 const uint32_t fb_nextts = !emerg ?
SC_ATOMIC_GET(fb->next_ts) : 0;
940 const bool timeout_check = (fb_nextts <= (uint32_t)
SCTIME_SECS(
p->
ts));
946 const bool our_flow = FlowCompare(
f,
p) != 0;
947 if (our_flow || timeout_check) {
949 const bool timedout = (timeout_check && FlowIsTimedOut(tv_id,
f,
p->
ts, emerg));
952 MoveToWorkQueue(
tv, fls, fb,
f, prev_f);
955 }
else if (our_flow) {
958 Flow *new_f = TcpReuseReplace(
tv, fls, fb,
f, hash,
p);
961 MoveToWorkQueue(
tv, fls, fb,
f, prev_f);
970 FlowReference(dest,
f);
983 if (next_f == NULL) {
984 f = FlowGetNew(
tv, fls,
p);
1000 FlowReference(dest,
f);
1005 }
while (
f != NULL);
1017 static inline bool FlowCompareKey(
Flow *
f,
FlowKey *key)
1019 if ((
f->
proto != IPPROTO_TCP) && (
f->
proto != IPPROTO_UDP))
1021 return CmpFlowKey(
f, key);
1035 uint32_t hash = flow_id & 0x0000FFFF;
1038 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
1041 if (FlowGetId(
f) == flow_id) {
1062 static Flow *FlowGetExistingFlowFromHash(
FlowKey *key,
const uint32_t hash)
1067 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
1071 if (FlowCompareKey(
f, key)) {
1099 Flow *
f = FlowGetExistingFlowFromHash(key, hash);
1108 SCLogDebug(
"Can't get a spare flow at start");
1114 f->
src.addr_data32[0] = key->
src.addr_data32[0];
1115 f->
src.addr_data32[1] = key->
src.addr_data32[1];
1116 f->
src.addr_data32[2] = key->
src.addr_data32[2];
1117 f->
src.addr_data32[3] = key->
src.addr_data32[3];
1118 f->
dst.addr_data32[0] = key->
dst.addr_data32[0];
1119 f->
dst.addr_data32[1] = key->
dst.addr_data32[1];
1120 f->
dst.addr_data32[2] = key->
dst.addr_data32[2];
1121 f->
dst.addr_data32[3] = key->
dst.addr_data32[3];
1129 }
else if (key->
src.
family == AF_INET6) {
1148 #define FLOW_GET_NEW_TRIES 5
1152 static inline int GetUsedTryLockBucket(FlowBucket *fb)
1157 static inline int GetUsedTryLockFlow(
Flow *
f)
1162 static inline uint32_t GetUsedAtomicUpdate(
const uint32_t val)
1199 #define STATSADDUI64(cnt, value) \
1201 StatsCounterAddI64(&tv->stats, dtv->cnt, (value)); \
1204 #define STATSADDUI64(cnt, value) StatsCounterAddI64(&tv->stats, dtv->cnt, (value));
1240 if (GetUsedTryLockBucket(fb) != 0) {
1251 if (GetUsedTryLockFlow(
f) != 0) {
1257 if (StillAlive(
f,
ts)) {
#define ESP_GET_SPI(esph)
Get the spi field off a packet.
FlowQueuePrivate work_queue
StatsCounterId counter_flow_icmp6
TmEcode OutputFlowLog(ThreadVars *tv, void *thread_data, Flow *f)
Run flow logger(s)
void ExceptionPolicyApply(Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason)
#define ICMPV4_GET_EMB_PROTO(p)
#define IPV4_GET_RAW_IPDST_U32(ip4h)
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
bool TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
struct Packet_::@34::@40 icmp_d
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
@ PKT_DROP_REASON_FLOW_MEMCAP
uint32_t address_un_data32[4]
FlowQueuePrivate FlowSpareGetFromPool(void)
uint64_t PcapPacketCntGet(const Packet *p)
StatsCounterId counter_flow_spare_sync_empty
uint32_t FlowKeyGetHash(FlowKey *fk)
#define ICMPV4_DEST_UNREACH_IS_VALID(p)
uint16_t vlan_id[VLAN_MAX_LAYERS]
struct Flow_::@126::@133 esp
unsigned int SCFlowStorageSize(void)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define FLOWLOCK_TRYWRLOCK(fb)
StatsCounterId counter_flow_get_used
struct FlowHashKey4_ FlowHashKey4
#define FBLOCK_TRYLOCK(fb)
uint32_t address_un_data32[4]
TcpStreamCnf stream_config
StatsCounterId counter_flow_spare_sync
SCTime_t TmThreadsGetThreadTime(const int idx)
#define FLOWLOCK_UNLOCK(fb)
void FlowWakeupFlowManagerThread(void)
struct Packet_::@32::@39 icmp_s
union Address_::@29 address
struct Flow_::@128::@134 icmp_d
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
uint32_t emerg_spare_sync_stamp
void StatsCounterAvgAddI64(StatsThreadContext *stats, StatsCounterAvgId id, int64_t x)
StatsCounterId counter_flow_memcap
void SCFlowRunFinishCallbacks(ThreadVars *tv, Flow *f)
#define FLOW_GET_NEW_TRIES
#define STATSADDUI64(cnt, value)
#define SCTIME_FROM_TIMESPEC(ts)
#define FLOWLOCK_WRLOCK(fb)
SC_ATOMIC_EXTERN(unsigned int, flow_prune_idx)
Per thread variable structure.
StatsCounterId counter_flow_active
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
struct FlowHashKey6_ FlowHashKey6
Flow * FlowQueuePrivateGetFromTop(FlowQueuePrivate *fqc)
StatsCounterAvgId counter_flow_spare_sync_avg
FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX]
StatsCounterId counter_flow_icmp4
bool TimeModeIsLive(void)
void FlowTimeoutsEmergency(void)
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
#define FLOW_END_FLAG_TCPREUSE
#define FLOW_END_FLAG_EMERGENCY
#define FBLOCK_UNLOCK(fb)
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
#define STREAM_PKT_FLAG_TCP_SESSION_REUSE
Data structures and function prototypes for keeping state for the detection engine.
int RunmodeIsUnittests(void)
void FlowUpdateState(Flow *f, const enum FlowState s)
FlowQueuePrivate spare_queue
uint32_t FlowGetIpPairProtoHash(const Packet *p)
#define SCTIME_CMP_LT(a, b)
struct Flow_::@126::@132 icmp_s
#define IPV4_GET_RAW_IPSRC_U32(ip4h)
StatsCounterId counter_flow_udp
ExceptionPolicyCounters counter_flow_memcap_eps
Flow * FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow **dest)
Get Flow for packet.
enum ExceptionPolicy memcap_policy
StatsCounterId counter_flow_spare_sync_incomplete
Structure to hold thread specific data for all decode modules.
Flow * FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t hash)
Get or create a Flow using a FlowKey.
union FlowAddress_::@125 address
void * output_flow_thread_data
void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
uint16_t vlan_id[VLAN_MAX_LAYERS]
#define STREAM_PKT_FLAG_SET(p, f)
uint16_t vlan_id[VLAN_MAX_LAYERS]
#define FLOW_END_FLAG_TIMEOUT
uint16_t vlan_id[VLAN_MAX_LAYERS]
StatsCounterId counter_flow_total
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
uint16_t vlan_id[VLAN_MAX_LAYERS]
void FlowQueuePrivateAppendFlow(FlowQueuePrivate *fqc, Flow *f)
Flow * FlowAlloc(void)
allocate a flow
#define SCTIME_ADD_SECS(ts, s)
Flow * FlowGetExistingFlowFromFlowId(uint64_t flow_id)
Look for existing Flow using a flow id value.
#define FLOW_END_FLAG_FORCED
#define ICMPV4_IS_ERROR_MSG(type)
StatsCounterId eps_id[EXCEPTION_POLICY_MAX]
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to indicate workers should do a flow look...
union PacketL4::L4Vars vars
FlowThreadId thread_id[2]
#define SC_ATOMIC_OR(name, val)
Bitwise OR a value to our atomic variable.
StatsCounterId counter_flow_tcp_reuse
#define CmpFlowMisc(x, y)
StatsCounterId counter_flow_tcp