|
|
|
|
/* Copyright (C) 2007-2014 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>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef __TMQH_PACKETPOOL_H__
|
|
|
|
|
#define __TMQH_PACKETPOOL_H__
|
|
|
|
|
|
|
|
|
|
#include "decode.h"
|
For PktPool add local pending freed packets list.
Better handle the autofp case where one thread allocates the majority
of the packets and other threads free those packets.
Add a list of locally pending packets. The first packet freed goes on the
pending list, then subsequent freed packets for the same Packet Pool are
added to this list until it hits a fixed number of packets, then the
entire list of packets is pushed onto the pool's return stack. If a freed
packet is not for the pending pool, it is freed immediately to its pool's
return stack, as before.
For the autofp case, since there is only one Packet Pool doing all the
allocation, every other thread will keep a list of pending packets for
that pool.
For the worker run mode, most packets are allocated and freed locally. For
the case where packets are being returned to a remote pool, a pending list
will be kept for one of those other threads, all others are returned as before.
Which remote pool for which to keep a pending list is changed each time the
pending list is returned. Since the return pending pool is cleared when it is
freed, then next packet to be freed chooses the new pending pool.
12 years ago
|
|
|
#include "threads.h"
|
|
|
|
|
|
|
|
|
|
/* Return stack, onto which other threads free packets. */
|
|
|
|
|
typedef struct PktPoolLockedStack_{
|
|
|
|
|
/* linked list of free packets. */
|
|
|
|
|
SCMutex mutex;
|
|
|
|
|
SCCondT cond;
|
|
|
|
|
SC_ATOMIC_DECLARE(int, sync_now);
|
For PktPool add local pending freed packets list.
Better handle the autofp case where one thread allocates the majority
of the packets and other threads free those packets.
Add a list of locally pending packets. The first packet freed goes on the
pending list, then subsequent freed packets for the same Packet Pool are
added to this list until it hits a fixed number of packets, then the
entire list of packets is pushed onto the pool's return stack. If a freed
packet is not for the pending pool, it is freed immediately to its pool's
return stack, as before.
For the autofp case, since there is only one Packet Pool doing all the
allocation, every other thread will keep a list of pending packets for
that pool.
For the worker run mode, most packets are allocated and freed locally. For
the case where packets are being returned to a remote pool, a pending list
will be kept for one of those other threads, all others are returned as before.
Which remote pool for which to keep a pending list is changed each time the
pending list is returned. Since the return pending pool is cleared when it is
freed, then next packet to be freed chooses the new pending pool.
12 years ago
|
|
|
Packet *head;
|
|
|
|
|
} __attribute__((aligned(CLS))) PktPoolLockedStack;
|
|
|
|
|
|
|
|
|
|
typedef struct PktPool_ {
|
|
|
|
|
/* link listed of free packets local to this thread.
|
For PktPool add local pending freed packets list.
Better handle the autofp case where one thread allocates the majority
of the packets and other threads free those packets.
Add a list of locally pending packets. The first packet freed goes on the
pending list, then subsequent freed packets for the same Packet Pool are
added to this list until it hits a fixed number of packets, then the
entire list of packets is pushed onto the pool's return stack. If a freed
packet is not for the pending pool, it is freed immediately to its pool's
return stack, as before.
For the autofp case, since there is only one Packet Pool doing all the
allocation, every other thread will keep a list of pending packets for
that pool.
For the worker run mode, most packets are allocated and freed locally. For
the case where packets are being returned to a remote pool, a pending list
will be kept for one of those other threads, all others are returned as before.
Which remote pool for which to keep a pending list is changed each time the
pending list is returned. Since the return pending pool is cleared when it is
freed, then next packet to be freed chooses the new pending pool.
12 years ago
|
|
|
* No mutex is needed.
|
|
|
|
|
*/
|
|
|
|
|
Packet *head;
|
For PktPool add local pending freed packets list.
Better handle the autofp case where one thread allocates the majority
of the packets and other threads free those packets.
Add a list of locally pending packets. The first packet freed goes on the
pending list, then subsequent freed packets for the same Packet Pool are
added to this list until it hits a fixed number of packets, then the
entire list of packets is pushed onto the pool's return stack. If a freed
packet is not for the pending pool, it is freed immediately to its pool's
return stack, as before.
For the autofp case, since there is only one Packet Pool doing all the
allocation, every other thread will keep a list of pending packets for
that pool.
For the worker run mode, most packets are allocated and freed locally. For
the case where packets are being returned to a remote pool, a pending list
will be kept for one of those other threads, all others are returned as before.
Which remote pool for which to keep a pending list is changed each time the
pending list is returned. Since the return pending pool is cleared when it is
freed, then next packet to be freed chooses the new pending pool.
12 years ago
|
|
|
/* Packets waiting (pending) to be returned to the given Packet
|
|
|
|
|
* Pool. Accumulate packets for the same pool until a theshold is
|
|
|
|
|
* reached, then return them all at once. Keep the head and tail
|
|
|
|
|
* to fast insertion of the entire list onto a return stack.
|
|
|
|
|
*/
|
|
|
|
|
struct PktPool_ *pending_pool;
|
|
|
|
|
Packet *pending_head;
|
|
|
|
|
Packet *pending_tail;
|
|
|
|
|
uint32_t pending_count;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_VALIDATION
|
|
|
|
|
int initialized;
|
|
|
|
|
int destroyed;
|
|
|
|
|
#endif /* DEBUG_VALIDATION */
|
|
|
|
|
|
|
|
|
|
/* All members above this point are accessed locally by only one thread, so
|
For PktPool add local pending freed packets list.
Better handle the autofp case where one thread allocates the majority
of the packets and other threads free those packets.
Add a list of locally pending packets. The first packet freed goes on the
pending list, then subsequent freed packets for the same Packet Pool are
added to this list until it hits a fixed number of packets, then the
entire list of packets is pushed onto the pool's return stack. If a freed
packet is not for the pending pool, it is freed immediately to its pool's
return stack, as before.
For the autofp case, since there is only one Packet Pool doing all the
allocation, every other thread will keep a list of pending packets for
that pool.
For the worker run mode, most packets are allocated and freed locally. For
the case where packets are being returned to a remote pool, a pending list
will be kept for one of those other threads, all others are returned as before.
Which remote pool for which to keep a pending list is changed each time the
pending list is returned. Since the return pending pool is cleared when it is
freed, then next packet to be freed chooses the new pending pool.
12 years ago
|
|
|
* these should live on their own cache line.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Return stack, where other threads put packets that they free that belong
|
|
|
|
|
* to this thread.
|
|
|
|
|
*/
|
|
|
|
|
PktPoolLockedStack return_stack;
|
|
|
|
|
} PktPool;
|
|
|
|
|
|
|
|
|
|
Packet *TmqhInputPacketpool(ThreadVars *);
|
|
|
|
|
void TmqhOutputPacketpool(ThreadVars *, Packet *);
|
|
|
|
|
void TmqhReleasePacketsToPacketPool(PacketQueue *);
|
|
|
|
|
void TmqhPacketpoolRegister(void);
|
|
|
|
|
Packet *PacketPoolGetPacket(void);
|
|
|
|
|
void PacketPoolWait(void);
|
|
|
|
|
void PacketPoolWaitForN(int n);
|
|
|
|
|
void PacketPoolReturnPacket(Packet *p);
|
|
|
|
|
void PacketPoolInit(void);
|
|
|
|
|
void PacketPoolInitEmpty(void);
|
|
|
|
|
void PacketPoolDestroy(void);
|
threading: avoid autofp deadlock
When there are many threads and/or the packet pool (max-pending-packets) is
small, a potential dead lock exists between the packet pool return pool
logic and the capture threads. The autofp workers together can have all the
packets in their return pools, while the capture thread(s) are waiting at an
empty pool. A race between the worker threads and the capture thread, where
the latter signals the former, is lost by the capture thread. Now everyone
is waiting.
To avoid this scenario, this patch makes the previously hardcoded 'return
pool' threshold dynamic based on the number of threads and the packet pool
size.
It sets the threshold to the max pending packets value, divided by the number
of lister threads. The max value hasn't changed. Normally, in the autofp
runmode these are the stream/detect/log worker threads.
The max_pending_return_packets value needs to stay below the packet pool size
of the 'producers' (normally pkt capture threads but also flow timeout
injection) to avoid the deadlock.
As it's quite impossible at this time to learn how many threads will be
created before starting the runmodes, and thus spawning the threads and
already initializing the packet pools, this code sets a global variable
after runmode setup, but before the threads are 'unpaused'.
11 years ago
|
|
|
void PacketPoolPostRunmodes(void);
|
|
|
|
|
|
|
|
|
|
#endif /* __TMQH_PACKETPOOL_H__ */
|