]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
af-packet: loop on ring if there is data to read.
authorEric Leblond <eric@regit.org>
Fri, 27 Jul 2012 09:29:37 +0000 (11:29 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 6 Aug 2012 14:11:19 +0000 (16:11 +0200)
This patch should bring some improvements by looping on the
ring when there is some data available instead of getting back
to the poll. It also fix recovery in case of drops on the ring
because the poll command will not return correctly in this case.

src/source-af-packet.c

index 20062ee35e688cc27fc49cde277d802acce982e2..c201876959cf076d651c3615171be483285d3c11 100644 (file)
@@ -400,85 +400,88 @@ int AFPReadFromRing(AFPThreadVars *ptv)
     Packet *p = NULL;
     union thdr h;
 
-    /* Read packet from ring */
-    h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
-    if (h.raw == NULL) {
-        SCReturnInt(AFP_FAILURE);
-    }
-    if (h.h2->tp_status == 0) {
-        SCReturnInt(AFP_READ_OK);
-    }
-
-    p = PacketGetFromQueueOrAlloc();
-    if (p == NULL) {
-        SCReturnInt(AFP_FAILURE);
-    }
-
-    ptv->pkts++;
-    ptv->bytes += h.h2->tp_len;
-    (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
-    p->livedev = ptv->livedev;
-
-    /* add forged header */
-    if (ptv->cooked) {
-        SllHdr * hdrp = (SllHdr *)ptv->data;
-        struct sockaddr_ll *from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
-        /* XXX this is minimalist, but this seems enough */
-        hdrp->sll_protocol = from->sll_protocol;
-    }
-
-    p->datalink = ptv->datalink;
-    if (h.h2->tp_len > h.h2->tp_snaplen) {
-        SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
-                   h.h2->tp_len, h.h2->tp_snaplen);
-    }
-    if (ptv->flags & AFP_ZERO_COPY) {
-        if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
-            TmqhOutputPacketpool(ptv->tv, p);
+    /* Loop till we have packets available */
+    while (1) {
+        /* Read packet from ring */
+        h.raw = (((union thdr **)ptv->frame_buf)[ptv->frame_offset]);
+        if (h.raw == NULL) {
             SCReturnInt(AFP_FAILURE);
         }
-    } else {
-        if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
-            TmqhOutputPacketpool(ptv->tv, p);
+        if (h.h2->tp_status == TP_STATUS_KERNEL) {
+            SCReturnInt(AFP_READ_OK);
+        }
+
+        p = PacketGetFromQueueOrAlloc();
+        if (p == NULL) {
             SCReturnInt(AFP_FAILURE);
         }
-    }
-    /* Timestamp */
-    p->ts.tv_sec = h.h2->tp_sec;
-    p->ts.tv_usec = h.h2->tp_nsec/1000;
-    SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
-               GET_PKT_LEN(p), p, GET_PKT_DATA(p));
 
-    /* We only check for checksum disable */
-    if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
-        p->flags |= PKT_IGNORE_CHECKSUM;
-    } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
-        if (ptv->livedev->ignore_checksum) {
-            p->flags |= PKT_IGNORE_CHECKSUM;
-        } else if (ChecksumAutoModeCheck(ptv->pkts,
-                    SC_ATOMIC_GET(ptv->livedev->pkts),
-                    SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
-            ptv->livedev->ignore_checksum = 1;
-            p->flags |= PKT_IGNORE_CHECKSUM;
+        ptv->pkts++;
+        ptv->bytes += h.h2->tp_len;
+        (void) SC_ATOMIC_ADD(ptv->livedev->pkts, 1);
+        p->livedev = ptv->livedev;
+
+        /* add forged header */
+        if (ptv->cooked) {
+            SllHdr * hdrp = (SllHdr *)ptv->data;
+            struct sockaddr_ll *from = (void *)h.raw + TPACKET_ALIGN(ptv->tp_hdrlen);
+            /* XXX this is minimalist, but this seems enough */
+            hdrp->sll_protocol = from->sll_protocol;
         }
-    } else {
-        if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
+
+        p->datalink = ptv->datalink;
+        if (h.h2->tp_len > h.h2->tp_snaplen) {
+            SCLogDebug("Packet length (%d) > snaplen (%d), truncating",
+                    h.h2->tp_len, h.h2->tp_snaplen);
+        }
+        if (ptv->flags & AFP_ZERO_COPY) {
+            if (PacketSetData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
+                TmqhOutputPacketpool(ptv->tv, p);
+                SCReturnInt(AFP_FAILURE);
+            }
+        } else {
+            if (PacketCopyData(p, (unsigned char*)h.raw + h.h2->tp_mac, h.h2->tp_snaplen) == -1) {
+                TmqhOutputPacketpool(ptv->tv, p);
+                SCReturnInt(AFP_FAILURE);
+            }
+        }
+        /* Timestamp */
+        p->ts.tv_sec = h.h2->tp_sec;
+        p->ts.tv_usec = h.h2->tp_nsec/1000;
+        SCLogDebug("pktlen: %" PRIu32 " (pkt %p, pkt data %p)",
+                GET_PKT_LEN(p), p, GET_PKT_DATA(p));
+
+        /* We only check for checksum disable */
+        if (ptv->checksum_mode == CHECKSUM_VALIDATION_DISABLE) {
+            p->flags |= PKT_IGNORE_CHECKSUM;
+        } else if (ptv->checksum_mode == CHECKSUM_VALIDATION_AUTO) {
+            if (ptv->livedev->ignore_checksum) {
+                p->flags |= PKT_IGNORE_CHECKSUM;
+            } else if (ChecksumAutoModeCheck(ptv->pkts,
+                        SC_ATOMIC_GET(ptv->livedev->pkts),
+                        SC_ATOMIC_GET(ptv->livedev->invalid_checksums))) {
+                ptv->livedev->ignore_checksum = 1;
                 p->flags |= PKT_IGNORE_CHECKSUM;
+            }
+        } else {
+            if (h.h2->tp_status & TP_STATUS_CSUMNOTREADY) {
+                p->flags |= PKT_IGNORE_CHECKSUM;
+            }
+        }
+
+        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);
         }
-    }
 
-    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);