From 27b5136bf29a2698ccbb4b303619a08d045689e0 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Fri, 27 Jul 2012 11:48:10 +0200 Subject: [PATCH] af-packet: add optional emergency mode 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 | 7 +++++++ src/source-af-packet.c | 24 ++++++++++++++++++++++-- src/source-af-packet.h | 1 + suricata.yaml.in | 3 +++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/runmode-af-packet.c b/src/runmode-af-packet.c index 0a92be406d..aaceb55ee8 100644 --- a/src/runmode-af-packet.c +++ b/src/runmode-af-packet.c @@ -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", ©modestr) == 1) { diff --git a/src/source-af-packet.c b/src/source-af-packet.c index a128243262..ec838cbe2e 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -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", diff --git a/src/source-af-packet.h b/src/source-af-packet.h index d9e9a759a6..263b1d9105 100644 --- a/src/source-af-packet.h +++ b/src/source-af-packet.h @@ -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 diff --git a/suricata.yaml.in b/suricata.yaml.in index 224bd349aa..1cff85e228 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -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