capture: add data release mechanism

This patch adds a data release mechanism. If the capture module
has a call to indicate that userland has finished with the data,
it is possible to use this system. The data will then be released
when the treatment of the packet is finished.

To do so the Packet structure has been modified:
+    TmEcode (*ReleaseData)(ThreadVars *, struct Packet_ *);
If ReleaseData is null, the function is called when the treatment
of the Packet is finished.
Thus it is sufficient for the capture module to code a function
wrapping the data release mechanism and to assign it to ReleaseData
field.

This patch also includes an implementation of this mechanism for
AF_PACKET.
pull/48/merge
Eric Leblond 13 years ago committed by Victor Julien
parent 8879df8004
commit 2011a3f87e

@ -42,6 +42,7 @@ typedef enum {
#include "source-nfq.h"
#include "source-ipfw.h"
#include "source-pcap.h"
#include "source-af-packet.h"
#include "action-globals.h"
@ -370,6 +371,9 @@ typedef struct Packet_
#ifdef IPFW
IPFWPacketVars ipfw_v;
#endif /* IPFW */
#ifdef AF_PACKET
AFPPacketVars afp_v;
#endif
/** libpcap vars: shared by Pcap Live mode and Pcap File mode */
PcapPacketVars pcap_v;
@ -385,6 +389,9 @@ typedef struct Packet_
int debuglog_flowbits_names_len;
const char **debuglog_flowbits_names;
/** The release function for packet data */
TmEcode (*ReleaseData)(ThreadVars *, struct Packet_ *);
/* pkt vars */
PktVar *pktvar;

@ -368,6 +368,17 @@ int AFPRead(AFPThreadVars *ptv)
SCReturnInt(AFP_READ_OK);
}
TmEcode AFPReleaseDataFromRing(ThreadVars *t, Packet *p)
{
if (p->afp_v.relptr) {
union thdr h;
h.raw = p->afp_v.relptr;
h.h2->tp_status = TP_STATUS_KERNEL;
return TM_ECODE_OK;
}
return TM_ECODE_FAILED;
}
/**
* \brief AF packet read function for ring
*
@ -388,6 +399,11 @@ int AFPReadFromRing(AFPThreadVars *ptv)
h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
if (h.raw == NULL) {
SCReturnInt(AFP_FAILURE);
} else {
if (ptv->flags & AFP_RING_MODE) {
p->afp_v.relptr = h.raw;
p->ReleaseData = AFPReleaseDataFromRing;
}
}
if (h.h2->tp_status == TP_STATUS_KERNEL) {
SCReturnInt(AFP_READ_OK);
@ -1013,6 +1029,13 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
SCLogInfo("Enabling zero copy mode");
}
/* If we are in RING mode, then we can use ZERO copy
* by using the data release mechanism */
if (ptv->flags & AFP_RING_MODE) {
ptv->flags |= AFP_ZERO_COPY;
SCLogInfo("Enabling zero copy mode by using data release call");
}
r = AFPCreateSocket(ptv, ptv->iface, 1);
if (r < 0) {
SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");

@ -67,6 +67,13 @@ typedef struct AFPIfaceConfig_
void (*DerefFunc)(void *);
} AFPIfaceConfig;
/* per packet AF_PACKET vars */
typedef struct AFPPacketVars_
{
void *relptr;
} AFPPacketVars;
void TmModuleReceiveAFPRegister (void);
void TmModuleDecodeAFPRegister (void);

@ -250,8 +250,16 @@ void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
FlowDecrUsecnt(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) {
SCFree(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) {
@ -262,6 +270,13 @@ void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
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");
}
}
/* if p uses extended data, free them */

Loading…
Cancel
Save