From: Eric Leblond Date: Fri, 27 Jul 2012 09:29:37 +0000 (+0200) Subject: af-packet: loop on ring if there is data to read. X-Git-Tag: suricata-1.3.1~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a369f8c359f19fcf7a5df85288f2f7b92c1816ad;p=thirdparty%2Fsuricata.git af-packet: loop on ring if there is data to read. 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. --- diff --git a/src/source-af-packet.c b/src/source-af-packet.c index 20062ee35e..c201876959 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -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);