From: Victor Julien Date: Tue, 21 Jun 2016 14:43:53 +0000 (+0200) Subject: af-packet: test if fanout is supported before use X-Git-Tag: suricata-3.1.1~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=402bdf9b2b76ac56f33d87e6f6a4d51a30ec57c7;p=thirdparty%2Fsuricata.git af-packet: test if fanout is supported before use 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) (TmThreadWaitOnThreadInit) -- all 4 packet processing threads, 4 management threads initialized, engine started. [15785] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) (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) (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) (main) -- Signal Received. Stopping engine. [15787] 21/6/2016 -- 16:00:13 - (source-af-packet.c:1907) (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) (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) (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) (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) (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) (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) (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. --- diff --git a/src/runmode-af-packet.c b/src/runmode-af-packet.c index 1e003f7c16..714589fc55 100644 --- a/src/runmode-af-packet.c +++ b/src/runmode-af-packet.c @@ -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(); diff --git a/src/source-af-packet.c b/src/source-af-packet.c index 313278e3cc..db6f5056bc 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -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; diff --git a/src/source-af-packet.h b/src/source-af-packet.h index 2aa803a56b..513fdc9b37 100644 --- a/src/source-af-packet.h +++ b/src/source-af-packet.h @@ -147,4 +147,6 @@ TmEcode AFPPeersListCheck(); void AFPPeersListClean(); int AFPGetLinkType(const char *ifname); +int AFPIsFanoutSupported(void); + #endif /* __SOURCE_AFP_H__ */