From c2d0d93806c6a684ced8492e86157a4f28e36bf4 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Sat, 9 Apr 2016 16:07:23 +0200 Subject: [PATCH] af-packet: detect availability of tpacket_v3 If TPACKET_V3 is not defined then it is not available and we should not build anything related to tpacket_v3. This will allow us to activate it dy default and fallback to v2 if not available. --- configure.ac | 5 +++++ src/runmode-af-packet.c | 6 ++++++ src/source-af-packet.c | 25 ++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d5719d7748..e7237651a2 100644 --- a/configure.ac +++ b/configure.ac @@ -1192,6 +1192,11 @@ AC_DEFINE([HAVE_PACKET_FANOUT],[1],[Recent packet fanout support is available]), [], [[#include ]]) + AC_CHECK_DECL([TPACKET_V3], + AC_DEFINE([HAVE_TPACKET_V3],[1],[AF_PACKET tpcket_v3 support is available]), + [], + [[#include + #include ]]) ]) # Netmap support diff --git a/src/runmode-af-packet.c b/src/runmode-af-packet.c index 15dc03baf4..f1c3dba316 100644 --- a/src/runmode-af-packet.c +++ b/src/runmode-af-packet.c @@ -231,13 +231,19 @@ void *ParseAFPConfig(const char *iface) (void)ConfGetChildValueBoolWithDefault(if_root, if_default, "tpacket-v3", (int *)&boolval); if (boolval) { if (strcasecmp(RunmodeGetActive(), "workers") == 0) { +#ifdef HAVE_TPACKET_V3 SCLogInfo("Enabling tpacket v3 capture on iface %s", aconf->iface); aconf->flags |= AFP_TPACKET_V3|AFP_RING_MODE; +#else + SCLogNotice("System too old for tpacket v3 switching to v2"); + aconf->flags |= AFP_RING_MODE; +#endif } else { SCLogError(SC_ERR_RUNMODE, "tpacket v3 is only implemented for 'workers' running mode." " Switching to tpacket v2."); + aconf->flags |= AFP_RING_MODE; } } (void)ConfGetChildValueBoolWithDefault(if_root, if_default, "use-emergency-flush", (int *)&boolval); diff --git a/src/source-af-packet.c b/src/source-af-packet.c index b149de8157..a993fddd70 100644 --- a/src/source-af-packet.c +++ b/src/source-af-packet.c @@ -179,7 +179,9 @@ enum { union thdr { struct tpacket2_hdr *h2; +#ifdef HAVE_TPACKET_V3 struct tpacket3_hdr *h3; +#endif void *raw; }; @@ -249,7 +251,9 @@ typedef struct AFPThreadVars_ union { struct tpacket_req req; +#ifdef HAVE_TPACKET_V3 struct tpacket_req3 req3; +#endif }; char iface[AFP_IFACE_NAME_LENGTH]; @@ -1002,6 +1006,7 @@ static inline int AFPWalkBlock(AFPThreadVars *ptv, struct tpacket_block_desc *pb */ int AFPReadFromRingV3(AFPThreadVars *ptv) { +#ifdef HAVE_TPACKET_V3 struct tpacket_block_desc *pbd; /* Loop till we have packets available */ @@ -1030,7 +1035,7 @@ int AFPReadFromRingV3(AFPThreadVars *ptv) SCReturnInt(AFP_READ_OK); } } - +#endif SCReturnInt(AFP_READ_OK); } @@ -1554,6 +1559,7 @@ frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + siz return 1; } +#ifdef HAVE_TPACKET_V3 static int AFPComputeRingParamsV3(AFPThreadVars *ptv) { ptv->req3.tp_block_size = ptv->block_size; @@ -1592,6 +1598,7 @@ static int AFPComputeRingParamsV3(AFPThreadVars *ptv) ); return 1; } +#endif static int AFPSetupRing(AFPThreadVars *ptv, char *devname) { @@ -1602,11 +1609,15 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) int order; int r, mmap_flag; +#ifdef HAVE_TPACKET_V3 if (ptv->flags & AFP_TPACKET_V3) { val = TPACKET_V3; } else { +#endif val = TPACKET_V2; +#ifdef HAVE_TPACKET_V3 } +#endif if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { if (errno == ENOPROTOOPT) { if (ptv->flags & AFP_TPACKET_V3) { @@ -1635,6 +1646,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) } /* Allocate RX ring */ +#ifdef HAVE_TPACKET_V3 if (ptv->flags & AFP_TPACKET_V3) { if (AFPComputeRingParamsV3(ptv) != 1) { return AFP_FATAL_ERROR; @@ -1650,6 +1662,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) return AFP_FATAL_ERROR; } } else { +#endif for (order = AFP_BLOCK_SIZE_DEFAULT_ORDER; order >= 0; order--) { if (AFPComputeRingParams(ptv, order) != 1) { SCLogInfo("Ring parameter are incorrect. Please correct the devel"); @@ -1680,14 +1693,20 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) devname); return AFP_FATAL_ERROR; } +#ifdef HAVE_TPACKET_V3 } +#endif /* Allocate the Ring */ +#ifdef HAVE_TPACKET_V3 if (ptv->flags & AFP_TPACKET_V3) { ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size; } else { +#endif ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size; +#ifdef HAVE_TPACKET_V3 } +#endif mmap_flag = MAP_SHARED; if (ptv->flags & AFP_MMAP_LOCKED) mmap_flag |= MAP_LOCKED; @@ -1697,6 +1716,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap"); goto mmap_err; } +#ifdef HAVE_TPACKET_V3 if (ptv->flags & AFP_TPACKET_V3) { ptv->ring_v3 = SCMalloc(ptv->req3.tp_block_nr * sizeof(*ptv->ring_v3)); if (!ptv->ring_v3) { @@ -1708,6 +1728,7 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size; } } else { +#endif /* allocate a ring for each frame header pointer*/ ptv->ring_v2 = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *)); if (ptv->ring_v2 == NULL) { @@ -1726,7 +1747,9 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname) } } ptv->frame_offset = 0; +#ifdef HAVE_TPACKET_V3 } +#endif return 0;