From: Eric Leblond Date: Fri, 15 Jun 2012 15:18:57 +0000 (+0200) Subject: capture: add data release mechanism X-Git-Tag: suricata-1.4beta1~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2011a3f87e433b0c8b72ea2b8b2b10d6ed8485e3;p=thirdparty%2Fsuricata.git 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. --- diff --git a/src/decode.h b/src/decode.h index a0127f5f3e..4814afc586 100644 --- a/src/decode.h +++ b/src/decode.h @@ -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; diff --git a/src/source-af-packet.c b/src/source-af-packet.c index 82e5c345ee..6fa02c5983 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -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"); diff --git a/src/source-af-packet.h b/src/source-af-packet.h index 02b1d63a2f..97dc2c29c7 100644 --- a/src/source-af-packet.h +++ b/src/source-af-packet.h @@ -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); diff --git a/src/tmqh-packetpool.c b/src/tmqh-packetpool.c index 1e5a5cd136..1844f7cc12 100644 --- a/src/tmqh-packetpool.c +++ b/src/tmqh-packetpool.c @@ -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 */