Commit 7e3bd892 authored by Nigel Kukard's avatar Nigel Kukard
Browse files

* Various code cleanups

* Added parameters...

	report-format
		Either rrd or native, updates rrd files and creates BWM Tools native logging files automagically

	report-filename
		Specify the report filename manually

	flow-mode
		Specify the mode of flow control for the said flow, either local (INPUT & OUTPUT) or forward (FORWARD), this is needed if you're shaping traffic sourcing and destined to your local box and not forwarding traffic through a firewall/router

* Install RRD Tool when installing BWM Tools
parent d56b391d
......@@ -17,7 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
SUBDIRS=lib bwm_firewall bwm_graph bwmd bwm_monitor doc
SUBDIRS=@RRDTOOL_DIRS@ lib bwm_firewall bwm_graph bwmd bwm_monitor doc
EXTRA_DIST=include/autoclass.h include/common.h include/flow.h include/flowControl.h include/ipq.h
EXTRA_DIST+=include/libipq.h include/misc.h include/report.h include/xmlConf.h
......@@ -13,3 +13,19 @@ TO DO
* bwm_firewall to generate automatic MARK values for flows
* fix findFlowByName & findGroupByName, these 2 functions are similar and i'm sure can be merged
* have the location of iptables-restore automatically discovered using ./configure, with override options
* Create /etc/bwm_tools and /var/bwm_tools on install
* BPS/KBPS/MBPS support in firewall.xml for flows
* TBF and CBQ params
- queue-manager
- prio
* Process bands in priority, dequeue 0 first, then 1 ... to n
- prio-weighted
* Dequeue X packets or X bytes + add a weight
* Fix up prio classifier
* Fix default queue size + len
* xmlConf queue & flow parsing has duplicated code, alot!
* Try autoassign nfmark?
......@@ -23,13 +23,23 @@ GLIB_CFLAGS=@GLIB_CFLAGS@
XML_LIBS=@XML_LIBS@
XML_CFLAGS=@XML_CFLAGS@
RRDTOOL_INCLUDEDIR=@RRDTOOL_INCLUDEDIR@
RRDTOOL_LIBS=@RRDTOOL_LIBS@
RRDTOOL_LDADDS=@RRDTOOL_LDADDS@
RRDTOOL_VER=@RRDTOOL_VER@
CONFIG_DIR=/etc/bwm_tools
CONFIG_FILE=$(CONFIG_DIR)/firewall.xml
LOG_DIR=/var/bwm_tools
bin_PROGRAMS = bwmd
bwmd_SOURCES = report.c flowControl.c logging.c ipq.c flow.c libipq.c autoclass.c bwmd.c
bwmd_LDADD = $(top_builddir)/lib/libbwm.la
bwmd_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) -DCONFIG_FILE=\"$(CONFIG_FILE)\" -DLOG_DIR=\"$(LOG_DIR)\" $(AM_CFLAGS)
bwmd_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS)
bwmd_SOURCES = report.c flowControl.c logging.c ipq.c libipq.c flow.c autoclass.c bwmd.c
bwmd_DEPENDENCIES = $(RRDTOOL_LDADDS)
bwmd_LDADD = $(top_builddir)/lib/libbwm.la $(RRDTOOL_LDADDS)
bwmd_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) $(RRDTOOL_INCLUDEDIR) -DCONFIG_FILE=\"$(CONFIG_FILE)\" \
-DRRDTOOL_VER=$(RRDTOOL_VER) $(AM_CFLAGS)
bwmd_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS) $(RRDTOOL_LIBS)
# Build rrdtool if we need it
$(top_builddir)/rrdtool/src/librrd.la:
$(MAKE) $(AM_MAKEFLAGS) -C ../rrdtool
......@@ -31,12 +31,13 @@
#include <time.h>
#include <unistd.h>
#include "flow.h"
#include "misc.h"
#include "report.h"
// Function to write a log entry to the report file
static void *writeEntry(void *data)
static void *writeNativeEntry(void *data)
{
struct reportData_t *reportData = (struct reportData_t*) data;
struct stat statBuf;
......@@ -45,28 +46,23 @@ static void *writeEntry(void *data)
int opRes;
int err = 0;
int fd;
char filename[MAX_NAMELEN];
// Blank file header & filename
// Blank file header
memset(&fileHeader,'\0',sizeof(struct aLogFileHeader_t));
memset(&filename,'\0',MAX_NAMELEN);
// Lets get our filename...
snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,reportData->ref);
// Get stats for file
result = stat(filename,&statBuf);
result = stat(reportData->reportFilename,&statBuf);
if (result == 0)
{
// Stats was ok, open it
fd = open(filename,O_RDWR);
fd = open(reportData->reportFilename,O_RDWR);
if (fd > 0)
{
opRes = read(fd,&fileHeader,sizeof(struct aLogFileHeader_t));
if (opRes != sizeof(struct aLogFileHeader_t))
{
logMessage(LOG_DEBUG, "Error reading header from \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error reading header from \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
// If no errors seek...
......@@ -76,7 +72,7 @@ static void *writeEntry(void *data)
opRes = lseek(fd,0,SEEK_END);
if (opRes < 0)
{
logMessage(LOG_DEBUG, "Error seeking end of file \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error seeking end of file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
}
......@@ -87,7 +83,7 @@ static void *writeEntry(void *data)
opRes = write(fd,&reportData->entry,sizeof(struct aLogFileEntry_t));
if (opRes != sizeof(struct aLogFileEntry_t))
{
logMessage(LOG_DEBUG, "Error writing record to file \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error writing record to file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
else
......@@ -107,7 +103,7 @@ static void *writeEntry(void *data)
opRes = lseek(fd,0,SEEK_SET);
if (opRes < 0)
{
logMessage(LOG_DEBUG, "Error seeking beginning of file \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error seeking beginning of file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
}
......@@ -118,28 +114,28 @@ static void *writeEntry(void *data)
opRes = write(fd,&fileHeader,sizeof(struct aLogFileHeader_t));
if (opRes != sizeof(struct aLogFileHeader_t))
{
logMessage(LOG_DEBUG, "Error writing header to file \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error writing header to file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
}
close(fd);
}
else
fprintf(stderr,"Stat error on \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR,"Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
}
else
{
// Check if file doesn't exist
if (errno == ENOENT)
{
logMessage(LOG_DEBUG, "Creating report file %s\n",filename);
logMessage(LOG_ERR, "Creating report file %s\n",reportData->reportFilename);
// If not create it
fd = open(filename,O_CREAT|O_RDWR,S_IREAD|S_IWRITE);
fd = open(reportData->reportFilename,O_CREAT|O_RDWR,S_IREAD|S_IWRITE);
if (fd > 0)
{
// Build header
memcpy(&fileHeader.fileVer,FILE_VER_CURRENT,strlen(FILE_VER_CURRENT));
memcpy(&fileHeader.ref,&reportData->ref,strlen(reportData->ref));
memcpy(&fileHeader.ref,reportData->ref,strlen(reportData->ref));
fileHeader.start = reportData->entry.unixStampStart;
fileHeader.end = reportData->entry.unixStampStart;
fileHeader.recs = 1;
......@@ -148,7 +144,7 @@ static void *writeEntry(void *data)
opRes = write(fd,&fileHeader,sizeof(struct aLogFileHeader_t));
if (opRes != sizeof(struct aLogFileHeader_t))
{
logMessage(LOG_DEBUG, "Error writing header to \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error writing header to \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
// If no errors write more...
......@@ -157,17 +153,73 @@ static void *writeEntry(void *data)
opRes = write(fd,&reportData->entry,sizeof(struct aLogFileEntry_t));
if (opRes != sizeof(struct aLogFileEntry_t))
{
logMessage(LOG_DEBUG, "Error writing record to \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Error writing record to \"%s\": %s\n",reportData->reportFilename,strerror(errno));
err = 1;
}
}
close(fd);
}
else
logMessage(LOG_DEBUG, "Stat error on \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Failed to create \"%s\": %s\n",reportData->reportFilename,strerror(errno));
}
else
logMessage(LOG_DEBUG, "Failed to open file \"%s\": %s\n",filename,strerror(errno));
logMessage(LOG_ERR, "Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
}
return(NULL);
}
// Function to write a log entry to an RRD file
static void *writeRRDEntry(void *data)
{
struct reportData_t *reportData = (struct reportData_t*) data;
struct stat statBuf;
int result;
int opRes;
int err = 0;
int fd;
// Get stats for file
result = stat(reportData->reportFilename,&statBuf);
if (result == 0)
{
char **params;
int numParams = 0;
int i;
// Create just a little mem for us to begin with
params = (char **) malloc0(sizeof(char*));
// Add update string
ADD_SINGLE_PARAM(params,numParams,
"%i@%i:%i:%i:%i",
reportData->entry.unixStampEnd,
reportData->entry.bytesSeen,
reportData->entry.packetsSeen,
reportData->entry.packetsBursted,
reportData->entry.packetsDropped
);
// Try the update
if ((i = rrd_update_r(reportData->reportFilename,"bytes:packets:bursted:dropped",numParams,params)) < 0)
logMessage(LOG_ERR,"Failed to update RRD file %s: %s\n",reportData->reportFilename,rrd_get_error());
// Free memory
for (i = 0; i < numParams; i++)
free(params[i]);
free(params);
}
else
{
// Check if file doesn't exist
if (errno == ENOENT)
logMessage(LOG_ERR, "Please create \"%s\" first\n",reportData->reportFilename);
else
logMessage(LOG_ERR, "Failed to open file \"%s\": %s\n",reportData->reportFilename,strerror(errno));
}
return(NULL);
......@@ -208,9 +260,9 @@ void *reportRunner(void *data)
// Check if we gonna pump to disk
if (flow->counterRemaining < 1)
{
// Build our structure to pump into the file
strncpy(reportData.ref,flow->flowName,MAX_REFLEN);
reportData.ref = flow->flowName;
reportData.reportFilename = flow->reportFilename;
reportData.entry.unixStampStart = flow->lastDumpTimestamp;
flow->lastDumpTimestamp = time(NULL);
reportData.entry.unixStampEnd = flow->lastDumpTimestamp;
......@@ -220,8 +272,16 @@ void *reportRunner(void *data)
reportData.entry.packetsSeen = flow->counter.pktCount;
reportData.entry.packetsBursted = flow->counter.pktBursted;
reportData.entry.packetsDropped = flow->counter.pktDropped;
// Log to file
writeEntry(&reportData);
// Check what format we're working with
if (flow->reportFormat == REPORT_FORMAT_NATIVE)
// Log to file
writeNativeEntry(&reportData);
else if (flow->reportFormat == REPORT_FORMAT_RRD)
writeRRDEntry(&reportData);
else
logMessage(LOG_ERR, "ERROR: Internal error, report format not understood for \"%s\"\n",flow->flowName);
// Reset counters
flow->counterRemaining = flow->counterTimeout;
reset = 1;
......@@ -267,8 +327,7 @@ void *reportRunner(void *data)
// Check if we gonna pump to disk
if (group->counterRemaining < 1)
{
// Build our structure to pump into the file
// Build our structure and write below
strncpy(reportData.ref,group->groupName,MAX_REFLEN);
reportData.entry.unixStampStart = group->lastDumpTimestamp;
group->lastDumpTimestamp = time(NULL);
......@@ -279,8 +338,16 @@ void *reportRunner(void *data)
reportData.entry.packetsSeen = group->counter.pktCount;
reportData.entry.packetsBursted = group->counter.pktBursted;
reportData.entry.packetsDropped = group->counter.pktDropped;
// Log to file
writeEntry(&reportData);
// Check what format we're working with
if (group->reportFormat == REPORT_FORMAT_NATIVE)
// Log to file
writeNativeEntry(&reportData);
else if (group->reportFormat == REPORT_FORMAT_RRD)
writeRRDEntry(&reportData);
else
logMessage(LOG_ERR, "ERROR: Internal error, report format not understood for \"%s\"\n",group->groupName);
// Reset counters
group->counterRemaining = group->counterTimeout;
reset = 1;
......
......@@ -20,7 +20,7 @@
*/
AC_PREREQ(2.57)
AC_INIT([bwm_tools],[200602012132])
AC_INIT([bwm_tools],[devel])
AC_CONFIG_SRCDIR([bwm_monitor/bwm_monitor.c])
AC_CONFIG_HEADER([config.h])
......@@ -58,6 +58,7 @@ AC_ARG_WITH([rrdtool-source],
[ --with-rrdtool-source Specify that you have the rrdtool sources in the main build dir],
[
AC_CONFIG_SUBDIRS(rrdtool)
RRDTOOL_DIRS="rrdtool"
RRDTOOL_LDADDS="\$(top_builddir)/rrdtool/src/librrd.la"
RRDTOOL_INCLUDEDIR="-I\$(top_builddir)/rrdtool/src"
],
......@@ -87,7 +88,7 @@ AC_ARG_WITH([rrdtool-source],
RRDTOOL_LIBS="-lm -lrrd"
])
AC_SUBST(RRDTOOL_LDADDS RRDTOOL_LIBS RRDTOOL_INCLUDEDIR RRDTOOL_VER)
AC_SUBST(RRDTOOL_DIRS RRDTOOL_LDADDS RRDTOOL_LIBS RRDTOOL_INCLUDEDIR RRDTOOL_VER)
# Checks for header files.
AC_HEADER_STDC
......
......@@ -824,6 +824,20 @@ parameter is set to 60, @command{bwmd} will log traffic stats to file every 60
seconds. Minimum value for this parameter is 30.
@*
@item
@cindex report-format
@code{report-format="@dfn{native}|@dfn{rrd}"} - Optional parameter to specify
the format of the report file. Defaults to @dfn{native}. Note: if using
@dfn{rrd}, you MUST create the RRDTool file before running bwmd. It is not
created automagically. For the @dfn{native} format @code{report-filename}
would default to @code{/var/bwm_tools/flow_name.dat}, for the @dfn{rrd} format
@code{report-filename} would default to @code{/var/bwm_tools/flow_name.rrd}.
@*
@item
@cindex report-filename
@code{report-filename="@dots{}"} - Optional parameter to specify
the report filename.
@*
@item
@cindex prio-classifier
@code{prio-classifier="@dots{}"} - Optional parameter to specify an automatic
traffic prioritization classifier. This parameter defaults to the @dfn{none}
......
......@@ -128,10 +128,13 @@ struct flow_t
unsigned int accumMs; // Accumulated number of microseconds
struct timeval lastCreditCalc; // Last "timeval" that we calculated additional credit
struct pktStat_t running; // This is the running counter used for stats & logging
// Reporting stuff
int lastDumpTimestamp;
int counterTimeout; // STATIC - length between file logs
int counterRemaining;
int reportFormat;
char *reportFilename;
};
......@@ -157,6 +160,8 @@ struct group_t
int lastDumpTimestamp;
int counterTimeout; // STATIC - length between file logs
int counterRemaining;
int reportFormat;
char *reportFilename;
// Flows we "contain"
GList *flowList;
......
......@@ -37,6 +37,10 @@
#define FILE_VER_CURRENT FILE_VER_0_2
#define FILE_VER_0_2 "BWM_VER-0.2"
// Report formats we can generate
#define REPORT_FORMAT_NATIVE 0
#define REPORT_FORMAT_RRD 1
// File format stuff...
struct aLogFileHeader_t
......@@ -64,9 +68,10 @@ struct aLogFileEntry_t
// Function passed structure for logging
struct reportData_t
{
char ref[MAX_REFLEN];
char *ref;
int counterTimeout;
struct aLogFileEntry_t entry;
char *reportFilename;
};
......
......@@ -23,9 +23,10 @@ GLIB_CFLAGS=@GLIB_CFLAGS@
XML_LIBS=@XML_LIBS@
XML_CFLAGS=@XML_CFLAGS@
LOG_DIR=/var/bwm_tools
lib_LTLIBRARIES = libbwm.la
libbwm_la_SOURCES = xmlConf.c misc.c
libbwm_la_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) $(AM_CFLAGS)
libbwm_la_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(XML_CFLAGS) -DLOG_DIR=\"$(LOG_DIR)\" $(AM_CFLAGS)
libbwm_la_LDFLAGS = $(GLIB_LIBS) $(XML_LIBS) -version-info 1:0:0
......@@ -32,6 +32,7 @@
#include "autoclass.h"
#include "common.h"
#include "flow.h"
#include "report.h"
#include "xmlConf.h"
......@@ -357,13 +358,13 @@ static char *createNATRuleset(char *target, GHashTable *properties)
if (!strcmp(key,"to-src") && !done)
{
// Make sure to-src is only used in SNAT section
if ((strcmp(target, "SNAT") == 0))
if (!strcmp(target, "SNAT"))
{
snprintf(tmp,BUFFER_SIZE,"--to-source %s ",value);
strncat(buffer,tmp,BUFFER_SIZE);
}
else
fprintf(stderr,"ERROR: Tag parameter \"to-src\" is only valid in the <snat> tag, ignoring\n");
fprintf(stderr,"ERROR: Tag parameter \"to-src\" is only valid in the <snat> tag. Ignoring!\n");
done = 1;
}
......@@ -371,13 +372,13 @@ static char *createNATRuleset(char *target, GHashTable *properties)
if (!strcmp(key,"to-dst") && !done)
{
// Make sure to-dst is only used in DNAT section
if ((strcmp(target, "DNAT") == 0))
if (!strcmp(target, "DNAT"))
{
snprintf(tmp,BUFFER_SIZE,"--to-destination %s ",value);
strncat(buffer,tmp,BUFFER_SIZE);
}
else
fprintf(stderr,"ERROR: Tag parameter \"to-dst\" is only valid in the <dnat> tag, ignoring\n");
fprintf(stderr,"ERROR: Tag parameter \"to-dst\" is only valid in the <dnat> tag. Ignoring!\n");
done = 1;
}
......@@ -385,13 +386,13 @@ static char *createNATRuleset(char *target, GHashTable *properties)
if (!strcmp(key,"to-ports") && !done)
{
// Make sure to-ports is only used in DNAT section
if ((strcmp(target, "MASQUERADE") == 0))
if (!strcmp(target, "MASQUERADE"))
{
snprintf(tmp,BUFFER_SIZE,"--to-ports %s ",value);
strncat(buffer,tmp,BUFFER_SIZE);
}
else
fprintf(stderr,"ERROR: Tag parameter \"to-ports\" is only valid in the <masq> tag, ignoring\n");
fprintf(stderr,"ERROR: Tag parameter \"to-ports\" is only valid in the <masq> tag. Ignoring!\n");
done = 1;
}
......@@ -402,7 +403,7 @@ static char *createNATRuleset(char *target, GHashTable *properties)
// Check if we must complain
if (!done)
{
fprintf(stderr,"ERROR: Option \"%s\" no recognized\n",key);
fprintf(stderr,"ERROR: Option \"%s\" not recognized. Ignoring!\n",key);
}
}
......@@ -449,6 +450,10 @@ static char *createTrafficRuleset(GHashTable *properties)
done = 1;
if (!done && !strcmp(key,"report-timeout"))
done = 1;
if (!done && !strcmp(key,"report-format"))
done = 1;
if (!done && !strcmp(key,"report-filename"))
done = 1;
if (!done && !strcmp(key,"prio-classifier"))
done = 1;
if (!done && !strcmp(key,"burst-rate"))
......@@ -467,11 +472,13 @@ static char *createTrafficRuleset(GHashTable *properties)
done = 1;
if (!done && !strcmp(key,"burst-threshold"))
done = 1;
if (!done && !strcmp(key,"flow-mode"))
done = 1;
// Check if we must complain
if (!done)
{
fprintf(stderr,"ERROR: Flow option \"%s\" not recognized\n",key);
fprintf(stderr,"ERROR: Flow option \"%s\" not recognized. Ignoring!\n",key);
}
}
......@@ -629,14 +636,14 @@ GHashTable *getModuleLoadHash(char *filename)
// First check if our name is valid
if (!moduleName)
{
fprintf(stderr,"ERROR: Tag <LOAD /> requires a name\n");
fprintf(stderr,"ERROR: Tag <LOAD /> requires a name. Ignoring!\n");
ok = 0;
}
// Then if we a duplicate
if (ok && g_hash_table_lookup(moduleHash,moduleName))
{
fprintf(stderr,"ERROR: Duplicate module %s in MODULES section\n",moduleName);
fprintf(stderr,"ERROR: Duplicate module %s in MODULES section. Ignoring!\n",moduleName);
ok = 0;
}
......@@ -652,7 +659,7 @@ GHashTable *getModuleLoadHash(char *filename)
}
}
else
fprintf(stderr,"WARNING: Unknown tag %s in MODULES section\n",moduleNode->name);
fprintf(stderr,"WARNING: Unknown tag %s in MODULES section. Ignoring!\n",moduleNode->name);
moduleNode = moduleNode->next;
}
......@@ -666,7 +673,7 @@ GHashTable *getModuleLoadHash(char *filename)
// Check if we knew what the tag was
if (!validTag)
fprintf(stderr,"WARNING: Unknown tag %s in GLOBAL section\n",myNode->name);
fprintf(stderr,"WARNING: Unknown tag %s in GLOBAL section. Ignoring!\n",myNode->name);
// Advance "class"
myNode = myNode->next;
......@@ -698,7 +705,9 @@ static struct flow_t* createFlow(
unsigned long int nfmark,
unsigned char prioClassifier,
float parent_th,
int reportTimeout)
int reportFormat,
int reportTimeout,
char *reportFilename)
{
int i;
struct flow_t *flow = (struct flow_t*) malloc(sizeof(struct flow_t));
......@@ -787,7 +796,34 @@ static struct flow_t* createFlow(
flow->running.pktSize = 0;
flow->running.pktDropped = 0;
flow->running.pktBursted = 0;
// Reporting stuff
flow->reportFormat = reportFormat;
if (!reportFilename)
{
char filename[MAX_NAMELEN];
// Blank filename
memset(&filename,'\0',MAX_NAMELEN);
// Generate our filename
switch (flow->reportFormat)
{
case REPORT_FORMAT_NATIVE:
snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,flow->flowName);
break;
case REPORT_FORMAT_RRD:
snprintf(filename,MAX_NAMELEN,"%s/%s.rrd",LOG_DIR,flow->flowName);
break;
}
flow->reportFilename = strdup(filename);
}
else
flow->reportFilename = strdup(reportFilename);
// Verify everything is ok...
if (flow->statsLen == 0)
flow->statsLen = 10;
......@@ -805,6 +841,7 @@ static struct flow_t* createFlow(
if (flow->maxQueueLen == -1)
{
if (flow->maxRate != 0)
// max rate / 2 (half a second) / 750 (half of MTU)
flow->maxQueueLen = ((flow->burstRate + flow->maxRate) / 2 / 750) * 2; // Seems an OK value for normal use?
else
flow->maxQueueLen = 0;
......@@ -858,7 +895,9 @@ static struct flow_t* createFlow(
static struct group_t *createGroup(
char *groupName,
long int statsLen,
int reportFormat,
int reportTimeout,
char *reportFilename,
GList *flowList)
{
struct group_t *group = (struct group_t *) malloc(sizeof(struct group_t));
......@@ -891,6 +930,31 @@ static struct group_t *createGroup(
// Report stuff
group->counterTimeout = reportTimeout;
group->counterRemaining = reportTimeout;
group->reportFormat = reportFormat;
if (!reportFilename)
{
char filename[MAX_NAMELEN];
// Blank filename
memset(&filename,'\0',MAX_NAMELEN);
// Generate our filename
switch (group->reportFormat)
{
case REPORT_FORMAT_NATIVE:
snprintf(filename,MAX_NAMELEN,"%s/%s.dat",LOG_DIR,group->groupName);
break;
case REPORT_FORMAT_RRD:
snprintf(filename,MAX_NAMELEN,"%s/%s.rrd",LOG_DIR,group->groupName);
break;
}
group->reportFilename = strdup(filename);
}
else
group->reportFilename = strdup(reportFilename);