This commit allows handling Packets allocated by different methods.
The ReleaseData function pointer in the Packet structure is replaced
with ReleasePacket function pointer, which is then always called to
release the memory associated with a Packet.
Currently, the only usage of ReleaseData is in AF Packet. Previously
ReleaseData was only called when it was not NULL. To implement the
same functionality as before in AF Packet, a new function is defined
in AF Packet to first call the AFP specific ReleaseData function and
then releases the Packet structure.
Three new general functions are defined for releasing packets in the
default case:
1) PacketFree() - To release a packet alloced with SCMalloc()
2) PacketPoolReturnPacket() - For packets allocated from the Packet Pool.
Calls RECYCLE_PACKET(p)
3) PacketFreeOrRelease() - Calls PacketFree() or PacketPoolReturnPacket()
based on the PKT_ALLOC flag.
Having these functions removes the need to check the PKT_ALLOC flag
when releasing a packet in most cases, since the ReleasePacket
function encodes how the Packet was allocated. The PKT_ALLOC flag is
still set and is needed when AF Packet releases a packet, since it
replaces the ReleasePacket function pointer with its own function and
then calls PacketFreeOfRelease(), which uses the PKT_ALLOC flag.
-/* Copyright (C) 2007-2012 Open Information Security Foundation
+/* Copyright (C) 2007-2013 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
#include "util-print.h"
#include "tmqh-packetpool.h"
#include "util-profiling.h"
+#include "pkt-var.h"
void DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,
uint8_t *pkt, uint16_t len, PacketQueue *pq, uint8_t proto)
}
}
+/**
+ * \brief Return a malloced packet.
+ */
+void PacketFree(Packet *p)
+{
+ PACKET_CLEANUP(p);
+ SCFree(p);
+}
+
/**
* \brief Get a malloced packet.
*
memset(p, 0, SIZE_OF_PACKET);
PACKET_INITIALIZE(p);
+ p->ReleasePacket = PacketFree;
p->flags |= PKT_ALLOC;
SCLogDebug("allocated a new packet only using alloc...");
return p;
}
+/**
+ * \brief Return a packet to where it was allocated.
+ */
+void PacketFreeOrRelease(Packet *p)
+{
+ if (p->flags & PKT_ALLOC)
+ PacketFree(p);
+ else
+ PacketPoolReturnPacket(p);
+}
+
/**
* \brief Get a packet. We try to get a packet from the packetpool first, but
* if that is empty we alloc a packet that is free'd again after
return PacketCopyDataOffset(p, 0, pktdata, pktlen);
}
-
-
/**
* \brief Setup a pseudo packet (tunnel)
*
*
* \retval p the pseudo packet or NULL if out of memory
*/
-Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto) {
+Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto)
+{
SCEnter();
/* get us a packet */
*
* \todo IPv6
*/
-void AddressDebugPrint(Address *a) {
+void AddressDebugPrint(Address *a)
+{
if (a == NULL)
return;
}
/** \brief Alloc and setup DecodeThreadVars */
-DecodeThreadVars *DecodeThreadVarsAlloc() {
+DecodeThreadVars *DecodeThreadVarsAlloc()
+{
DecodeThreadVars *dtv = NULL;
return dtv;
}
-
/**
* \brief Set data for Packet and set length when zeo copy is used
*
return 0;
}
-const char *PktSrcToString(enum PktSrcEnum pkt_src) {
+const char *PktSrcToString(enum PktSrcEnum pkt_src)
+{
char *pkt_src_str = "<unknown>";
switch (pkt_src) {
case PKT_SRC_WIRE:
int debuglog_flowbits_names_len;
const char **debuglog_flowbits_names;
- /** The release function for packet data */
- TmEcode (*ReleaseData)(ThreadVars *, struct Packet_ *);
+ /** The release function for packet structure and data */
+ void (*ReleasePacket)(struct Packet_ *);
/* pkt vars */
PktVar *pktvar;
(p)->prev = NULL; \
(p)->root = NULL; \
(p)->livedev = NULL; \
- (p)->ReleaseData = NULL; \
PACKET_RESET_CHECKSUMS((p)); \
PACKET_PROFILING_RESET((p)); \
} while (0)
Packet *PacketDefragPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto);
Packet *PacketGetFromQueueOrAlloc(void);
Packet *PacketGetFromAlloc(void);
+void PacketFree(Packet *p);
+void PacketFreeOrRelease(Packet *p);
int PacketCopyData(Packet *p, uint8_t *pktdata, int pktlen);
int PacketSetData(Packet *p, uint8_t *pktdata, int pktlen);
int PacketCopyDataOffset(Packet *p, int offset, uint8_t *data, int datalen);
-/* Copyright (C) 2011,2012 Open Information Security Foundation
+/* Copyright (C) 2011-2013 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
return TM_ECODE_OK;
}
-TmEcode AFPReleaseDataFromRing(ThreadVars *t, Packet *p)
+void AFPReleaseDataFromRing(Packet *p)
{
- int ret = TM_ECODE_OK;
/* Need to be in copy mode and need to detect early release
where Ethernet header could not be set (and pseudo packet) */
if ((p->afp_v.copy_mode != AFP_COPY_MODE_NONE) && !PKT_IS_PSEUDOPKT(p)) {
- ret = AFPWritePacket(p);
+ AFPWritePacket(p);
}
if (AFPDerefSocket(p->afp_v.mpeer) == 0)
cleanup:
AFPV_CLEANUP(&p->afp_v);
- return ret;
+}
+
+void AFPReleasePacket(Packet *p)
+{
+ AFPReleaseDataFromRing(p);
+ PacketFreeOrRelease(p);
}
/**
SCReturnInt(AFP_FAILURE);
} else {
p->afp_v.relptr = h.raw;
- p->ReleaseData = AFPReleaseDataFromRing;
+ p->ReleasePacket = AFPReleasePacket;
p->afp_v.mpeer = ptv->mpeer;
AFPRefSocket(ptv->mpeer);
/* Clear the PKT_ALLOC flag, since that indicates to push back
* onto the ring buffer. */
p->flags &= ~PKT_ALLOC;
+ p->ReleasePacket = PacketPoolReturnPacket;
+ PacketPoolReturnPacket(p);
- RingBufferMrMwPut(ringbuffer, (void *)p);
SCLogDebug("buffersize %u", RingBufferSize(ringbuffer));
}
return p;
}
+/** \brief Return packet to Packet pool
+ *
+ */
+void PacketPoolReturnPacket(Packet *p)
+{
+ PACKET_RECYCLE(p);
+ RingBufferMrMwPut(ringbuffer, (void *)p);
+}
+
void PacketPoolInit(intmax_t max_pending_packets) {
/* pre allocate packets */
SCLogDebug("preallocating packets... packet size %" PRIuMAX "", (uintmax_t)SIZE_OF_PACKET);
FlowDeReference(&p->root->flow);
/* if p->root uses extended data, free them */
- if (p->root->ReleaseData) {
- if (p->root->ReleaseData(t, p->root) == TM_ECODE_FAILED) {
- SCLogWarning(SC_ERR_INVALID_ACTION,
- "Unable to release packet data");
- }
- }
if (p->root->ext_pkt) {
if (!(p->root->flags & PKT_ZERO_COPY)) {
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->ReleaseData) {
- if (p->ReleaseData(t, p) == TM_ECODE_FAILED) {
- SCLogWarning(SC_ERR_INVALID_ACTION, "Unable to release packet data");
- }
+ p->root->ReleasePacket(p->root);
+ p->root = NULL;
}
/* if p uses extended data, free them */
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);
- }
+ p->ReleasePacket(p);
SCReturn;
}
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2013 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
uint16_t PacketPoolSize(void);
void PacketPoolStorePacket(Packet *);
void PacketPoolWait(void);
-
+void PacketPoolReturnPacket(Packet *p);
void PacketPoolInit(intmax_t max_pending_packets);
void PacketPoolDestroy(void);