You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/src/tmqh-packetpool.c

272 lines
8.1 KiB
C

/* Copyright (C) 2007-2010 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/**
* \file
*
* \author Victor Julien <victor@inliniac.net>
*
* Packetpool queue handlers. Packet pool is implemented as a ringbuffer.
* We're using a multi reader / multi writer version of the ringbuffer,
* that is relatively expensive due to the CAS function. But it is necessary
* because every thread can return packets to the pool and multiple parts
* of the code retrieve packets (Decode, Defrag) and these can run in their
* own threads as well.
*/
#include "suricata.h"
#include "packet-queue.h"
#include "decode.h"
#include "detect.h"
#include "detect-uricontent.h"
#include "threads.h"
#include "threadvars.h"
#include "flow.h"
#include "stream.h"
#include "tm-queuehandlers.h"
#include "pkt-var.h"
#include "tmqh-packetpool.h"
#include "util-ringbuffer.h"
#include "util-debug.h"
#include "util-error.h"
Add per packet profiling. Per packet profiling uses tick based accounting. It has 2 outputs, a summary and a csv file that contains per packet stats. Stats per packet include: 1) total ticks spent 2) ticks spent per individual thread module 3) "threading overhead" which is simply calculated by subtracting (2) of (1). A number of changes were made to integrate the new code in a clean way: a number of generic enums are now placed in tm-threads-common.h so we can include them from any part of the engine. Code depends on --enable-profiling just like the rule profiling code. New yaml parameters: profiling: # packet profiling packets: # Profiling can be disabled here, but it will still have a # performance impact if compiled in. enabled: yes filename: packet_stats.log append: yes # per packet csv output csv: # Output can be disabled here, but it will still have a # performance impact if compiled in. enabled: no filename: packet_stats.csv Example output of summary stats: IP ver Proto cnt min max avg ------ ----- ------ ------ ---------- ------- IPv4 6 19436 11448 5404365 32993 IPv4 256 4 11511 49968 30575 Per Thread module stats: Thread Module IP ver Proto cnt min max avg ------------------------ ------ ----- ------ ------ ---------- ------- TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770 TMM_DETECT IPv4 6 19436 1107 137241 1504 TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155 TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138 TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154 TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944 TMM_STREAMTCP IPv4 6 19434 828 1299159 19438 The proto 256 is a counter for handling of pseudo/tunnel packets. Example output of csv: pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading 1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337 First line of the file contains labels. 2 example gnuplot scripts added to plot the data.
14 years ago
#include "util-profiling.h"
static RingBuffer16 *ringbuffer = NULL;
/**
* \brief TmqhPacketpoolRegister
* \initonly
*/
void TmqhPacketpoolRegister (void) {
tmqh_table[TMQH_PACKETPOOL].name = "packetpool";
tmqh_table[TMQH_PACKETPOOL].InHandler = TmqhInputPacketpool;
tmqh_table[TMQH_PACKETPOOL].OutHandler = TmqhOutputPacketpool;
ringbuffer = RingBufferInit();
if (ringbuffer == NULL) {
SCLogError(SC_ERR_FATAL, "Error registering Packet pool handler (at ring buffer init)");
exit(EXIT_FAILURE);
}
}
void TmqhPacketpoolDestroy (void) {
if (ringbuffer != NULL) {
RingBufferDestroy(ringbuffer);
}
}
int PacketPoolIsEmpty(void) {
return RingBufferIsEmpty(ringbuffer);
}
uint16_t PacketPoolSize(void) {
return RingBufferSize(ringbuffer);
}
void PacketPoolWait(void) {
RingBufferWait(ringbuffer);
}
/** \brief a initialized packet
*
* \warning Use *only* at init, not at packet runtime
*/
void PacketPoolStorePacket(Packet *p) {
if (RingBufferIsFull(ringbuffer)) {
exit(1);
}
RingBufferMrMwPut(ringbuffer, (void *)p);
SCLogDebug("buffersize %u", RingBufferSize(ringbuffer));
}
/** \brief get a packet from the packet pool, but if the
* pool is empty, don't wait, just return NULL
*/
Packet *PacketPoolGetPacket(void) {
if (RingBufferIsEmpty(ringbuffer))
return NULL;
Packet *p = RingBufferMrMwGetNoWait(ringbuffer);
return p;
}
Packet *TmqhInputPacketpool(ThreadVars *t)
{
Packet *p = NULL;
while (p == NULL && ringbuffer->shutdown == FALSE) {
p = RingBufferMrMwGet(ringbuffer);
17 years ago
}
/* packet is clean */
return p;
}
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
{
int proot = 0;
SCEnter();
SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, p->flags & PKT_ALLOC ? "true" : "false");
/* final alerts cleanup... return smsgs to pool if needed */
if (p->alerts.alert_msgs != NULL) {
StreamMsgReturnListToPool(p->alerts.alert_msgs);
p->alerts.alert_msgs = NULL;
}
17 years ago
if (IS_TUNNEL_PKT(p)) {
SCLogDebug("Packet %p is a tunnel packet: %s",
p,p->root ? "upper layer" : "tunnel root");
17 years ago
/* get a lock to access root packet fields */
SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex;
SCMutexLock(m);
17 years ago
if (IS_TUNNEL_ROOT_PKT(p)) {
SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE");
17 years ago
if (TUNNEL_PKT_TPR(p) == 0) {
SCLogDebug("TUNNEL_PKT_TPR(p) == 0, no more tunnel packet "
"depending on this root");
17 years ago
/* if this packet is the root and there are no
* more tunnel packets, return it to the pool */
17 years ago
/* fall through */
} else {
SCLogDebug("tunnel root Packet %p: TUNNEL_PKT_TPR(p) > 0, so "
"packets are still depending on this root, setting "
"p->tunnel_verdicted == 1", p);
17 years ago
/* if this is the root and there are more tunnel
* packets, return this to the pool. It's still referenced
* by the tunnel packets, and we will return it
17 years ago
* when we handle them */
SET_TUNNEL_PKT_VERDICTED(p);
Add per packet profiling. Per packet profiling uses tick based accounting. It has 2 outputs, a summary and a csv file that contains per packet stats. Stats per packet include: 1) total ticks spent 2) ticks spent per individual thread module 3) "threading overhead" which is simply calculated by subtracting (2) of (1). A number of changes were made to integrate the new code in a clean way: a number of generic enums are now placed in tm-threads-common.h so we can include them from any part of the engine. Code depends on --enable-profiling just like the rule profiling code. New yaml parameters: profiling: # packet profiling packets: # Profiling can be disabled here, but it will still have a # performance impact if compiled in. enabled: yes filename: packet_stats.log append: yes # per packet csv output csv: # Output can be disabled here, but it will still have a # performance impact if compiled in. enabled: no filename: packet_stats.csv Example output of summary stats: IP ver Proto cnt min max avg ------ ----- ------ ------ ---------- ------- IPv4 6 19436 11448 5404365 32993 IPv4 256 4 11511 49968 30575 Per Thread module stats: Thread Module IP ver Proto cnt min max avg ------------------------ ------ ----- ------ ------ ---------- ------- TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770 TMM_DETECT IPv4 6 19436 1107 137241 1504 TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155 TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138 TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154 TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944 TMM_STREAMTCP IPv4 6 19434 828 1299159 19438 The proto 256 is a counter for handling of pseudo/tunnel packets. Example output of csv: pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading 1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337 First line of the file contains labels. 2 example gnuplot scripts added to plot the data.
14 years ago
SCMutexUnlock(m);
Add per packet profiling. Per packet profiling uses tick based accounting. It has 2 outputs, a summary and a csv file that contains per packet stats. Stats per packet include: 1) total ticks spent 2) ticks spent per individual thread module 3) "threading overhead" which is simply calculated by subtracting (2) of (1). A number of changes were made to integrate the new code in a clean way: a number of generic enums are now placed in tm-threads-common.h so we can include them from any part of the engine. Code depends on --enable-profiling just like the rule profiling code. New yaml parameters: profiling: # packet profiling packets: # Profiling can be disabled here, but it will still have a # performance impact if compiled in. enabled: yes filename: packet_stats.log append: yes # per packet csv output csv: # Output can be disabled here, but it will still have a # performance impact if compiled in. enabled: no filename: packet_stats.csv Example output of summary stats: IP ver Proto cnt min max avg ------ ----- ------ ------ ---------- ------- IPv4 6 19436 11448 5404365 32993 IPv4 256 4 11511 49968 30575 Per Thread module stats: Thread Module IP ver Proto cnt min max avg ------------------------ ------ ----- ------ ------ ---------- ------- TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770 TMM_DETECT IPv4 6 19436 1107 137241 1504 TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155 TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138 TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154 TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944 TMM_STREAMTCP IPv4 6 19434 828 1299159 19438 The proto 256 is a counter for handling of pseudo/tunnel packets. Example output of csv: pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading 1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337 First line of the file contains labels. 2 example gnuplot scripts added to plot the data.
14 years ago
PACKET_PROFILING_END(p);
SCReturn;
17 years ago
}
} else {
SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt");
/* the p->root != NULL here seems unnecessary: IS_TUNNEL_PKT checks
* that p->tunnel_pkt == 1, IS_TUNNEL_ROOT_PKT checks that +
* p->root == NULL. So when we are here p->root can only be
* non-NULL, right? CLANG thinks differently. May be a FP, but
* better safe than sorry. VJ */
if (p->root != NULL && IS_TUNNEL_PKT_VERDICTED(p->root) &&
TUNNEL_PKT_TPR(p) == 1)
{
SCLogDebug("p->root->tunnel_verdicted == 1 && TUNNEL_PKT_TPR(p) == 1");
17 years ago
/* the root is ready and we are the last tunnel packet,
* lets enqueue them both. */
TUNNEL_DECR_PKT_TPR_NOLOCK(p);
17 years ago
/* handle the root */
SCLogDebug("setting proot = 1 for root pkt, p->root %p "
"(tunnel packet %p)", p->root, p);
17 years ago
proot = 1;
/* fall through */
} else {
/* root not ready yet, so get rid of the tunnel pkt only */
SCLogDebug("NOT p->root->tunnel_verdicted == 1 && "
"TUNNEL_PKT_TPR(p) == 1 (%" PRIu32 ")", TUNNEL_PKT_TPR(p));
TUNNEL_DECR_PKT_TPR_NOLOCK(p);
17 years ago
/* fall through */
}
}
SCMutexUnlock(m);
SCLogDebug("tunnel stuff done, move on (proot %d)", proot);
17 years ago
}
FlowDecrUsecnt(p->flow);
/* we're done with the tunnel root now as well */
if (proot == 1) {
SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false");
FlowDecrUsecnt(p->root->flow);
/* if p->root uses extended data, free them */
if (p->root->ext_pkt) {
SCFree(p->root->ext_pkt);
p->root->ext_pkt = NULL;
}
if (p->root->flags & PKT_ALLOC) {
PACKET_CLEANUP(p->root);
SCFree(p->root);
p->root = NULL;
} else {
PACKET_RECYCLE(p->root);
RingBufferMrMwPut(ringbuffer, (void *)p->root);
}
}
/* if p uses extended data, free them */
if (p->ext_pkt) {
SCFree(p->ext_pkt);
p->ext_pkt = NULL;
}
Add per packet profiling. Per packet profiling uses tick based accounting. It has 2 outputs, a summary and a csv file that contains per packet stats. Stats per packet include: 1) total ticks spent 2) ticks spent per individual thread module 3) "threading overhead" which is simply calculated by subtracting (2) of (1). A number of changes were made to integrate the new code in a clean way: a number of generic enums are now placed in tm-threads-common.h so we can include them from any part of the engine. Code depends on --enable-profiling just like the rule profiling code. New yaml parameters: profiling: # packet profiling packets: # Profiling can be disabled here, but it will still have a # performance impact if compiled in. enabled: yes filename: packet_stats.log append: yes # per packet csv output csv: # Output can be disabled here, but it will still have a # performance impact if compiled in. enabled: no filename: packet_stats.csv Example output of summary stats: IP ver Proto cnt min max avg ------ ----- ------ ------ ---------- ------- IPv4 6 19436 11448 5404365 32993 IPv4 256 4 11511 49968 30575 Per Thread module stats: Thread Module IP ver Proto cnt min max avg ------------------------ ------ ----- ------ ------ ---------- ------- TMM_DECODEPCAPFILE IPv4 6 19434 1242 47889 1770 TMM_DETECT IPv4 6 19436 1107 137241 1504 TMM_ALERTFASTLOG IPv4 6 19436 90 1323 155 TMM_ALERTUNIFIED2ALERT IPv4 6 19436 108 1359 138 TMM_ALERTDEBUGLOG IPv4 6 19436 90 1134 154 TMM_LOGHTTPLOG IPv4 6 19436 414 5392089 7944 TMM_STREAMTCP IPv4 6 19434 828 1299159 19438 The proto 256 is a counter for handling of pseudo/tunnel packets. Example output of csv: pcap_cnt,ipver,ipproto,total,TMM_DECODENFQ,TMM_VERDICTNFQ,TMM_RECEIVENFQ,TMM_RECEIVEPCAP,TMM_RECEIVEPCAPFILE,TMM_DECODEPCAP,TMM_DECODEPCAPFILE,TMM_RECEIVEPFRING,TMM_DECODEPFRING,TMM_DETECT,TMM_ALERTFASTLOG,TMM_ALERTFASTLOG4,TMM_ALERTFASTLOG6,TMM_ALERTUNIFIEDLOG,TMM_ALERTUNIFIEDALERT,TMM_ALERTUNIFIED2ALERT,TMM_ALERTPRELUDE,TMM_ALERTDEBUGLOG,TMM_ALERTSYSLOG,TMM_LOGDROPLOG,TMM_ALERTSYSLOG4,TMM_ALERTSYSLOG6,TMM_RESPONDREJECT,TMM_LOGHTTPLOG,TMM_LOGHTTPLOG4,TMM_LOGHTTPLOG6,TMM_PCAPLOG,TMM_STREAMTCP,TMM_DECODEIPFW,TMM_VERDICTIPFW,TMM_RECEIVEIPFW,TMM_RECEIVEERFFILE,TMM_DECODEERFFILE,TMM_RECEIVEERFDAG,TMM_DECODEERFDAG,threading 1,4,6,172008,0,0,0,0,0,0,47889,0,0,48582,1323,0,0,0,0,1359,0,1134,0,0,0,0,0,8028,0,0,0,49356,0,0,0,0,0,0,0,14337 First line of the file contains labels. 2 example gnuplot scripts added to plot the data.
14 years ago
PACKET_PROFILING_END(p);
SCLogDebug("getting rid of tunnel pkt... alloc'd %s (root %p)", p->flags & PKT_ALLOC ? "true" : "false", p->root);
if (p->flags & PKT_ALLOC) {
PACKET_CLEANUP(p);
SCFree(p);
} else {
PACKET_RECYCLE(p);
RingBufferMrMwPut(ringbuffer, (void *)p);
}
SCReturn;
}
/**
* \brief Release all the packets in the queue back to the packetpool. Mainly
* used by threads that have failed, and wants to return the packets back
* to the packetpool.
*
* \param pq Pointer to the packetqueue from which the packets have to be
* returned back to the packetpool
*
* \warning this function assumes that the pq does not use locking
*/
void TmqhReleasePacketsToPacketPool(PacketQueue *pq)
{
Packet *p = NULL;
if (pq == NULL)
return;
while ( (p = PacketDequeue(pq)) != NULL)
TmqhOutputPacketpool(NULL, p);
return;
}