suricata
tmqh-packetpool.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * Packetpool queue handlers. Packet pool is implemented as a stack.
24  */
25 
26 #include "suricata-common.h"
27 #include "tmqh-packetpool.h"
28 #include "tm-queuehandlers.h"
29 #include "tm-threads.h"
30 #include "threads.h"
31 #include "decode.h"
32 #include "tm-modules.h"
33 #include "packet.h"
34 #include "util-profiling.h"
35 #include "util-validate.h"
36 #include "action-globals.h"
37 
38 /* Number of freed packet to save for one pool before freeing them. */
39 #define MAX_PENDING_RETURN_PACKETS 32
40 static uint32_t max_pending_return_packets = MAX_PENDING_RETURN_PACKETS;
41 
42 thread_local PktPool thread_pkt_pool;
43 
44 static inline PktPool *GetThreadPacketPool(void)
45 {
46  return &thread_pkt_pool;
47 }
48 
49 /**
50  * \brief TmqhPacketpoolRegister
51  * \initonly
52  */
54 {
55  tmqh_table[TMQH_PACKETPOOL].name = "packetpool";
58 }
59 
60 static int PacketPoolIsEmpty(PktPool *pool)
61 {
62  /* Check local stack first. */
63  if (pool->head || pool->return_stack.head)
64  return 0;
65 
66  return 1;
67 }
68 
69 void PacketPoolWait(void)
70 {
71  PktPool *my_pool = GetThreadPacketPool();
72 
73  if (PacketPoolIsEmpty(my_pool)) {
74  SCMutexLock(&my_pool->return_stack.mutex);
75  SC_ATOMIC_ADD(my_pool->return_stack.sync_now, 1);
76  SCCondWait(&my_pool->return_stack.cond, &my_pool->return_stack.mutex);
77  SCMutexUnlock(&my_pool->return_stack.mutex);
78  }
79 
80  while(PacketPoolIsEmpty(my_pool))
81  cc_barrier();
82 }
83 
84 /** \brief Wait until we have the requested amount of packets in the pool
85  *
86  * In some cases waiting for packets is undesirable. Especially when
87  * a wait would happen under a lock of some kind, other parts of the
88  * engine could have to wait.
89  *
90  * This function only returns when at least N packets are in our pool.
91  *
92  * If counting in our pool's main stack didn't give us the number we
93  * are seeking, we check if the return stack is filled and add those
94  * to our main stack. Then we retry.
95  *
96  * \param n number of packets needed
97  */
98 void PacketPoolWaitForN(int n)
99 {
100  PktPool *my_pool = GetThreadPacketPool();
101 
102  while (1) {
103  PacketPoolWait();
104 
105  /* count packets in our stack */
106  int i = 0;
107  Packet *p, *pp;
108  pp = p = my_pool->head;
109  while (p != NULL) {
110  if (++i == n)
111  return;
112 
113  pp = p;
114  p = p->next;
115  }
116 
117  /* check return stack, return to our pool and retry counting */
118  if (my_pool->return_stack.head != NULL) {
119  SCMutexLock(&my_pool->return_stack.mutex);
120  /* Move all the packets from the locked return stack to the local stack. */
121  if (pp) {
122  pp->next = my_pool->return_stack.head;
123  } else {
124  my_pool->head = my_pool->return_stack.head;
125  }
126  my_pool->return_stack.head = NULL;
127  SC_ATOMIC_RESET(my_pool->return_stack.sync_now);
128  SCMutexUnlock(&my_pool->return_stack.mutex);
129 
130  /* or signal that we need packets and wait */
131  } else {
132  SCMutexLock(&my_pool->return_stack.mutex);
133  SC_ATOMIC_ADD(my_pool->return_stack.sync_now, 1);
134  SCCondWait(&my_pool->return_stack.cond, &my_pool->return_stack.mutex);
135  SCMutexUnlock(&my_pool->return_stack.mutex);
136  }
137  }
138 }
139 
140 /** \brief a initialized packet
141  *
142  * \warning Use *only* at init, not at packet runtime
143  */
144 static void PacketPoolStorePacket(Packet *p)
145 {
146  p->pool = GetThreadPacketPool();
149 }
150 
151 static void PacketPoolGetReturnedPackets(PktPool *pool)
152 {
153  SCMutexLock(&pool->return_stack.mutex);
154  /* Move all the packets from the locked return stack to the local stack. */
155  pool->head = pool->return_stack.head;
156  pool->return_stack.head = NULL;
157  SCMutexUnlock(&pool->return_stack.mutex);
158 }
159 
160 /** \brief Get a new packet from the packet pool
161  *
162  * Only allocates from the thread's local stack, or mallocs new packets.
163  * If the local stack is empty, first move all the return stack packets to
164  * the local stack.
165  * \retval Packet pointer, or NULL on failure.
166  */
168 {
169  PktPool *pool = GetThreadPacketPool();
170 #ifdef DEBUG_VALIDATION
171  BUG_ON(pool->initialized == 0);
172  BUG_ON(pool->destroyed == 1);
173 #endif /* DEBUG_VALIDATION */
174  if (pool->head) {
175  /* Stack is not empty. */
176  Packet *p = pool->head;
177  pool->head = p->next;
178  p->pool = pool;
179  PacketReinit(p);
180  return p;
181  }
182 
183  /* Local Stack is empty, so check the return stack, which requires
184  * locking. */
185  PacketPoolGetReturnedPackets(pool);
186 
187  /* Try to allocate again. Need to check for not empty again, since the
188  * return stack might have been empty too.
189  */
190  if (pool->head) {
191  /* Stack is not empty. */
192  Packet *p = pool->head;
193  pool->head = p->next;
194  p->pool = pool;
195  PacketReinit(p);
196  return p;
197  }
198 
199  /* Failed to allocate a packet, so return NULL. */
200  /* Optionally, could allocate a new packet here. */
201  return NULL;
202 }
203 
204 /** \brief Return packet to Packet pool
205  *
206  */
208 {
209  PktPool *my_pool = GetThreadPacketPool();
210  PktPool *pool = p->pool;
211  if (pool == NULL) {
212  PacketFree(p);
213  return;
214  }
215 
217 
218 #ifdef DEBUG_VALIDATION
219  BUG_ON(pool->initialized == 0);
220  BUG_ON(pool->destroyed == 1);
221  BUG_ON(my_pool->initialized == 0);
222  BUG_ON(my_pool->destroyed == 1);
223 #endif /* DEBUG_VALIDATION */
224 
225  if (pool == my_pool) {
226  /* Push back onto this thread's own stack, so no locking. */
227  p->next = my_pool->head;
228  my_pool->head = p;
229  } else {
230  PktPool *pending_pool = my_pool->pending_pool;
231  if (pending_pool == NULL) {
232  /* No pending packet, so store the current packet. */
233  p->next = NULL;
234  my_pool->pending_pool = pool;
235  my_pool->pending_head = p;
236  my_pool->pending_tail = p;
237  my_pool->pending_count = 1;
238  } else if (pending_pool == pool) {
239  /* Another packet for the pending pool list. */
240  p->next = my_pool->pending_head;
241  my_pool->pending_head = p;
242  my_pool->pending_count++;
243  if (SC_ATOMIC_GET(pool->return_stack.sync_now) || my_pool->pending_count > max_pending_return_packets) {
244  /* Return the entire list of pending packets. */
245  SCMutexLock(&pool->return_stack.mutex);
246  my_pool->pending_tail->next = pool->return_stack.head;
247  pool->return_stack.head = my_pool->pending_head;
248  SC_ATOMIC_RESET(pool->return_stack.sync_now);
249  SCMutexUnlock(&pool->return_stack.mutex);
250  SCCondSignal(&pool->return_stack.cond);
251  /* Clear the list of pending packets to return. */
252  my_pool->pending_pool = NULL;
253  my_pool->pending_head = NULL;
254  my_pool->pending_tail = NULL;
255  my_pool->pending_count = 0;
256  }
257  } else {
258  /* Push onto return stack for this pool */
259  SCMutexLock(&pool->return_stack.mutex);
260  p->next = pool->return_stack.head;
261  pool->return_stack.head = p;
262  SC_ATOMIC_RESET(pool->return_stack.sync_now);
263  SCMutexUnlock(&pool->return_stack.mutex);
264  SCCondSignal(&pool->return_stack.cond);
265  }
266  }
267 }
268 
270 {
271  PktPool *my_pool = GetThreadPacketPool();
272 
273 #ifdef DEBUG_VALIDATION
274  BUG_ON(my_pool->initialized);
275  my_pool->initialized = 1;
276  my_pool->destroyed = 0;
277 #endif /* DEBUG_VALIDATION */
278 
279  SCMutexInit(&my_pool->return_stack.mutex, NULL);
280  SCCondInit(&my_pool->return_stack.cond, NULL);
281  SC_ATOMIC_INIT(my_pool->return_stack.sync_now);
282 }
283 
284 void PacketPoolInit(void)
285 {
286  extern uint16_t max_pending_packets;
287 
288  PktPool *my_pool = GetThreadPacketPool();
289 
290 #ifdef DEBUG_VALIDATION
291  BUG_ON(my_pool->initialized);
292  my_pool->initialized = 1;
293  my_pool->destroyed = 0;
294 #endif /* DEBUG_VALIDATION */
295 
296  SCMutexInit(&my_pool->return_stack.mutex, NULL);
297  SCCondInit(&my_pool->return_stack.cond, NULL);
298  SC_ATOMIC_INIT(my_pool->return_stack.sync_now);
299 
300  /* pre allocate packets */
301  SCLogDebug("preallocating packets... packet size %" PRIuMAX "",
302  (uintmax_t)SIZE_OF_PACKET);
303  int i = 0;
304  for (i = 0; i < max_pending_packets; i++) {
305  Packet *p = PacketGetFromAlloc();
306  if (unlikely(p == NULL)) {
307  FatalError("Fatal error encountered while allocating a packet. Exiting...");
308  }
309  PacketPoolStorePacket(p);
310  }
311 
312  //SCLogInfo("preallocated %"PRIiMAX" packets. Total memory %"PRIuMAX"",
313  // max_pending_packets, (uintmax_t)(max_pending_packets*SIZE_OF_PACKET));
314 }
315 
317 {
318  Packet *p = NULL;
319  PktPool *my_pool = GetThreadPacketPool();
320 
321 #ifdef DEBUG_VALIDATION
322  BUG_ON(my_pool && my_pool->destroyed);
323 #endif /* DEBUG_VALIDATION */
324 
325  if (my_pool && my_pool->pending_pool != NULL) {
326  p = my_pool->pending_head;
327  while (p) {
328  Packet *next_p = p->next;
329  PacketFree(p);
330  p = next_p;
331  my_pool->pending_count--;
332  }
333 #ifdef DEBUG_VALIDATION
334  BUG_ON(my_pool->pending_count);
335 #endif /* DEBUG_VALIDATION */
336  my_pool->pending_pool = NULL;
337  my_pool->pending_head = NULL;
338  my_pool->pending_tail = NULL;
339  }
340 
341  while ((p = PacketPoolGetPacket()) != NULL) {
342  PacketFree(p);
343  }
344 
345 #ifdef DEBUG_VALIDATION
346  my_pool->initialized = 0;
347  my_pool->destroyed = 1;
348 #endif /* DEBUG_VALIDATION */
349 }
350 
352 {
353  return PacketPoolGetPacket();
354 }
355 
357 {
358  bool proot = false;
359 
360  SCEnter();
361  SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, BOOL2STR(p->pool == NULL));
362 
363  if (IS_TUNNEL_PKT(p)) {
364  SCLogDebug("Packet %p is a tunnel packet: %s",
365  p,p->root ? "upper layer" : "tunnel root");
366 
367  /* get a lock to access root packet fields */
369  SCSpinLock(lock);
370 
371  if (IS_TUNNEL_ROOT_PKT(p)) {
372  SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE");
373  CaptureStatsUpdate(t, p);
374 
375  const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p);
376  SCLogDebug("root pkt: outstanding %u", outstanding);
377  if (outstanding == 0) {
378  SCLogDebug("no tunnel packets outstanding, no more tunnel "
379  "packet(s) depending on this root");
380  /* if this packet is the root and there are no
381  * more tunnel packets to consider
382  *
383  * return it to the pool */
384  } else {
385  SCLogDebug("tunnel root Packet %p: outstanding > 0, so "
386  "packets are still depending on this root, setting "
387  "SET_TUNNEL_PKT_VERDICTED", p);
388  /* if this is the root and there are more tunnel
389  * packets, return this to the pool. It's still referenced
390  * by the tunnel packets, and we will return it
391  * when we handle them */
393 
396  SCReturn;
397  }
398  } else {
399  SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt");
400 
402  const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p);
403  SCLogDebug("tunnel pkt: outstanding %u", outstanding);
404  /* all tunnel packets are processed except us. Root already
405  * processed. So return tunnel pkt and root packet to the
406  * pool. */
407  if (outstanding == 0 &&
409  {
410  SCLogDebug("root verdicted == true && no outstanding");
411 
412  /* handle freeing the root as well*/
413  SCLogDebug("setting proot = 1 for root pkt, p->root %p "
414  "(tunnel packet %p)", p->root, p);
415  proot = true;
416 
417  /* fall through */
418 
419  } else {
420  /* root not ready yet, or not the last tunnel packet,
421  * so get rid of the tunnel pkt only */
422 
423  SCLogDebug("NOT IS_TUNNEL_PKT_VERDICTED (%s) || "
424  "outstanding > 0 (%u)",
425  (p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) ? "true" : "false",
426  outstanding);
427 
428  /* fall through */
429  }
430  }
432 
433  SCLogDebug("tunnel stuff done, move on (proot %d)", proot);
434 
435  } else {
436  CaptureStatsUpdate(t, p);
437  }
438 
439  SCLogDebug("[packet %p][%s] %s", p,
440  IS_TUNNEL_PKT(p) ? IS_TUNNEL_ROOT_PKT(p) ? "tunnel::root" : "tunnel::leaf"
441  : "no tunnel",
442  (p->action & ACTION_DROP) ? "DROP" : "no drop");
443 
444  /* we're done with the tunnel root now as well */
445  if (proot == true) {
446  SCLogDebug("getting rid of root pkt... alloc'd %s", BOOL2STR(p->root->pool == NULL));
447 
449  p->root->ReleasePacket(p->root);
450  p->root = NULL;
451  }
452 
454 
456  p->ReleasePacket(p);
457 
458  SCReturn;
459 }
460 
461 /**
462  * \brief Release all the packets in the queue back to the packetpool. Mainly
463  * used by threads that have failed, and wants to return the packets back
464  * to the packetpool.
465  *
466  * \param pq Pointer to the packetqueue from which the packets have to be
467  * returned back to the packetpool
468  *
469  * \warning this function assumes that the pq does not use locking
470  */
472 {
473  Packet *p = NULL;
474 
475  if (pq == NULL)
476  return;
477 
478  while ((p = PacketDequeue(pq)) != NULL) {
479  DEBUG_VALIDATE_BUG_ON(p->flow != NULL);
480  TmqhOutputPacketpool(NULL, p);
481  }
482 
483  return;
484 }
485 
486 /** number of packets to keep reserved when calculating the pending
487  * return packets count. This assumes we need at max 10 packets in one
488  * PacketPoolWaitForN call. The actual number is 9 now, so this has a
489  * bit of margin. */
490 #define RESERVED_PACKETS 10
491 
492 /**
493  * \brief Set the max_pending_return_packets value
494  *
495  * Set it to the max pending packets value, divided by the number
496  * of lister threads. Normally, in autofp these are the stream/detect/log
497  * worker threads.
498  *
499  * The max_pending_return_packets value needs to stay below the packet
500  * pool size of the 'producers' (normally pkt capture threads but also
501  * flow timeout injection ) to avoid a deadlock where all the 'workers'
502  * keep packets in their return pools, while the capture thread can't
503  * continue because its pool is empty.
504  */
506 {
507  extern uint16_t max_pending_packets;
508  uint16_t pending_packets = max_pending_packets;
509  if (pending_packets < RESERVED_PACKETS) {
510  FatalError("'max-pending-packets' setting "
511  "must be at least %d",
513  }
515  if (threads == 0)
516  return;
517 
518  uint32_t packets = (pending_packets / threads) - 1;
519  if (packets < max_pending_return_packets)
520  max_pending_return_packets = packets;
521 
522  /* make sure to have a margin in the return logic */
523  if (max_pending_return_packets >= RESERVED_PACKETS)
524  max_pending_return_packets -= RESERVED_PACKETS;
525 
526  SCLogDebug("detect threads %u, max packets %u, max_pending_return_packets %u",
527  threads, packets, max_pending_return_packets);
528 }
tm-threads.h
PktPool_::pending_tail
Packet * pending_tail
Definition: tmqh-packetpool.h:51
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:315
Packet_::persistent
struct Packet_::@40 persistent
PacketPoolReturnPacket
void PacketPoolReturnPacket(Packet *p)
Return packet to Packet pool.
Definition: tmqh-packetpool.c:207
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
PktPool_
Definition: tmqh-packetpool.h:39
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
RESERVED_PACKETS
#define RESERVED_PACKETS
Definition: tmqh-packetpool.c:490
TM_FLAG_DETECT_TM
#define TM_FLAG_DETECT_TM
Definition: tm-modules.h:34
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:49
action-globals.h
Packet_::action
uint8_t action
Definition: decode.h:581
threads.h
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:333
Tmqh_::OutHandler
void(* OutHandler)(ThreadVars *, Packet *)
Definition: tm-queuehandlers.h:40
Packet_::pool
struct PktPool_ * pool
Definition: decode.h:639
PacketReleaseRefs
void PacketReleaseRefs(Packet *p)
Definition: packet.c:70
SCCondInit
#define SCCondInit
Definition: threads-debug.h:138
IS_TUNNEL_ROOT_PKT
#define IS_TUNNEL_ROOT_PKT(p)
Definition: decode.h:797
TmThreadCountThreadsByTmmFlags
uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
returns a count of all the threads that match the flag
Definition: tm-threads.c:2002
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
tm-modules.h
SCSpinLock
#define SCSpinLock
Definition: threads-debug.h:235
PktPool_::pending_count
uint32_t pending_count
Definition: tmqh-packetpool.h:52
PacketPoolPostRunmodes
void PacketPoolPostRunmodes(void)
Set the max_pending_return_packets value.
Definition: tmqh-packetpool.c:505
MAX_PENDING_RETURN_PACKETS
#define MAX_PENDING_RETURN_PACKETS
Definition: tmqh-packetpool.c:39
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:356
tmqh-packetpool.h
thread_pkt_pool
thread_local PktPool thread_pkt_pool
Definition: tmqh-packetpool.c:42
PktPool_::pending_head
Packet * pending_head
Definition: tmqh-packetpool.h:50
TmqhReleasePacketsToPacketPool
void TmqhReleasePacketsToPacketPool(PacketQueue *pq)
Release all the packets in the queue back to the packetpool. Mainly used by threads that have failed,...
Definition: tmqh-packetpool.c:471
PacketPoolInit
void PacketPoolInit(void)
Definition: tmqh-packetpool.c:284
Tmqh_::InHandler
Packet *(* InHandler)(ThreadVars *)
Definition: tm-queuehandlers.h:38
lock
HRLOCK_TYPE lock
Definition: host.h:0
decode.h
TUNNEL_PKT_TPR
#define TUNNEL_PKT_TPR(p)
Definition: decode.h:792
PacketReinit
void PacketReinit(Packet *p)
Recycle a packet structure for reuse.
Definition: packet.c:80
SCCondWait
#define SCCondWait
Definition: threads-debug.h:141
Packet_::tunnel_lock
SCSpinlock tunnel_lock
Definition: decode.h:652
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
BOOL2STR
#define BOOL2STR(b)
Definition: util-debug.h:527
CaptureStatsUpdate
void CaptureStatsUpdate(ThreadVars *tv, const Packet *p)
Definition: decode.c:879
IS_TUNNEL_PKT_VERDICTED
#define IS_TUNNEL_PKT_VERDICTED(p)
Definition: decode.h:799
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
PacketPoolWaitForN
void PacketPoolWaitForN(int n)
Wait until we have the requested amount of packets in the pool.
Definition: tmqh-packetpool.c:98
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:134
SCSpinUnlock
#define SCSpinUnlock
Definition: threads-debug.h:237
TmqhInputPacketpool
Packet * TmqhInputPacketpool(ThreadVars *tv)
Definition: tmqh-packetpool.c:351
SIZE_OF_PACKET
#define SIZE_OF_PACKET
Definition: decode.h:664
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:295
util-profiling.h
PacketPoolWait
void PacketPoolWait(void)
Definition: tmqh-packetpool.c:69
SCReturn
#define SCReturn
Definition: util-debug.h:273
Packet_
Definition: decode.h:430
Tmqh_::name
const char * name
Definition: tm-queuehandlers.h:37
IS_TUNNEL_PKT
#define IS_TUNNEL_PKT(p)
Definition: decode.h:794
max_pending_packets
uint16_t max_pending_packets
Definition: suricata.c:186
SET_TUNNEL_PKT_VERDICTED
#define SET_TUNNEL_PKT_VERDICTED(p)
Definition: decode.h:800
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
PktPool_::return_stack
PktPoolLockedStack return_stack
Definition: tmqh-packetpool.h:66
tm-queuehandlers.h
TmqhPacketpoolRegister
void TmqhPacketpoolRegister(void)
TmqhPacketpoolRegister \initonly.
Definition: tmqh-packetpool.c:53
Packet_::ReleasePacket
void(* ReleasePacket)(struct Packet_ *)
Definition: decode.h:519
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:139
Packet_::flow
struct Flow_ * flow
Definition: decode.h:469
suricata-common.h
packet.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
FatalError
#define FatalError(...)
Definition: util-debug.h:502
tmqh_table
Tmqh tmqh_table[TMQH_SIZE]
Definition: tm-queuehandlers.c:37
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
SC_ATOMIC_RESET
#define SC_ATOMIC_RESET(name)
wrapper for reinitializing an atomic variable.
Definition: util-atomic.h:324
PacketDequeue
Packet * PacketDequeue(PacketQueue *q)
Definition: packet-queue.c:216
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
TUNNEL_PKT_RTV
#define TUNNEL_PKT_RTV(p)
Definition: decode.h:791
Packet_::next
struct Packet_ * next
Definition: decode.h:607
Packet_::root
struct Packet_ * root
Definition: decode.h:622
TUNNEL_INCR_PKT_RTV_NOLOCK
#define TUNNEL_INCR_PKT_RTV_NOLOCK(p)
Definition: decode.h:779
PACKET_PROFILING_END
#define PACKET_PROFILING_END(p)
Definition: util-profiling.h:86
PacketPoolGetPacket
Packet * PacketPoolGetPacket(void)
Get a new packet from the packet pool.
Definition: tmqh-packetpool.c:167
SCSpinlock
#define SCSpinlock
Definition: threads-debug.h:234
PacketPoolInitEmpty
void PacketPoolInitEmpty(void)
Definition: tmqh-packetpool.c:269
cc_barrier
#define cc_barrier()
Definition: util-optimize.h:43
PktPool_::pending_pool
struct PktPool_ * pending_pool
Definition: tmqh-packetpool.h:49
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:376
PacketPoolDestroy
void PacketPoolDestroy(void)
Definition: tmqh-packetpool.c:316
PktPool_::head
Packet * head
Definition: tmqh-packetpool.h:43
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:104
TMQH_PACKETPOOL
@ TMQH_PACKETPOOL
Definition: tm-queuehandlers.h:30