]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
capture: add data release mechanism
authorEric Leblond <eric@regit.org>
Fri, 15 Jun 2012 15:18:57 +0000 (17:18 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 3 Sep 2012 13:27:38 +0000 (15:27 +0200)
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.

src/decode.h
src/source-af-packet.c
src/source-af-packet.h
src/tmqh-packetpool.c

index a0127f5f3eccc048943cdb8ce6755b9ddf14a4f7..4814afc5867da5a868eee4b869c9e6977fe1f406 100644 (file)
@@ -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;
 
index 82e5c345eeb12b94698aa6e42b2cc657998254df..6fa02c59838e7af017a64d6584a2bc78084bd115 100644 (file)
@@ -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");
index 02b1d63a2f3f6e6f4737af96385c7d71364f88e2..97dc2c29c731a367835f84b2e83f846856bd6e14 100644 (file)
@@ -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);
 
index 1e5a5cd1368dc6404dce27112d872bdb1eeb8e8a..1844f7cc12b6f36a93f15eafce3e08b15f135b66 100644 (file)
@@ -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 */