Index: softflowd.8
===================================================================
RCS file: /var/cvs/softflowd/softflowd.8,v
retrieving revision 1.16
diff -u -p -r1.16 softflowd.8
--- softflowd.8	10 Jan 2005 01:50:07 -0000	1.16
+++ softflowd.8	25 Jan 2006 23:59:34 -0000
@@ -40,6 +40,7 @@
 .Op Fl p Ar pidfile
 .Op Fl c Ar ctl_sock
 .Op Fl L Ar hoplimit
+.Op Fl T Ar track_level
 .Op bpf_program
 .Sh DESCRIPTION
 .Nm
@@ -196,6 +197,24 @@ Sets the IPv4 TTL or the IPv6 hop limit 
 will use the default system TTL when exporting flows to a unicast host.
 When exporting to a multicast group, the default TTL will be 1
 (i.e. link-local).
+.It Fl T Ar track_level
+Specifies what flow elements
+.Nm
+should be used to define a flow.
+.Ar track_level
+may be one of:
+.Dq full
+(track everything in the flow, the default),
+.Dq proto
+(track source and destination addresses and protocol), or
+.Dq ip
+(only track source and destination addresses).
+Selecting either of the latter options will produce flows with less information
+in them (e.g. TCP/UDP ports will not be recorded).
+This will cause flows to be consolidated, reducing the quantity of output 
+and CPU load that
+.Nm
+will place on the system at the cost of some detail.
 .El
 .Pp
 Any further commandline arguments will be concatenated together and 
