]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
af-packet: add optional emergency mode
authorEric Leblond <eric@regit.org>
Fri, 27 Jul 2012 09:48:10 +0000 (11:48 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 3 Sep 2012 13:27:38 +0000 (15:27 +0200)
Flush all waiting packets to be in sync with kernel when drop
occurs. This mode can be activated by setting use-emergency-flush
to yes in the interface configuration.

src/runmode-af-packet.c
src/source-af-packet.c
src/source-af-packet.h
suricata.yaml.in

index 0a92be406d991287f3f33ede94e85673a74349eb..aaceb55ee82f22d64b182776873f7c0ffdb235c8 100644 (file)
@@ -190,6 +190,13 @@ void *ParseAFPConfig(const char *iface)
                 aconf->iface);
         aconf->flags |= AFP_RING_MODE;
     }
+    (void)ConfGetChildValueBool(if_root, "use-emergency-flush", (int *)&boolval);
+    if (boolval) {
+        SCLogInfo("Enabling ring emergency flush on iface %s",
+                aconf->iface);
+        aconf->flags |= AFP_EMERGENCY_MODE;
+    }
+
 
     aconf->copy_mode = AFP_COPY_MODE_NONE;
     if (ConfGetChildValue(if_root, "copy-mode", &copymodestr) == 1) {
index a128243262c2046ffeae518156a73aa17d4b7dfd..ec838cbe2eec5fbbda68f9ab28d058da38e2c455 100644 (file)
@@ -129,6 +129,7 @@ enum {
     AFP_READ_OK,
     AFP_READ_FAILURE,
     AFP_FAILURE,
+    AFP_KERNEL_DROP,
 };
 
 union thdr {
@@ -610,6 +611,7 @@ int AFPReadFromRing(AFPThreadVars *ptv)
     Packet *p = NULL;
     union thdr h;
     struct sockaddr_ll *from;
+    uint8_t emergency_flush = 0;
 
     /* Loop till we have packets available */
     while (1) {
@@ -620,7 +622,15 @@ int AFPReadFromRing(AFPThreadVars *ptv)
         }
 
         if (h.h2->tp_status == TP_STATUS_KERNEL) {
-            SCReturnInt(AFP_READ_OK);
+            if ((emergency_flush) && (ptv->flags & AFP_EMERGENCY_MODE)) {
+                SCReturnInt(AFP_KERNEL_DROP);
+            } else {
+                SCReturnInt(AFP_READ_OK);
+            }
+        }
+        if ((ptv->flags & AFP_EMERGENCY_MODE) && (emergency_flush == 1)) {
+            h.h2->tp_status = TP_STATUS_KERNEL;
+            goto next_frame;
         }
 
         p = PacketGetFromQueueOrAlloc();
@@ -704,6 +714,9 @@ int AFPReadFromRing(AFPThreadVars *ptv)
             if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
                 p->flags |= PKT_IGNORE_CHECKSUM;
             }
+            if (h.h2->tp_status & TP_STATUS_LOSING) {
+                emergency_flush = 1;
+            }
         }
 
         if (TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p) != TM_ECODE_OK) {
@@ -715,7 +728,11 @@ int AFPReadFromRing(AFPThreadVars *ptv)
             SCReturnInt(AFP_FAILURE);
         }
 
-        h.h2->tp_status = TP_STATUS_KERNEL;
+        /* release frame if not in zero copy mode */
+        if (!(ptv->flags &  AFP_ZERO_COPY)) {
+            h.h2->tp_status = TP_STATUS_KERNEL;
+        }
+next_frame:
         if (++ptv->frame_offset >= ptv->req.tp_frame_nr) {
             ptv->frame_offset = 0;
         }
@@ -838,6 +855,9 @@ TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
                 case AFP_READ_OK:
                     AFPDumpCounters(ptv, 0);
                     break;
+                case AFP_KERNEL_DROP:
+                    AFPDumpCounters(ptv, 1);
+                    break;
             }
         } else if ((r < 0) && (errno != EINTR)) {
             SCLogError(SC_ERR_AFP_READ, "Error reading data from socket: (%d" PRIu32 ") %s",
index d9e9a759a68e48d92fa38d07530813ca0599f18e..263b1d9105add62b732b740be5c367ffcf8062f2 100644 (file)
@@ -42,6 +42,7 @@
 #define AFP_RING_MODE (1<<0)
 #define AFP_ZERO_COPY (1<<1)
 #define AFP_SOCK_PROTECT (1<<2)
+#define AFP_EMERGENCY_MODE (1<<3)
 
 #define AFP_COPY_MODE_NONE  0
 #define AFP_COPY_MODE_TAP   1
index 224bd349aa763e0a39d8801fecbfed3b07fd9ae8..1cff85e228c513cc91786632c4ca92eadb613759 100644 (file)
@@ -236,6 +236,9 @@ af-packet:
     # intensive single-flow you could want to set the ring-size independantly of the number
     # of threads:
     #ring-size: 2048
+    # On busy system, this could help to set it to yes to recover from a packet drop
+    # phase. This will result in some packets (at max a ring flush) being non treated.
+    #use-emergency-flush: yes
     # recv buffer size, increase value could improve performance
     # buffer-size: 32768
     # Set to yes to disable promiscuous mode