]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
af-packet: Implement zero copy
authorEric Leblond <eric@regit.org>
Thu, 16 Feb 2012 16:08:54 +0000 (17:08 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 23 Feb 2012 15:29:45 +0000 (16:29 +0100)
This patch adds support for zero copy to AF_PACKET running mode.
This requires to use the 'worker' mode which is the only one where
the threading architecture is simple enough to permit this without
heavy modification.

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

index 13a75afef2baf9ea11f6b660ff413c9b0fd1b8d4..237575bb33b6c5fcdda466522516f7c702b7c094 100644 (file)
@@ -895,6 +895,7 @@ void AddressDebugPrint(Address *);
 #define PKT_TUNNEL_VERDICTED            0x2000
 
 #define PKT_IGNORE_CHECKSUM             0x4000    /**< Packet checksum is not computed (TX packet for example) */
+#define PKT_ZERO_COPY                   0x8000    /**< Packet comes from zero copy (ext_pkt must not be freed) */
 
 /** \brief return 1 if the packet is a pseudo packet */
 #define PKT_IS_PSEUDOPKT(p) ((p)->flags & PKT_PSEUDO_STREAM_END)
index 764e3ba38d3ada57f0a02b6d4762a50169645a05..9378fe0a8369c12b77a0c099e5b477ad75eece6b 100644 (file)
@@ -65,6 +65,7 @@
 #include "util-checksum.h"
 #include "tmqh-packetpool.h"
 #include "source-af-packet.h"
+#include "runmodes.h"
 
 #ifdef HAVE_AF_PACKET
 #include <sys/ioctl.h>
@@ -390,11 +391,16 @@ int AFPReadFromRing(AFPThreadVars *ptv)
     }
 
     p->datalink = ptv->datalink;
-    /* FIXME switch to no copy */
-    SET_PKT_LEN(p, h.h2->tp_len);
-    if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, GET_PKT_LEN(p)) == -1) {
-        TmqhOutputPacketpool(ptv->tv, p);
-        SCReturnInt(AFP_FAILURE);
+    if (ptv->flags & AFP_ZERO_COPY) {
+        if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_len) == -1) {
+            TmqhOutputPacketpool(ptv->tv, p);
+            SCReturnInt(AFP_FAILURE);
+        }
+    } else {
+        if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_len) == -1) {
+            TmqhOutputPacketpool(ptv->tv, p);
+            SCReturnInt(AFP_FAILURE);
+        }
     }
     /* Timestamp */
     p->ts.tv_sec = h.h2->tp_sec;
@@ -419,18 +425,21 @@ int AFPReadFromRing(AFPThreadVars *ptv)
                 p->flags |= PKT_IGNORE_CHECKSUM;
         }
     }
-    /* tell kernel it can use the buffer */
-    h.h2->tp_status = TP_STATUS_KERNEL;
-    if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
-        ptv->frame_offset = 0;
-    }
-
 
     if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
+        h.h2->tp_status = TP_STATUS_KERNEL;
+        if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
+            ptv->frame_offset = 0;
+        }
         TmqhOutputPacketpool(ptv->tv, p);
         SCReturnInt(AFP_FAILURE);
     }
 
+    h.h2->tp_status = TP_STATUS_KERNEL;
+    if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
+        ptv->frame_offset = 0;
+    }
+
     SCReturnInt(AFP_READ_OK);
 }
 
@@ -890,6 +899,13 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, void *initdata, void **data) {
 #endif
     ptv->flags = afpconfig->flags;
 
+    char *active_runmode = RunmodeGetActive();
+
+    if (active_runmode && !strcmp("workers", active_runmode)) {
+        ptv->flags |= AFP_ZERO_COPY;
+        SCLogInfo("Enabling zero copy mode");
+    }
+
     r = AFPCreateSocket(ptv, ptv->iface, 1);
     if (r < 0) {
         SCLogError(SC_ERR_AFP_CREATE, "Couldn't init AF_PACKET socket");
index e5c7f7d5c25b74190e4cace2cb3661c83123fab9..487ed23f453ea281586348f5276ebba620c133a9 100644 (file)
@@ -40,6 +40,7 @@
 
 /* value for flags */
 #define AFP_RING_MODE (1<<0)
+#define AFP_ZERO_COPY (1<<1)
 
 #define AFP_FILE_MAX_PKTS 256
 #define AFP_IFACE_NAME_LENGTH 48
index 316fad15b008c9ffa2ff0166823f270a5e10123e..444d70a5852d3d3fcd60befbbcd130b662175b95 100644 (file)
@@ -229,7 +229,9 @@ void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
 
     /* if p uses extended data, free them */
     if (p->ext_pkt) {
-        SCFree(p->ext_pkt);
+        if (!(p->flags & PKT_ZERO_COPY)) {
+            SCFree(p->ext_pkt);
+        }
         p->ext_pkt = NULL;
     }