From a64dcfeba21241c560c98ae842b880d36977e8bd Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Fri, 9 Sep 2011 16:40:59 +0200 Subject: [PATCH] pfring: use factorisation function This patch convert pfring to pktacqloop and use the new factorisation function. This also fixes commmand line parsing of pfring which is now able to work like af-packet: - 'suricata -c s.yaml --pfring' start suricata with all interfaces in conf - 'suricata -c s.yaml --pfring=eth2' start suricata on eth2 --- src/runmode-pfring.c | 461 ++++++++++++------------------------------- src/source-pfring.c | 143 +++++++------- src/source-pfring.h | 21 ++ src/suricata.c | 25 ++- 4 files changed, 237 insertions(+), 413 deletions(-) diff --git a/src/runmode-pfring.c b/src/runmode-pfring.c index db53b291e9..77007e5b39 100644 --- a/src/runmode-pfring.c +++ b/src/runmode-pfring.c @@ -37,6 +37,7 @@ #include "util-time.h" #include "util-cpu.h" #include "util-affinity.h" +#include "util-runmodes.h" static const char *default_mode_auto = NULL; static const char *default_mode_autofp = NULL; @@ -44,11 +45,7 @@ static const char *default_mode_autofp = NULL; const char *RunModeIdsPfringGetDefaultMode(void) { #ifdef HAVE_PFRING - if (PfringConfGetThreads() <= 1) { - return default_mode_auto; - } else { - return default_mode_autofp; - } + return default_mode_autofp; #else return NULL; #endif @@ -72,6 +69,103 @@ void RunModeIdsPfringRegister(void) return; } +/** + * \brief extract information from config file + * + * The returned structure will be freed by the thread init function. + * This is thus necessary to or copy the structure before giving it + * to thread or to reparse the file for each thread (and thus have + * new structure. + * + * If old config system is used, then return the smae parameters + * value for each interface. + * + * \return a PfringIfaceConfig corresponding to the interface name + */ +void *ParsePfringConfig(const char *iface) +{ + char *threadsstr = NULL; + ConfNode *if_root; + ConfNode *pf_ring_node; + PfringIfaceConfig *pfconf = SCMalloc(sizeof(*pfconf)); + char *tmpclusterid; +#ifdef HAVE_PFRING_CLUSTER_TYPE + char *tmpctype = NULL; + char * default_ctype = strdup("cluster_round_robin"); +#endif + + if (iface == NULL) { + return NULL; + } + + if (pfconf == NULL) { + return NULL; + } + strlcpy(pfconf->iface, iface, sizeof(pfconf->iface)); + pfconf->threads = 1; + pfconf->cluster_id = 1; +#ifdef HAVE_PFRING_CLUSTER_TYPE + pfconf->ctype = (cluster_type)default_ctype; +#endif + + /* Find initial node */ + pf_ring_node = ConfGetNode("pfring"); + if (pf_ring_node == NULL) { + SCLogInfo("Unable to find pfring config using default value"); + return pfconf; + } + + if_root = ConfNodeLookupKeyValue(pf_ring_node, "interface", iface); + if (if_root == NULL) { + SCLogInfo("Unable to find af-packet config for " + "interface %s, using default value", + iface); + return pfconf; + } + + if (ConfGetChildValue(if_root, "threads", &threadsstr) != 1) { + pfconf->threads = 1; + } else { + if (threadsstr != NULL) { + pfconf->threads = (uint8_t)atoi(threadsstr); + } + } + if (pfconf->threads == 0) { + pfconf->threads = 1; + } + if (ConfGetChildValue(if_root, "cluster-id", &tmpclusterid) != 1) { + SCLogError(SC_ERR_INVALID_ARGUMENT,"Could not get cluster-id from config"); + } else { + pfconf->cluster_id = (uint16_t)atoi(tmpclusterid); + SCLogDebug("Going to use cluster-id %" PRId32, pfconf->cluster_id); + } + +#ifdef HAVE_PFRING_CLUSTER_TYPE + if (ConfGetChildValue(if_root, "cluster-type", &tmpctype) != 1) { + SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get cluster-type fron config"); + } else if (strcmp(tmpctype, "cluster_round_robin") == 0) { + SCLogInfo("Using round-robin cluster mode for PF_RING (iface %s)", + pfconf->iface); + pfconf->ctype = (cluster_type)tmpctype; + } else if (strcmp(tmpctype, "cluster_flow") == 0) { + SCLogInfo("Using flow cluster mode for PF_RING (iface %s)", + pfconf->iface); + pfconf->ctype = (cluster_type)tmpctype; + } else { + SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype); + return NULL; + } +#endif + + return pfconf; +} + +int PfringConfigGeThreadsCount(void *conf) +{ + PfringIfaceConfig *pfp = (PfringIfaceConfig *)conf; + return pfp->threads; +} + /** * \brief RunModeIdsPfringAuto set up the following thread packet handlers: * - Receive thread (from pfring) @@ -95,214 +189,21 @@ int RunModeIdsPfringAuto(DetectEngineCtx *de_ctx) SCEnter(); /* We include only if pfring is enabled */ #ifdef HAVE_PFRING - char tname[12]; - uint16_t cpu = 0; - - /* Available cpus */ - uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); + int ret; + char live_dev = NULL; RunModeInitialize(); TimeModeSetLive(); - /* create the threads */ - ThreadVars *tv_receivepfring = - TmThreadCreatePacketHandler("ReceivePfring", - "packetpool", "packetpool", - "pickup-queue1", "simple", - "1slot"); - if (tv_receivepfring == NULL) { - printf("ERROR: TmThreadsCreate failed\n"); - exit(EXIT_FAILURE); - } - TmModule *tm_module = TmModuleGetByName("ReceivePfring"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_receivepfring, tm_module, NULL); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_receivepfring, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_receivepfring, PRIO_MEDIUM); - } - - if (TmThreadSpawn(tv_receivepfring) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - ThreadVars *tv_decode1 = - TmThreadCreatePacketHandler("Decode1", - "pickup-queue1", "simple", - "decode-queue1", "simple", - "1slot"); - if (tv_decode1 == NULL) { - printf("ERROR: TmThreadsCreate failed for Decode1\n"); - exit(EXIT_FAILURE); - } - tm_module = TmModuleGetByName("DecodePfring"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName DecodePfring failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_decode1, tm_module, NULL); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_decode1, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_decode1, PRIO_MEDIUM); - } - - if (TmThreadSpawn(tv_decode1) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - ThreadVars *tv_stream1 = - TmThreadCreatePacketHandler("Stream1", - "decode-queue1", "simple", - "stream-queue1", "simple", - "1slot"); - if (tv_stream1 == NULL) { - printf("ERROR: TmThreadsCreate failed for Stream1\n"); - exit(EXIT_FAILURE); - } - tm_module = TmModuleGetByName("StreamTcp"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName StreamTcp failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_stream1, tm_module, NULL); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_stream1, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_stream1, PRIO_MEDIUM); - } - - if (TmThreadSpawn(tv_stream1) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - /* start with cpu 1 so that if we're creating an odd number of detect - * threads we're not creating the most on CPU0. */ - if (ncpus > 0) - cpu = 1; - - /* always create at least one thread */ - int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET); - if (thread_max == 0) - thread_max = ncpus * threading_detect_ratio; - if (thread_max < 1) - thread_max = 1; - - int thread; - for (thread = 0; thread < thread_max; thread++) { - snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1); - - char *thread_name = SCStrdup(tname); - SCLogDebug("Assigning %s affinity to cpu %u", thread_name, cpu); - - ThreadVars *tv_detect_ncpu = - TmThreadCreatePacketHandler(thread_name, - "stream-queue1", "simple", - "verdict-queue", "simple", - "1slot"); - if (tv_detect_ncpu == NULL) { - printf("ERROR: TmThreadsCreate failed\n"); - exit(EXIT_FAILURE); - } - tm_module = TmModuleGetByName("Detect"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName Detect failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_detect_ncpu, (int)cpu); - /* If we have more than one core/cpu, the first Detect thread - * (at cpu 0) will have less priority (higher 'nice' value) - * In this case we will set the thread priority to +10 (default is 0) - */ - if (cpu == 0 && ncpus > 1) { - TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_LOW); - } else if (ncpus > 1) { - TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_MEDIUM); - } - } + ConfGet("pfring.live-interface", &live_dev); - char *thread_group_name = SCStrdup("Detect"); - if (thread_group_name == NULL) { - printf("Error allocating memory\n"); - exit(EXIT_FAILURE); - } - tv_detect_ncpu->thread_group_name = thread_group_name; - - if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - if ((cpu + 1) == ncpus) - cpu = 0; - else - cpu++; - } - - ThreadVars *tv_rreject = - TmThreadCreatePacketHandler("RespondReject", - "verdict-queue", "simple", - "alert-queue1", "simple", - "1slot"); - if (tv_rreject == NULL) { - printf("ERROR: TmThreadsCreate failed\n"); - exit(EXIT_FAILURE); - } - tm_module = TmModuleGetByName("RespondReject"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName for RespondReject failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_rreject, tm_module, NULL); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_rreject, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_rreject, PRIO_MEDIUM); - } - - if (TmThreadSpawn(tv_rreject) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - ThreadVars *tv_outputs = - TmThreadCreatePacketHandler("Outputs", - "alert-queue1", "simple", - "packetpool", "packetpool", - "varslot"); - - if (tv_outputs == NULL) { - printf("ERROR: TmThreadCreatePacketHandler for Outputs failed\n"); - exit(EXIT_FAILURE); - } - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_outputs, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_outputs, PRIO_MEDIUM); - } - SetupOutputs(tv_outputs); - - if (TmThreadSpawn(tv_outputs) != TM_ECODE_OK) { + ret = RunModeSetLiveCaptureAuto(de_ctx, ParsePfringConfig, "ReceivePfring", "DecodePfring", + "RxPFR", live_dev); + if (ret != 0) { printf("ERROR: TmThreadSpawn failed\n"); exit(EXIT_FAILURE); } - #endif /* HAVE_PFRING */ return 0; } @@ -313,150 +214,34 @@ int RunModeIdsPfringAutoFp(DetectEngineCtx *de_ctx) /* We include only if pfring is enabled */ #ifdef HAVE_PFRING - - char tname[12]; - char qname[12]; - uint16_t cpu = 0; - char queues[2048] = ""; + int ret; + char *live_dev = NULL; RunModeInitialize(); TimeModeSetLive(); - /* Available cpus */ - uint16_t ncpus = UtilCpuGetNumProcessorsOnline(); - - /* start with cpu 1 so that if we're creating an odd number of detect - * threads we're not creating the most on CPU0. */ - if (ncpus > 0) - cpu = 1; - - /* always create at least one thread */ - int thread_max = TmThreadGetNbThreads(DETECT_CPU_SET); - if (thread_max == 0) - thread_max = ncpus * threading_detect_ratio; - if (thread_max < 1) - thread_max = 1; - - int thread; - for (thread = 0; thread < thread_max; thread++) { - if (strlen(queues) > 0) - strlcat(queues, ",", sizeof(queues)); - - snprintf(qname, sizeof(qname),"pickup%"PRIu16, thread+1); - strlcat(queues, qname, sizeof(queues)); - } - SCLogDebug("queues %s", queues); - - int pfring_threads = PfringConfGetThreads(); - if (pfring_threads == 0) { - pfring_threads = 1; - } - /* create the threads */ - for (thread = 0; thread < pfring_threads; thread++) { - snprintf(tname, sizeof(tname), "RxPfring%"PRIu16, thread+1); - char *thread_name = SCStrdup(tname); - - ThreadVars *tv_receive = - TmThreadCreatePacketHandler(thread_name, - "packetpool", "packetpool", - queues, "flow", "varslot"); - if (tv_receive == NULL) { - printf("ERROR: TmThreadsCreate failed\n"); - exit(EXIT_FAILURE); - } - TmModule *tm_module = TmModuleGetByName("ReceivePfring"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName failed for ReceivePfring\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_receive, tm_module, NULL); - - tm_module = TmModuleGetByName("DecodePfring"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName DecodePfring failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_receive, tm_module, NULL); + ConfGet("pfring.live-interface", &live_dev); - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_receive, 0); - if (ncpus > 1) - TmThreadSetThreadPriority(tv_receive, PRIO_MEDIUM); - } + SCLogDebug("live_dev %s", live_dev); - if (TmThreadSpawn(tv_receive) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } + ret = RunModeSetLiveCaptureAutoFp(de_ctx, + ParsePfringConfig, + PfringConfigGeThreadsCount, + "ReceivePfring", + "DecodePfring", "RxPFR", + live_dev); + if (ret != 0) { + printf("ERROR: Unable to start runmode\n"); + if (live_dev) + SCFree(live_dev); + exit(EXIT_FAILURE); } - for (thread = 0; thread < thread_max; thread++) { - snprintf(tname, sizeof(tname), "Detect%"PRIu16, thread+1); - snprintf(qname, sizeof(qname), "pickup%"PRIu16, thread+1); - - SCLogDebug("tname %s, qname %s", tname, qname); - - char *thread_name = SCStrdup(tname); - SCLogDebug("Assigning %s affinity to cpu %u", thread_name, cpu); - - ThreadVars *tv_detect_ncpu = - TmThreadCreatePacketHandler(thread_name, - qname, "flow", - "packetpool", "packetpool", - "varslot"); - if (tv_detect_ncpu == NULL) { - printf("ERROR: TmThreadsCreate failed\n"); - exit(EXIT_FAILURE); - } - TmModule *tm_module = TmModuleGetByName("StreamTcp"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName StreamTcp failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, NULL); - - tm_module = TmModuleGetByName("Detect"); - if (tm_module == NULL) { - printf("ERROR: TmModuleGetByName Detect failed\n"); - exit(EXIT_FAILURE); - } - TmSlotSetFuncAppend(tv_detect_ncpu, tm_module, (void *)de_ctx); - - if (threading_set_cpu_affinity) { - TmThreadSetCPUAffinity(tv_detect_ncpu, (int)cpu); - /* If we have more than one core/cpu, the first Detect thread - * (at cpu 0) will have less priority (higher 'nice' value) - * In this case we will set the thread priority to +10 (default is 0) - */ - if (cpu == 0 && ncpus > 1) { - TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_LOW); - } else if (ncpus > 1) { - TmThreadSetThreadPriority(tv_detect_ncpu, PRIO_MEDIUM); - } - } - - char *thread_group_name = SCStrdup("Detect"); - if (thread_group_name == NULL) { - printf("Error allocating memory\n"); - exit(EXIT_FAILURE); - } - tv_detect_ncpu->thread_group_name = thread_group_name; - - /* add outputs as well */ - SetupOutputs(tv_detect_ncpu); - - if (TmThreadSpawn(tv_detect_ncpu) != TM_ECODE_OK) { - printf("ERROR: TmThreadSpawn failed\n"); - exit(EXIT_FAILURE); - } - - if ((cpu + 1) == ncpus) - cpu = 0; - else - cpu++; - } + if (live_dev) + SCFree(live_dev); + SCLogInfo("RunModeIdsPfringAutoFp initialised"); #endif /* HAVE_PFRING */ return 0; diff --git a/src/source-pfring.c b/src/source-pfring.c index e532d10b76..5eb26178f4 100644 --- a/src/source-pfring.c +++ b/src/source-pfring.c @@ -44,7 +44,7 @@ #include "util-debug.h" #include "util-privs.h" -TmEcode ReceivePfring(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *); +TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot); TmEcode ReceivePfringThreadInit(ThreadVars *, void *, void **); void ReceivePfringThreadExitStats(ThreadVars *, void *); TmEcode ReceivePfringThreadDeinit(ThreadVars *, void *); @@ -103,9 +103,6 @@ TmEcode NoPfringSupportExit(ThreadVars *tv, void *initdata, void **data) #define LIBPFRING_REENTRANT 0 #define LIBPFRING_WAIT_FOR_INCOMING 1 - -int g_pfring_threads; - /** * \brief Structure to hold thread specific variables. */ @@ -118,6 +115,12 @@ typedef struct PfringThreadVars_ uint64_t bytes; uint32_t pkts; + ThreadVars *tv; + TmSlot *slot; + + /* threads count */ + int threads; + #ifdef HAVE_PFRING_CLUSTER_TYPE cluster_type ctype; #endif /* HAVE_PFRING_CLUSTER_TYPE */ @@ -132,7 +135,8 @@ typedef struct PfringThreadVars_ void TmModuleReceivePfringRegister (void) { tmm_modules[TMM_RECEIVEPFRING].name = "ReceivePfring"; tmm_modules[TMM_RECEIVEPFRING].ThreadInit = ReceivePfringThreadInit; - tmm_modules[TMM_RECEIVEPFRING].Func = ReceivePfring; + tmm_modules[TMM_RECEIVEPFRING].Func = NULL; + tmm_modules[TMM_RECEIVEPFRING].PktAcqLoop = ReceivePfringLoop; tmm_modules[TMM_RECEIVEPFRING].ThreadExitPrintStats = ReceivePfringThreadExitStats; tmm_modules[TMM_RECEIVEPFRING].ThreadDeinit = NULL; tmm_modules[TMM_RECEIVEPFRING].RegisterTests = NULL; @@ -151,24 +155,6 @@ void TmModuleDecodePfringRegister (void) { tmm_modules[TMM_DECODEPFRING].RegisterTests = NULL; } -int PfringConfGetThreads(void) { - return g_pfring_threads; -} - -void PfringLoadConfig(void) { - char *threadsstr = NULL; - - if (ConfGet("pfring.threads", &threadsstr) != 1) { - g_pfring_threads = 1; - } else { - if (threadsstr != NULL) { - g_pfring_threads = (uint8_t)atoi(threadsstr); - SCLogInfo("Going to use %" PRId32 " PF_RING receive thread(s)", - g_pfring_threads); - } - } -} - /** * \brief Pfring Packet Process function. * @@ -204,40 +190,65 @@ static inline void PfringProcessPacket(void *user, struct pfring_pkthdr *h, Pack * * \param tv pointer to ThreadVars * \param data pointer that gets cast into PfringThreadVars for ptv - * \param pq pointer to the PacketQueue (not used here but part of the api) + * \param slot slot containing task information * \retval TM_ECODE_OK on success * \retval TM_ECODE_FAILED on failure */ -TmEcode ReceivePfring(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq, PacketQueue *postpq) { +TmEcode ReceivePfringLoop(ThreadVars *tv, void *data, void *slot) +{ + uint16_t packet_q_len = 0; PfringThreadVars *ptv = (PfringThreadVars *)data; + TmSlot *s = (TmSlot *)slot; + ptv->slot = s->slot_next; + Packet *p = NULL; struct pfring_pkthdr hdr; - if (suricata_ctl_flags & SURICATA_STOP || - suricata_ctl_flags & SURICATA_KILL) { - SCReturnInt(TM_ECODE_OK); - } + SCEnter(); - /* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */ + while(1) { + if (suricata_ctl_flags & SURICATA_STOP || + suricata_ctl_flags & SURICATA_KILL) { + SCReturnInt(TM_ECODE_FAILED); + } + + /* make sure we have at least one packet in the packet pool, to prevent + * us from alloc'ing packets at line rate */ + do { + packet_q_len = PacketPoolSize(); + if (unlikely(packet_q_len == 0)) { + PacketPoolWait(); + } + } while (packet_q_len == 0); + + p = PacketGetFromQueueOrAlloc(); + if (p == NULL) { + SCReturnInt(TM_ECODE_FAILED); + } + + /* Depending on what compile time options are used for pfring we either return 0 or -1 on error and always 1 for success */ #ifdef HAVE_PFRING_RECV_UCHAR - int r = pfring_recv(ptv->pd, (u_char**)&GET_PKT_DIRECT_DATA(p), - (u_int)GET_PKT_DIRECT_MAX_SIZE(p), - &hdr, - LIBPFRING_WAIT_FOR_INCOMING); + int r = pfring_recv(ptv->pd, (u_char**)&GET_PKT_DIRECT_DATA(p), + (u_int)GET_PKT_DIRECT_MAX_SIZE(p), + &hdr, + LIBPFRING_WAIT_FOR_INCOMING); #else - int r = pfring_recv(ptv->pd, (char *)GET_PKT_DIRECT_DATA(p), - (u_int)GET_PKT_DIRECT_MAX_SIZE(p), - &hdr, - LIBPFRING_WAIT_FOR_INCOMING); + int r = pfring_recv(ptv->pd, (char *)GET_PKT_DIRECT_DATA(p), + (u_int)GET_PKT_DIRECT_MAX_SIZE(p), + &hdr, + LIBPFRING_WAIT_FOR_INCOMING); #endif /* HAVE_PFRING_RECV_UCHAR */ - if (r == 1) { - //printf("RecievePfring src %" PRIu32 " sport %" PRIu32 " dst %" PRIu32 " dstport %" PRIu32 "\n", - // hdr.parsed_pkt.ipv4_src,hdr.parsed_pkt.l4_src_port, hdr.parsed_pkt.ipv4_dst,hdr.parsed_pkt.l4_dst_port); - PfringProcessPacket(ptv, &hdr, p); - } else { - SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error %" PRId32 "", r); - return TM_ECODE_FAILED; + if (r == 1) { + //printf("RecievePfring src %" PRIu32 " sport %" PRIu32 " dst %" PRIu32 " dstport %" PRIu32 "\n", + // hdr.parsed_pkt.ipv4_src,hdr.parsed_pkt.l4_src_port, hdr.parsed_pkt.ipv4_dst,hdr.parsed_pkt.l4_dst_port); + PfringProcessPacket(ptv, &hdr, p); + TmThreadsSlotProcessPkt(ptv->tv, ptv->slot, p); + } else { + SCLogError(SC_ERR_PF_RING_RECV,"pfring_recv error %" PRId32 "", r); + TmqhOutputPacketpool(ptv->tv, p); + return TM_ECODE_FAILED; + } } return TM_ECODE_OK; @@ -262,18 +273,17 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { u_int32_t version = 0; char *tmpclusterid; char *tmpctype; + PfringIfaceConfig *pfconf = (PfringIfaceConfig *) initdata; PfringThreadVars *ptv = SCMalloc(sizeof(PfringThreadVars)); if (ptv == NULL) return TM_ECODE_FAILED; memset(ptv, 0, sizeof(PfringThreadVars)); - if (ConfGet("pfring.interface", &ptv->interface) != 1) { - SCLogError(SC_ERR_PF_RING_GET_INTERFACE_FAILED,"Could not get pfring.interface"); - return TM_ECODE_FAILED; - } else { - SCLogDebug("going to use interface %s",ptv->interface); - } + ptv->tv = tv; + ptv->threads = 1; + + ptv->interface = strdup(pfconf->iface); ptv->pd = pfring_open(ptv->interface, LIBPFRING_PROMISC, (uint32_t)default_packet_size, LIBPFRING_REENTRANT); if (ptv->pd == NULL) { @@ -283,30 +293,17 @@ TmEcode ReceivePfringThreadInit(ThreadVars *tv, void *initdata, void **data) { } else { pfring_set_application_name(ptv->pd, PROG_NAME); pfring_version(ptv->pd, &version); - } /* We only set cluster info if the number of pfring threads is greater than 1 */ - if (PfringConfGetThreads() > 1) { - if (ConfGet("pfring.cluster-id", &tmpclusterid) != 1) { - SCLogError(SC_ERR_PF_RING_GET_CLUSTERID_FAILED,"could not get pfring.cluster-id"); - return TM_ECODE_FAILED; - } else { - ptv->cluster_id = (uint8_t)atoi(tmpclusterid); - SCLogDebug("Going to use cluster-id %" PRId32, ptv->cluster_id); - } + ptv->threads = pfconf->threads; + + if (ptv->threads > 1) { + ptv->cluster_id = pfconf->cluster_id; #ifdef HAVE_PFRING_CLUSTER_TYPE - if (ConfGet("pfring.cluster-type", &tmpctype) != 1) { - SCLogError(SC_ERR_GET_CLUSTER_TYPE_FAILED,"Could not get pfring.cluster-type"); - return TM_ECODE_FAILED; - } else if (strcmp(tmpctype, "cluster_round_robin") == 0 || strcmp(tmpctype, "cluster_flow") == 0) { - ptv->ctype = (cluster_type)tmpctype; - rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); - } else { - SCLogError(SC_ERR_INVALID_CLUSTER_TYPE,"invalid cluster-type %s",tmpctype); - return TM_ECODE_FAILED; - } + ptv->ctype = (cluster_type)strdup((char *)pfconf->ctype); + rc = pfring_set_cluster(ptv->pd, ptv->cluster_id, ptv->ctype); #else rc = pfring_set_cluster(ptv->pd, ptv->cluster_id); #endif /* HAVE_PFRING_CLUSTER_TYPE */ @@ -370,6 +367,12 @@ void ReceivePfringThreadExitStats(ThreadVars *tv, void *data) { */ TmEcode ReceivePfringThreadDeinit(ThreadVars *tv, void *data) { PfringThreadVars *ptv = (PfringThreadVars *)data; + if (ptv->interface) + SCFree(ptv->interface); +#ifdef HAVE_PFRING_CLUSTER_TYPE + if (ptv->ctype) + SCFree((char *)ptv->ctype); +#endif pfring_remove_from_cluster(ptv->pd); pfring_close(ptv->pd); return TM_ECODE_OK; diff --git a/src/source-pfring.h b/src/source-pfring.h index 11fc96e4d1..cfe3335ef5 100644 --- a/src/source-pfring.h +++ b/src/source-pfring.h @@ -24,6 +24,27 @@ #ifndef __SOURCE_PFRING_H__ #define __SOURCE_PFRING_H__ +#define PFRING_IFACE_NAME_LENGTH 48 + +#include +#ifdef HAVE_PFRING +#include +#endif + +typedef struct PfringIfaceConfig_ +{ + /* cluster param */ + int cluster_id; +#ifdef HAVE_PFRING_CLUSTER_TYPE + cluster_type ctype; +#endif /* HAVE_PFRING_CLUSTER_TYPE */ + char iface[PFRING_IFACE_NAME_LENGTH]; + /* number of threads */ + int threads; +} PfringIfaceConfig; + + + void TmModuleReceivePfringRegister (void); void TmModuleDecodePfringRegister (void); diff --git a/src/suricata.c b/src/suricata.c index 3524bfbc0c..328ac64593 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -683,10 +683,11 @@ int main(int argc, char **argv) #ifdef HAVE_PFRING run_mode = RUNMODE_PFRING; if (optarg != NULL) { - if (ConfSet("pfring.interface", optarg, 0) != 1) { - fprintf(stderr, "ERROR: Failed to set pfring.interface.\n"); - exit(EXIT_FAILURE); - } + memset(pcap_dev, 0, sizeof(pcap_dev)); + strlcpy(pcap_dev, optarg, + ((strlen(optarg) < sizeof(pcap_dev)) ? + (strlen(optarg) + 1) : sizeof(pcap_dev))); + LiveRegisterDevice(optarg); } #else SCLogError(SC_ERR_NO_PF_RING,"PF_RING not enabled. Make sure " @@ -1078,6 +1079,7 @@ int main(int argc, char **argv) case RUNMODE_PCAP_DEV: case RUNMODE_AFP_DEV: case RUNMODE_PFRING: + /* FIXME this don't work effficiently in multiinterface */ /* find payload for interface and use it */ default_packet_size = GetIfaceMaxPayloadSize(pcap_dev); if (default_packet_size) @@ -1432,7 +1434,20 @@ int main(int argc, char **argv) } #ifdef HAVE_PFRING } else if (run_mode == RUNMODE_PFRING) { - PfringLoadConfig(); + /* FIXME add backward compat support */ + /* iface has been set on command line */ + if (strlen(pcap_dev)) { + if (ConfSet("pfring.live-interface", pcap_dev, 0) != 1) { + fprintf(stderr, "ERROR: Failed to set pfring.live-interface\n"); + exit(EXIT_FAILURE); + } + } else { + int ret = LiveBuildIfaceList("pfring"); + if (ret == 0) { + fprintf(stderr, "ERROR: No interface found in config for pfring\n"); + exit(EXIT_FAILURE); + } + } #endif /* HAVE_PFRING */ } else if (run_mode == RUNMODE_AFP_DEV) { /* iface has been set on command line */