Index: softflowd.c
===================================================================
RCS file: /var/cvs/softflowd/softflowd.c,v
retrieving revision 1.87
diff -u -p -r1.87 softflowd.c
--- softflowd.c	25 Jan 2006 23:25:04 -0000	1.87
+++ softflowd.c	25 Jan 2006 23:50:06 -0000
@@ -538,6 +538,19 @@ process_packet(struct FLOWTRACK *ft, con
 	if (frag)
 		ft->frag_packets++;
 
+	/* Zero out bits of the flow that aren't relevant to tracking level */
+	switch (ft->track_level) {
+	case TRACK_IP_ONLY:
+		tmp.protocol = 0;
+		/* FALLTHROUGH */
+	case TRACK_IP_PROTO:
+		tmp.port[0] = tmp.port[1] = 0;
+		tmp.tcp_flags[0] = tmp.tcp_flags[1] = 0;
+		/* FALLTHROUGH */
+	case TRACK_FULL:
+		break;
+	}
+
 	/* If a matching flow does not exist, create and insert one */
 	if ((flow = FLOW_FIND(FLOWS, &ft->flows, &tmp)) == NULL) {
 		/* Allocate and fill in the flow */
@@ -1363,6 +1376,8 @@ init_flowtrack(struct FLOWTRACK *ft)
 	FLOW_INIT(&ft->flows);
 	EXPIRY_INIT(&ft->expiries);
 	
+	ft->track_level = TRACK_FULL;
+
 	ft->tcp_timeout = DEFAULT_TCP_TIMEOUT;
 	ft->tcp_rst_timeout = DEFAULT_TCP_RST_TIMEOUT;
 	ft->tcp_fin_timeout = DEFAULT_TCP_FIN_TIMEOUT;
@@ -1407,20 +1422,21 @@ usage(void)
 {
 	fprintf(stderr, "Usage: %s [options] [bpf_program]\n", PROGNAME);
 	fprintf(stderr, "This is %s version %s. Valid commandline options:\n", PROGNAME, PROGVER);
-	fprintf(stderr, "  -i interface    Specify interface to listen on\n");
-	fprintf(stderr, "  -r pcap_file    Specify packet capture file to read\n");
-	fprintf(stderr, "  -t timeout=time Specify named timeout\n");
-	fprintf(stderr, "  -m max_flows    Specify maximum number of flows to track (default %d)\n", DEFAULT_MAX_FLOWS);
-	fprintf(stderr, "  -n host:port    Send Cisco NetFlow(tm)-compatible packets to host:port\n");
-	fprintf(stderr, "  -p pidfile      Record pid in specified file (default: %s)\n", DEFAULT_PIDFILE);
-	fprintf(stderr, "  -c pidfile      Location of control socket (default: %s)\n", DEFAULT_CTLSOCK);
-	fprintf(stderr, "  -v 1|5|9        NetFlow export packet version\n");
-	fprintf(stderr, "  -L hoplimit     Set TTL/hoplimit for export datagrams\n");
-	fprintf(stderr, "  -6              Track IPv6 flows, regardless of whether selected \n"
-	                "                  NetFlow export protocol supports it\n");
-	fprintf(stderr, "  -d              Don't daemonise\n");
-	fprintf(stderr, "  -D              Debug mode: don't daemonise + verbosity + track v6 flows\n");
-	fprintf(stderr, "  -h              Display this help\n");
+	fprintf(stderr, "  -i interface     Specify interface to listen on\n");
+	fprintf(stderr, "  -r pcap_file     Specify packet capture file to read\n");
+	fprintf(stderr, "  -t timeout=time  Specify named timeout\n");
+	fprintf(stderr, "  -m max_flows     Specify maximum number of flows to track (default %d)\n", DEFAULT_MAX_FLOWS);
+	fprintf(stderr, "  -n host:port     Send Cisco NetFlow(tm)-compatible packets to host:port\n");
+	fprintf(stderr, "  -p pidfile       Record pid in specified file (default: %s)\n", DEFAULT_PIDFILE);
+	fprintf(stderr, "  -c pidfile       Location of control socket (default: %s)\n", DEFAULT_CTLSOCK);
+	fprintf(stderr, "  -v 1|5|9         NetFlow export packet version\n");
+	fprintf(stderr, "  -L hoplimit      Set TTL/hoplimit for export datagrams\n");
+	fprintf(stderr, "  -T full|proto|ip Set flow tracking level (default: full)\n");
+	fprintf(stderr, "  -6               Track IPv6 flows, regardless of whether selected \n"
+	                "                   NetFlow export protocol supports it\n");
+	fprintf(stderr, "  -d               Don't daemonise\n");
+	fprintf(stderr, "  -D               Debug mode: don't daemonise + verbosity + track v6 flows\n");
+	fprintf(stderr, "  -h               Display this help\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Valid timeout names and default values:\n");
 	fprintf(stderr, "  tcp     (default %6d)", DEFAULT_TCP_TIMEOUT);
@@ -1661,6 +1677,19 @@ main(int argc, char **argv)
 		case 't':
 			/* Will exit on failure */
 			set_timeout(&flowtrack, optarg); 
+			break;
+		case 'T':
+			if (strcasecmp(optarg, "full") == 0)
+				flowtrack.track_level = TRACK_FULL;
+			else if (strcasecmp(optarg, "proto") == 0)
+				flowtrack.track_level = TRACK_IP_PROTO;
+			else if (strcasecmp(optarg, "ip") == 0)
+				flowtrack.track_level = TRACK_IP_ONLY;
+			else {
+				fprintf(stderr, "Unknown flow tracking level\n");
+				usage();
+				exit(1);
+			}
 			break;
 		case 'L':
 			hoplimit = atoi(optarg);
Index: softflowd.h
===================================================================
RCS file: /var/cvs/softflowd/softflowd.h,v
retrieving revision 1.8
diff -u -p -r1.8 softflowd.h
--- softflowd.h	5 May 2005 03:31:42 -0000	1.8
+++ softflowd.h	25 Jan 2006 23:39:53 -0000
@@ -66,6 +66,11 @@ struct STATISTIC {
 	double min, mean, max;
 };
 
+/* Flow tracking levels */
+#define TRACK_FULL		1	/* src/dst/addr/port/proto 5-tuple */
+#define TRACK_IP_PROTO		2	/* src/dst/proto 3-tuple */
+#define TRACK_IP_ONLY		3	/* src/dst tuple */
+
 /*
  * This structure is the root of the flow tracking system.
  * It holds the root of the tree of active flows and the head of the
@@ -81,7 +86,8 @@ struct FLOWTRACK {
 
 	/* Stuff related to flow export */
 	struct timeval system_boot_time;	/* SysUptime */
-	
+	int track_level;			/* See TRACK_* above */
+
 	/* Flow timeouts */
 	int tcp_timeout;			/* Open TCP connections */
 	int tcp_rst_timeout;			/* TCP flows after RST */
