]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
af-packet: test if fanout is supported before use
authorVictor Julien <victor@inliniac.net>
Tue, 21 Jun 2016 14:43:53 +0000 (16:43 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 21 Jun 2016 15:12:38 +0000 (17:12 +0200)
Older system may pretend they can support FANOUT but then fail to
work at runtime. CentOS6 is an example of this. It would fail to
start up with the default configuration with errors like:

[15770] 21/6/2016 -- 16:00:13 - (tm-threads.c:2168) <Notice> (TmThreadWaitOnThreadInit) -- all 4 packet processing threads, 4 management threads initialized, engine started.
[15785] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) <Error> (AFPCreateSocket) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Coudn't set fanout mode, error Protocol not available
[15785] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1337) <Error> (ReceiveAFPLoop) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Couldn't init AF_PACKET socket, fatal error
[15770] 21/6/2016 -- 16:00:13 - (suricata.c:2664) <Notice> (main) -- Signal Received.  Stopping engine.
[15787] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) <Error> (AFPCreateSocket) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Coudn't set fanout mode, error Protocol not available
[15788] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) <Error> (AFPCreateSocket) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Coudn't set fanout mode, error Protocol not available
[15786] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) <Error> (AFPCreateSocket) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Coudn't set fanout mode, error Protocol not available
[15789] 21/6/2016 -- 16:00:13 - (flow-manager.c:693) <Perf> (FlowManager) -- 0 new flows, 0 established flows were timed out, 0 flows in closed state
[15787] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1337) <Error> (ReceiveAFPLoop) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Couldn't init AF_PACKET socket, fatal error
[15788] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1337) <Error> (ReceiveAFPLoop) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Couldn't init AF_PACKET socket, fatal error
[15786] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1337) <Error> (ReceiveAFPLoop) -- [ERRCODE: SC_ERR_AFP_CREATE(190)] - Couldn't init AF_PACKET socket, fatal error

This patch adds a test that if run before the number of threads
is determined. If the test fails, only 1 thread is created.

src/runmode-af-packet.c
src/source-af-packet.c
src/source-af-packet.h

index 1e003f7c16fa97bf3b02204e1bfc39c744b0ad38..714589fc5539eb31d289175cc1971ffdfd7c83fd 100644 (file)
@@ -387,6 +387,19 @@ void *ParseAFPConfig(const char *iface)
 
 finalize:
 
+    /* if the number of threads is not 1, we need to first check if fanout
+     * functions on this system. */
+    if (aconf->threads != 1) {
+        if (AFPIsFanoutSupported() == 0) {
+            if (aconf->threads != 0) {
+                SCLogNotice("fanout not supported on this system, falling "
+                        "back to 1 capture thread");
+            }
+            aconf->threads = 1;
+        }
+    }
+
+    /* try to automagically set the proper number of threads */
     if (aconf->threads == 0) {
         int rss_queues;
         aconf->threads = (int)UtilCpuGetNumProcessorsOnline();
index 313278e3ccd6beb7dbaf872f5cd5b51dba1fb166..db6f5056bc65462278cf0b28f26d3a0870603c9e 100644 (file)
@@ -1809,6 +1809,30 @@ mmap_err:
     return AFP_FATAL_ERROR;
 }
 
+/** \brief test if we can use FANOUT. Older kernels like those in
+ *         CentOS6 have HAVE_PACKET_FANOUT defined but fail to work
+ */
+int AFPIsFanoutSupported(void)
+{
+#ifdef HAVE_PACKET_FANOUT
+    int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+    if (fd != -1) {
+        uint16_t mode = PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_DEFRAG;
+        uint16_t id = 99;
+        uint32_t option = (mode << 16) | (id & 0xffff);
+        int r = setsockopt(fd, SOL_PACKET, PACKET_FANOUT,(void *)&option, sizeof(option));
+        close(fd);
+
+        if (r < 0) {
+            SCLogPerf("fanout not supported by kernel: %s", strerror(errno));
+            return 0;
+        }
+        return 1;
+    }
+#endif
+    return 0;
+}
+
 static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
 {
     int r;
index 2aa803a56b9c781f9c79ed56cb0e91b908d8672c..513fdc9b37ffa142a58a41ffc155ea47fd521d8c 100644 (file)
@@ -147,4 +147,6 @@ TmEcode AFPPeersListCheck();
 void AFPPeersListClean();
 int AFPGetLinkType(const char *ifname);
 
+int AFPIsFanoutSupported(void);
+
 #endif /* __SOURCE_AFP_H__ */