Go to the documentation of this file.
72 static inline int FlowHashRawAddressIPv6GtU32(
const uint32_t *a,
const uint32_t *b)
74 for (
int i = 0; i < 4; i++) {
93 const uint32_t
u32[5];
123 static inline uint32_t FlowGetHash(
const Packet *p)
127 if (p->
ip4h != NULL) {
128 if (p->
tcph != NULL || p->
udph != NULL) {
131 int ai = (p->
src.addr_data32[0] > p->
dst.addr_data32[0]);
132 fhk.
addrs[1-ai] = p->
src.addr_data32[0];
133 fhk.
addrs[ai] = p->
dst.addr_data32[0];
135 const int pi = (p->
sp > p->
dp);
153 const int ai = (psrc > pdst);
154 fhk.
addrs[1-ai] = psrc;
155 fhk.
addrs[ai] = pdst;
170 const int ai = (p->
src.addr_data32[0] > p->
dst.addr_data32[0]);
171 fhk.
addrs[1-ai] = p->
src.addr_data32[0];
172 fhk.
addrs[ai] = p->
dst.addr_data32[0];
173 fhk.
ports[0] = 0xfeed;
174 fhk.
ports[1] = 0xbeef;
182 }
else if (p->
ip6h != NULL) {
184 if (FlowHashRawAddressIPv6GtU32(p->
src.addr_data32, p->
dst.addr_data32)) {
185 fhk.
src[0] = p->
src.addr_data32[0];
186 fhk.
src[1] = p->
src.addr_data32[1];
187 fhk.
src[2] = p->
src.addr_data32[2];
188 fhk.
src[3] = p->
src.addr_data32[3];
189 fhk.
dst[0] = p->
dst.addr_data32[0];
190 fhk.
dst[1] = p->
dst.addr_data32[1];
191 fhk.
dst[2] = p->
dst.addr_data32[2];
192 fhk.
dst[3] = p->
dst.addr_data32[3];
194 fhk.
src[0] = p->
dst.addr_data32[0];
195 fhk.
src[1] = p->
dst.addr_data32[1];
196 fhk.
src[2] = p->
dst.addr_data32[2];
197 fhk.
src[3] = p->
dst.addr_data32[3];
198 fhk.
dst[0] = p->
src.addr_data32[0];
199 fhk.
dst[1] = p->
src.addr_data32[1];
200 fhk.
dst[2] = p->
src.addr_data32[2];
201 fhk.
dst[3] = p->
src.addr_data32[3];
204 const int pi = (p->
sp > p->
dp);
236 const int pi = (fk->
sp > fk->
dp);
269 const int pi = (fk->
sp > fk->
dp);
282 static inline bool CmpAddrs(
const uint32_t addr1[4],
const uint32_t addr2[4])
284 return addr1[0] == addr2[0] && addr1[1] == addr2[1] &&
285 addr1[2] == addr2[2] && addr1[3] == addr2[3];
288 static inline bool CmpAddrsAndPorts(
const uint32_t src1[4],
289 const uint32_t dst1[4],
Port src_port1,
Port dst_port1,
290 const uint32_t src2[4],
const uint32_t dst2[4],
Port src_port2,
296 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
297 src_port1 == src_port2 && dst_port1 == dst_port2) ||
298 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
299 src_port1 == dst_port2 && dst_port1 == src_port2);
302 static inline bool CmpVlanIds(
const uint16_t vlan_id1[2],
const uint16_t vlan_id2[2])
304 return ((vlan_id1[0] ^ vlan_id2[0]) &
g_vlan_mask) == 0 &&
310 static inline bool CmpFlowPacket(
const Flow *f,
const Packet *p)
316 return CmpAddrsAndPorts(f_src, f_dst, f->
sp, f->
dp, p_src, p_dst, p->
sp,
322 static inline bool CmpFlowKey(
const Flow *f,
const FlowKey *k)
328 return CmpAddrsAndPorts(f_src, f_dst, f->
sp, f->
dp, k_src, k_dst, k->
sp,
334 static inline bool CmpAddrsAndICMPTypes(
const uint32_t src1[4],
335 const uint32_t dst1[4], uint8_t icmp_s_type1, uint8_t icmp_d_type1,
336 const uint32_t src2[4],
const uint32_t dst2[4], uint8_t icmp_s_type2,
337 uint8_t icmp_d_type2)
342 return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
343 icmp_s_type1 == icmp_s_type2 && icmp_d_type1 == icmp_d_type2) ||
344 (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
345 icmp_s_type1 == icmp_d_type2 && icmp_d_type1 == icmp_s_type2);
348 static inline bool CmpFlowICMPPacket(
const Flow *f,
const Packet *p)
354 return CmpAddrsAndICMPTypes(f_src, f_dst, f->
icmp_s.type,
370 static inline int FlowCompareICMPv4(
Flow *f,
const Packet *p)
404 return CmpFlowICMPPacket(f, p);
419 static inline int FlowCompareESP(
Flow *f,
const Packet *p)
426 return CmpAddrs(f_src, p_src) && CmpAddrs(f_dst, p_dst) && f->
proto == p->
proto &&
437 static inline int FlowCompare(
Flow *f,
const Packet *p)
439 if (p->
proto == IPPROTO_ICMP) {
440 return FlowCompareICMPv4(f, p);
441 }
else if (p->
proto == IPPROTO_ESP) {
442 return FlowCompareESP(f, p);
444 return CmpFlowPacket(f, p);
459 static inline int FlowCreateCheck(
const Packet *p,
const bool emerg)
513 const Packet *p,
const bool emerg)
516 bool spare_sync =
false;
533 if (
tv && fls->
dtv) {
567 if (FlowCreateCheck(p, emerg) == 0) {
574 f = FlowSpareSync(
tv, fls, p, emerg);
585 f = FlowGetUsedFlow(
tv, fls->
dtv, &p->
ts);
590 if (
tv != NULL && fls->
dtv != NULL) {
605 if (
tv != NULL && fls->
dtv != NULL) {
627 FlowBucket *fb,
Flow *old_f,
628 const uint32_t hash,
const Packet *p)
631 if (
tv != NULL && fls->
dtv != NULL) {
648 Flow *f = FlowGetNew(
tv, fls, p);
681 FlowBucket *fb,
Flow *f,
Flow *prev_f)
691 if (f->
proto != IPPROTO_TCP || FlowBelongsToUs(
tv, f)) {
698 f->
next = fb->evicted;
707 static inline bool FlowIsTimedOut(
const Flow *f,
const uint32_t sec,
const bool emerg)
716 if ((int64_t)sec >= timeout_at)
722 static inline void FromHashLockBucket(FlowBucket *fb)
726 static inline void FromHashLockTO(
Flow *f)
730 static inline void FromHashLockCMP(
Flow *f)
760 FromHashLockBucket(fb);
762 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
765 if (fb->head == NULL) {
766 f = FlowGetNew(
tv, fls, p);
781 FlowReference(dest, f);
788 const uint32_t fb_nextts = !emerg ?
SC_ATOMIC_GET(fb->next_ts) : 0;
794 const bool timedout =
795 (fb_nextts < (uint32_t)p->
ts.tv_sec && FlowIsTimedOut(f, (uint32_t)p->
ts.tv_sec, emerg));
800 MoveToWorkQueue(
tv, fls, fb, f, prev_f);
805 }
else if (FlowCompare(f, p) != 0) {
809 f = TcpReuseReplace(
tv, fls, fb, f, hash, p);
815 FlowReference(dest, f);
825 if (next_f == NULL) {
826 f = FlowGetNew(
tv, fls, p);
842 FlowReference(dest, f);
854 static inline int FlowCompareKey(
Flow *f,
FlowKey *key)
856 if ((f->
proto != IPPROTO_TCP) && (f->
proto != IPPROTO_UDP))
858 return CmpFlowKey(f, key);
886 SCLogDebug(
"Can't get a spare flow at start");
892 f->
src.addr_data32[0] = key->
src.addr_data32[0];
893 f->
src.addr_data32[1] = key->
src.addr_data32[1];
894 f->
src.addr_data32[2] = key->
src.addr_data32[2];
895 f->
src.addr_data32[3] = key->
src.addr_data32[3];
896 f->
dst.addr_data32[0] = key->
dst.addr_data32[0];
897 f->
dst.addr_data32[1] = key->
dst.addr_data32[1];
898 f->
dst.addr_data32[2] = key->
dst.addr_data32[2];
899 f->
dst.addr_data32[3] = key->
dst.addr_data32[3];
906 }
else if (key->
src.
family == AF_INET6) {
912 f->
startts.tv_sec = ttime->tv_sec;
913 f->
startts.tv_usec = ttime->tv_nsec * 1000;
943 SCLogDebug(
"fb %p fb->head %p", fb, fb->head);
946 if (fb->head == NULL) {
955 if (FlowCompareKey(f, key) == 0) {
964 if (FlowCompareKey(f, key) != 0) {
981 #define FLOW_GET_NEW_TRIES 5
985 static inline int GetUsedTryLockBucket(FlowBucket *fb)
990 static inline int GetUsedTryLockFlow(
Flow *f)
995 static inline uint32_t GetUsedAtomicUpdate(
const uint32_t val)
1004 static inline bool StillAlive(
const Flow *f,
const struct timeval *
ts)
1008 if (
ts->tv_sec - f->
lastts.tv_sec <= 1) {
1013 if (
ts->tv_sec - f->
lastts.tv_sec <= 5) {
1018 if (
ts->tv_sec - f->
lastts.tv_sec <= 3) {
1023 if (
ts->tv_sec - f->
lastts.tv_sec < 30) {
1032 #define STATSADDUI64(cnt, value) \
1034 StatsAddUI64(tv, dtv->cnt, (value)); \
1037 #define STATSADDUI64(cnt, value) \
1038 StatsAddUI64(tv, dtv->cnt, (value));
1074 if (GetUsedTryLockBucket(fb) != 0) {
1085 if (GetUsedTryLockFlow(f) != 0) {
1100 if (StillAlive(f,
ts)) {
FlowQueuePrivate work_queue
TmEcode OutputFlowLog(ThreadVars *tv, void *thread_data, Flow *f)
Run flow logger(s)
uint16_t counter_flow_udp
#define ICMPV4_GET_EMB_PROTO(p)
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
#define IPV4_GET_RAW_IPDST_U32(ip4h)
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
uint16_t counter_flow_icmp4
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
uint32_t address_un_data32[4]
FlowQueuePrivate FlowSpareGetFromPool(void)
uint16_t counter_flow_spare_sync_avg
uint32_t FlowKeyGetHash(FlowKey *fk)
#define ICMPV4_DEST_UNREACH_IS_VALID(p)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define FLOWLOCK_TRYWRLOCK(fb)
struct FlowHashKey4_ FlowHashKey4
#define FBLOCK_TRYLOCK(fb)
uint16_t counter_flow_tcp
uint32_t address_un_data32[4]
TcpStreamCnf stream_config
uint16_t counter_flow_get_used
#define FLOWLOCK_UNLOCK(fb)
uint16_t counter_flow_spare_sync_empty
uint16_t counter_flow_tcp_reuse
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
uint32_t emerg_spare_sync_stamp
int TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn)
uint16_t counter_flow_spare_sync
#define FLOW_GET_NEW_TRIES
#define STATSADDUI64(cnt, value)
struct Packet_::@39::@48 icmp_s
#define ICMPV4_GET_EMB_IPV4(p)
union FlowAddress_::@118 address
#define FLOWLOCK_WRLOCK(fb)
SC_ATOMIC_EXTERN(unsigned int, flow_prune_idx)
Per thread variable structure.
unsigned int FlowStorageSize(void)
struct FlowHashKey6_ FlowHashKey6
Flow * FlowQueuePrivateGetFromTop(FlowQueuePrivate *fqc)
Flow * FlowGetExistingFlowFromHash(FlowKey *key, const uint32_t hash)
Look for existing Flow using a FlowKey.
void FlowTimeoutsEmergency(void)
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
#define ESP_GET_SPI(p)
Get the spi field off a packet.
#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.
FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX]
Data structures and function prototypes for keeping state for the detection engine.
Flow * FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, const Packet *p, Flow **dest)
Get Flow for packet.
int RunmodeIsUnittests(void)
void FlowUpdateState(Flow *f, const enum FlowState s)
FlowQueuePrivate spare_queue
uint16_t counter_flow_spare_sync_incomplete
#define IPV4_GET_RAW_IPSRC_U32(ip4h)
uint16_t counter_flow_icmp6
struct Flow_::@121::@127 icmp_d
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
#define ICMPV4_IS_ERROR_MSG(p)
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.
void * output_flow_thread_data
uint16_t counter_flow_memcap
struct Packet_::@41::@49 icmp_d
struct Flow_::@119::@126 esp
union Address_::@38 address
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
void FlowQueuePrivateAppendFlow(FlowQueuePrivate *fqc, Flow *f)
Flow * FlowAlloc(void)
allocate a flow
#define FLOW_END_FLAG_FORCED
void FlowInit(Flow *f, const Packet *p)
struct Flow_::@119::@125 icmp_s
void FlowSetupPacket(Packet *p)
prepare packet for a life with flow Set PKT_WANTS_FLOW flag to incidate workers should do a flow look...
FlowThreadId thread_id[2]
#define SC_ATOMIC_OR(name, val)
Bitwise OR a value to our atomic variable.