svn commit: r226125 - in projects/diffused_head/sys/netinet: . ipfw

Lawrence Stewart lstewart at FreeBSD.org
Sat Oct 8 02:58:24 UTC 2011


Author: lstewart
Date: Sat Oct  8 02:58:23 2011
New Revision: 226125
URL: http://svn.freebsd.org/changeset/base/226125

Log:
  Integrate DIFFUSE related hooks and supporting infrastructure into the IPFW
  kernel code. DIFFUSE is called both as part of packet processing (for per-flow
  management, feature calculation and classification) and IPFW related
  configuration (for handling DIFFUSE related rule configuration). The interface
  between IPFW and DIFFUSE was intentionally kept hook based to ensure minimal
  coupling between them. It should therefore be quite simple to integrate DIFFUSE
  with other firewalls in future if desired.
  
  Sponsored by:	FreeBSD Foundation
  Reviewed by:	bz

Added:
  projects/diffused_head/sys/netinet/ip_diffuse.h   (contents, props changed)
  projects/diffused_head/sys/netinet/ipfw/diffuse_common.h   (contents, props changed)
  projects/diffused_head/sys/netinet/ipfw/diffuse_feature.h   (contents, props changed)
  projects/diffused_head/sys/netinet/ipfw/diffuse_private.h   (contents, props changed)
Modified:
  projects/diffused_head/sys/netinet/ip_fw.h
  projects/diffused_head/sys/netinet/ipfw/ip_fw2.c
  projects/diffused_head/sys/netinet/ipfw/ip_fw_private.h
  projects/diffused_head/sys/netinet/ipfw/ip_fw_sockopt.c

Added: projects/diffused_head/sys/netinet/ip_diffuse.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sys/netinet/ip_diffuse.h	Sat Oct  8 02:58:23 2011	(r226125)
@@ -0,0 +1,333 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NETINET_IP_DIFFUSE_H_
+#define _NETINET_IP_DIFFUSE_H_
+
+/*
+ * Definition of the kernel-userland API for DIFFUSE.
+ * Use the same type of interface as dummynet.
+ *
+ * Setsockopt() and getsockopt() pass a batch of objects, each of them starting
+ * with a "struct di_oid" which should fully identify the object and its
+ * relation with others in the sequence.
+ * The first object in each request should have:
+ *	 type = DI_CMD_*, id = DI_API_VERSION.
+ * For other objects, type and subtype specify the object, len indicates the
+ * total length including the header, and 'id' identifies the specific object.
+ */
+
+/* Max feature/classifier name string length (including terminator). */
+#define	DI_MAX_NAME_STR_LEN	8
+
+#define	DI_MAX_MODEL_STR_LEN	256
+
+/* Max action parameter string length (including terminator). */
+#define	DI_MAX_PARAM_STR_LEN	16
+
+/* Max number of features in list. */
+#define	DI_MAX_FEATURES		12
+
+/* Max number of statistics/features used by classifier. */
+#define	DI_MAX_FEATURE_STATS	64
+
+/* Max number of classes/tags used by classifier. */
+#define	DI_MAX_CLASSES		25
+
+/* Char to indicate class numbers. */
+#define	DI_CLASS_NO_CHAR	'#'
+
+#define	DI_API_VERSION		1
+#define	DI_MAX_ID		0x10000
+
+#define	DI_UNIDIRECTIONAL	0x00
+#define	DI_BIDIRECTIONAL	0x01
+
+#define	DI_ACTION_TYPE_UNIDIRECTIONAL	DI_UNIDIRECTIONAL
+#define	DI_ACTION_TYPE_BIDIRECTIONAL	DI_BIDIRECTIONAL
+#define	DI_FEATURE_ALG_UNIDIRECTIONAL	DI_UNIDIRECTIONAL
+#define	DI_FEATURE_ALG_BIDIRECTIONAL	DI_BIDIRECTIONAL
+#define	DI_FLOW_TYPE_UNIDIRECTIONAL	DI_UNIDIRECTIONAL
+#define	DI_FLOW_TYPE_BIDIRECTIONAL	DI_BIDIRECTIONAL
+
+/* Enable debugging output. */
+/* #define	DIFFUSE_DEBUG 1 */
+
+/* Enable more debugging output. */
+/* #define	DIFFUSE_DEBUG2 1 */
+
+/* Debugging support. */
+#ifdef DIFFUSE_DEBUG
+#define	DID(fmt, ...) printf("diffuse: %-10s: " fmt "\n", __func__, \
+    ## __VA_ARGS__)
+#else
+#define	DID(fmt, ...) do {} while (0)
+#endif
+
+#ifdef DIFFUSE_DEBUG2
+#define	DID2(fmt, ...) printf("diffuse: %-10s: " fmt "\n", __func__, \
+    ## __VA_ARGS__)
+#else
+#define	DID2(fmt, ...) do {} while (0)
+#endif
+
+struct di_oid {
+	uint32_t	len;	/* Total obj len including this header
+				 * (16 bit too small for flowtable show). */
+	uint32_t	id;	/* Generic id. */
+	uint16_t	flags;	/* Data we can pass in the oid. */
+	uint8_t		type;	/* Type, e.g. delete or show. */
+	uint8_t		subtype; /* Object, e.g. feature, classifier. */
+};
+
+/*
+ * These values are in the type field of struct di_oid. To preserve the ABI,
+ * never rearrange the list or delete entries with the exception of DI_LAST.
+ */
+enum {
+	DI_NONE = 0,
+
+	DI_CMD_CONFIG,		/* Objects follow. */
+	DI_CMD_DELETE,		/* Subtype + list of entries. */
+	DI_CMD_GET,		/* Subtype + list of entries. */
+	DI_CMD_FLUSH,
+	DI_CMD_ZERO,
+
+	DI_FEATURE,
+	DI_FEATURE_CONFIG,
+	DI_CLASSIFIER,
+	DI_CLASSIFIER_CONFIG,
+	DI_EXPORT,
+	DI_FLOW_TABLE,
+
+	DI_LAST
+};
+
+/* Flow table export. */
+#define	DI_FT_GET_NONE		0x00
+#define	DI_FT_GET_EXPIRED	0x01
+
+struct di_ft_flow_class {
+	char		cname[DI_MAX_NAME_STR_LEN];
+	uint16_t	class;
+};
+
+/* This is the data sent to userspace for a show command. */
+struct di_ft_export_entry {
+	uint16_t	ruleno;
+	uint16_t	setno;
+
+	struct ipfw_flow_id id;	/* (masked) flow id */
+	uint64_t	pcnt;	/* Packet match counter. */
+	uint64_t	bcnt;	/* Byte match counter. */
+	uint32_t	expire;	/* Expire time. */
+	uint32_t	bucket;	/* Which bucket in hash table. */
+	uint32_t	state;	/* State of this rule (typically a
+				 * combination of TCP flags). */
+	uint8_t		fcnt;	/* Number of features. */
+	uint8_t		tcnt;	/* Number of class tags. */
+	uint8_t		final;	/* Equals 1 if final entry. */
+	uint8_t		ftype;	/* Bidirectional vs unidirectional. */
+#if 0
+	/*
+	 * The variable length data component which will appear after the above
+	 * fixed size header is structured as follows:
+	 */
+	uint8_t		fidx[fcnt];	/* Index for each feature in feature
+					 * list. */
+	uint8_t		scnt[fcnt];	/* Number of stats per feature. */
+	uint32_t	fwd_svals[fcnt][scnt];	/* Forward statistics. */
+	uint32_t	bck_svals[fcnt][scnt];	/* Backward statistics. */
+	di_ft_flow_class_t class_tags[tcnt];	/* Class tags. */
+#endif
+};
+
+/* Feature related types. */
+struct di_ctl_feature
+{
+	struct di_oid	oid;
+	char		name[DI_MAX_NAME_STR_LEN];	/* Feature name. */
+	char		mod_name[DI_MAX_NAME_STR_LEN];	/* Algorithm name. */
+};
+
+struct di_feature_stat {
+	uint8_t	fdir;				/* Flow direction. */
+	char	sname[DI_MAX_NAME_STR_LEN];	/* Stat name. */
+	char	fname[DI_MAX_NAME_STR_LEN];	/* Feature name. */
+};
+
+/* Classifier related types. */
+struct di_ctl_classifier
+{
+	struct di_oid	oid;
+	char		name[DI_MAX_NAME_STR_LEN]; /* Classifier name. */
+	char		mod_name[DI_MAX_NAME_STR_LEN]; /* Algorithm name. */
+	uint16_t	confirm;	/* Confirm threshold for
+					 * classification. */
+	uint8_t		ccnt;		/* Number of class names. */
+	uint8_t		fscnt;		/* Number of feature stats. */
+	struct di_feature_stat fstats[]; /* Features. */
+};
+
+/* Exporter related types. */
+struct di_export_config {
+	uint8_t		proto;		/* Fixed to UDP for now. */
+	uint8_t		addr_type;	/* 4=ip4, 6=ip6 */
+	uint16_t	port;		/* Port exporter is listening. */
+	struct in_addr	ip;		/* IPv4 address of exporter. */
+	struct in6_addr	ip6;		/* IPv6 address of exporter. */
+
+	uint16_t	confirm;	/* Need N consistent consecutive
+					 * classifications. */
+	uint16_t	min_batch;
+	uint16_t	max_batch;
+	uint32_t	max_delay;	/* Max ms delay for exporting. */
+	uint32_t	flags;		/* e.g. retransmit. */
+	uint8_t		atype;		/* Uni vs bidirectional action. */
+	char	action[DI_MAX_NAME_STR_LEN]; /* Opaque action for action node. */
+	char	action_param[DI_MAX_PARAM_STR_LEN]; /* Opaque action params. */
+};
+
+struct di_ctl_export
+{
+	struct di_oid		oid;
+	char			name[DI_MAX_NAME_STR_LEN];
+	struct di_export_config	conf;
+};
+
+/* Classification policy defines. */
+#define	DI_MATCH_ONCE		1
+#define	DI_MATCH_SAMPLE_REG	2
+#define	DI_MATCH_SAMPLE_RAND	3
+#define	DI_MATCH_ONCE_CLASS	4
+#define	DI_MATCH_ONCE_EXP	5
+
+/*
+ * Instruction definitions.
+ */
+
+typedef struct _ipfw_insn_features {
+	ipfw_insn	o;
+	uint8_t		ftype;		/* Bidirectional, unidirectional, ... */
+	uint8_t		fcnt;		/* Number of features. */
+	uint16_t	sample_int;	/* Regular sampling interval. */
+	uint32_t	sample_prob;	/* Random sampling. */
+	char		fnames[DI_MAX_FEATURES][DI_MAX_NAME_STR_LEN];
+	struct di_feature *fptrs[DI_MAX_FEATURES]; /* Feature ptrs. */
+} ipfw_insn_features;
+
+/* Feature match instruction. */
+#define	DI_MATCH_DIR_NONE	0x00
+#define	DI_MATCH_DIR_FWD	0x01
+#define	DI_MATCH_DIR_BCK	0x02
+
+enum di_comp_types {
+	DI_COMP_LT = 0,
+	DI_COMP_LE,
+	DI_COMP_EQ,
+	DI_COMP_GE,
+	DI_COMP_GT
+};
+
+typedef struct _ipfw_insn_feature_match {
+	ipfw_insn		o;
+	struct di_feature	*fptr;	/* Feature ptr. */
+	int32_t			thresh; /* Value we compare against. */
+	uint8_t			sidx;	/* Stat index. */
+	uint8_t			fdir;	/* Feature direction. */
+	uint8_t			comp;	/* Comparison type. */
+	char	sname[DI_MAX_NAME_STR_LEN];	/* Feature statistic. */
+	char	fname[DI_MAX_NAME_STR_LEN];	/* Feature name. */
+} ipfw_insn_feature_match;
+
+/* Match if class instruction. */
+
+/* Max number of classes in match-if. */
+#define	DI_MAX_MATCH_CLASSES 1
+
+typedef struct _ipfw_insn_match_if_class {
+	ipfw_insn	o;
+	uint8_t		mcnt; /* Number of classes that match. */
+	uint8_t	match_classes[DI_MAX_MATCH_CLASSES]; /* Class number of matching
+						      * classes. */
+	struct di_classifier *clptr;		/* Classifier ptr. */
+	char	cname[DI_MAX_NAME_STR_LEN];	/* Classifier name. */
+	char	clnames[][DI_MAX_NAME_STR_LEN];	/* Class names. */
+} ipfw_insn_match_if_class;
+
+/* Tag using ipfw tags. */
+typedef struct _ipfw_insn_class_tags {
+	ipfw_insn		o;
+	char			cname[DI_MAX_NAME_STR_LEN]; /* Classifier
+							     * name. */
+	struct di_classifier	*clptr; /* Classifier ptr. */
+	uint8_t			tcnt;	/* Number of tags
+					 * (<= number of classes). */
+	uint16_t		tags[];	/* One tag per class. */
+} ipfw_insn_class_tags;
+
+/* Classifier action instruction. */
+typedef struct _ipfw_insn_ml_classify {
+	ipfw_insn		o;
+	char			cname[DI_MAX_NAME_STR_LEN]; /* Classifier
+							     * name. */
+	struct di_classifier	*clptr; /* Classifier ptr. */
+	struct _ipfw_insn_class_tags *tcmd; /* Link to optional tag command. */
+} ipfw_insn_ml_classify;
+
+/* Export action instruction. */
+typedef struct _ipfw_insn_export {
+	ipfw_insn		o;
+	char			ename[DI_MAX_NAME_STR_LEN]; /* Export name. */
+	struct di_export	*eptr; /* Export instance ptr. */
+} ipfw_insn_export;
+
+/*
+ * Stores all the persistent data required across multiple calls to
+ * diffuse_chk_pkt().
+ */
+struct di_chk_pkt_args {
+	struct di_ft_entry	*q;
+	ipfw_insn_class_tags	*tcmd;
+	int			no_class;
+};
+
+/*
+ * Stores all the persistent data required (currently none) across multiple
+ * calls to diffuse_chk_rule_cmd().
+ */
+struct di_chk_rule_cmd_args {
+};
+
+#endif /* _NETINET_IP_DIFFUSE_H_ */

Modified: projects/diffused_head/sys/netinet/ip_fw.h
==============================================================================
--- projects/diffused_head/sys/netinet/ip_fw.h	Sat Oct  8 00:01:17 2011	(r226124)
+++ projects/diffused_head/sys/netinet/ip_fw.h	Sat Oct  8 02:58:23 2011	(r226125)
@@ -205,6 +205,28 @@ enum ipfw_opcodes {		/* arguments (4 byt
 
 	O_FORWARD_IP6,		/* fwd sockaddr_in6             */
 
+	/*
+	 * Actions for DIFFUSE.
+	 */
+	O_DI_FEATURES,		/* feature list */
+	O_DI_FEATURES_IMPLICIT,	/* feature list (implicitely configured) */
+	O_DI_FLOW_TABLE,	/* check flow table and update features */
+	O_DI_FEATURE_MATCH,	/* feature match */
+	O_DI_AFTER_EACH_RULE,	/* pseudo opcode, used after match for rule was
+				   decided */
+	O_DI_CLASS_TAGS,	/* tags used for classified packets */
+	O_DI_ML_CLASSIFY,	/* classify sub flow (action) */
+	O_DI_ML_CLASSIFY_IMPLICIT, /* classify sub flow
+				     (implicit -> non-action) */
+	O_DI_MATCH_IF_CLASS,	/* match if classified as class x */
+	O_DI_EXPORT,		/* export rules */
+	O_DI_BEFORE_ALL_RULES,	/* pseudo opcode, before matching rules,
+				   _inside_ lock */
+	O_DI_AFTER_ALL_RULES,	/* pseudo opcode, after all rules, _outside_
+				   lock */
+	O_DI_BEFORE_RULE_CHK,	/* pseudo opcode, called before rule checks */
+	O_DI_AFTER_RULE_CHK,	/* pseudo opcode, called after rule checks */
+
 	O_LAST_OPCODE		/* not an opcode!		*/
 };
 

Added: projects/diffused_head/sys/netinet/ipfw/diffuse_common.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sys/netinet/ipfw/diffuse_common.h	Sat Oct  8 02:58:23 2011	(r226125)
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NETINET_IPFW_DIFFUSE_COMMON_H_
+#define _NETINET_IPFW_DIFFUSE_COMMON_H_
+
+/* MSVC does not support designated initializers so we need this ugly macro. */
+#ifdef _WIN32
+#define	_FI(fld)
+#else
+#define	_FI(fld) fld
+#endif
+
+/* Feature or classifier instance data. */
+struct di_cdata {
+	void	*conf;	/* Instance configuration ptr. */
+};
+
+/* Flow data. */
+struct di_fdata {
+	void	*data;	/* Work data ptr. */
+	int32_t	*stats;	/* Stats ptr. */
+};
+
+/*
+ * Fast fixed point division with rounding for dividing by a number of 2.
+ * a is the divident and b is the power of the divisor.
+ */
+static inline uint64_t
+fixp_div(uint64_t a, int b)
+{
+	uint64_t q, r;
+
+	if (b <= 0)
+		return (a);
+
+	q = a >> b;
+	r = a & (b - 1);
+	if ((r << 1) >= ((uint64_t)1 << b))
+		return (q + 1);
+	else
+		return (q);
+}
+
+static inline uint32_t
+fixp_sqrt(uint64_t x)
+{
+	uint64_t rem_hi, rem_lo, test_div;
+	uint32_t root;
+	int count;
+
+	rem_hi = 0;
+	rem_lo = x;
+	root = 0;
+	count = 31;
+
+	do {
+		rem_hi = (rem_hi << 2) | (rem_lo >> 62);
+		rem_lo <<= 2; /* Get 2 bits of arg. */
+		root <<= 1; /* Get ready for the next bit in the root. */
+		test_div = (root << 1) + 1; /* Test radical. */
+		if (rem_hi >= test_div) {
+			rem_hi -= test_div;
+			root++;
+		}
+	} while (count-- != 0);
+
+	return (root);
+}
+
+/* Similar to timevalsub, but ensures the timeval returned will be >= 0. */
+static inline struct timeval
+tv_sub0(struct timeval *num, struct timeval *sub)
+{
+	struct timeval rv;
+
+	rv.tv_sec = num->tv_sec - sub->tv_sec;
+	rv.tv_usec = num->tv_usec - sub->tv_usec;
+
+	if (rv.tv_usec < 0) {
+		rv.tv_usec += 1000000;
+		rv.tv_sec--;
+	}
+	if (rv.tv_sec < 0) {
+		rv.tv_sec = 0;
+		rv.tv_usec = 0;
+	}
+
+	return (rv);
+}
+
+#endif /* _NETINET_IPFW_DIFFUSE_COMMON_H_ */

Added: projects/diffused_head/sys/netinet/ipfw/diffuse_feature.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sys/netinet/ipfw/diffuse_feature.h	Sat Oct  8 02:58:23 2011	(r226125)
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * DIFFUSE feature computation module parts.
+ */
+
+#ifndef _NETINET_IPFW_DIFFUSE_FEATURE_H_
+#define _NETINET_IPFW_DIFFUSE_FEATURE_H_
+
+struct di_cdata;
+struct di_fdata;
+struct mbuf;
+
+/*
+ * Descriptor for a feature. A feature is actually a list of related
+ * statistics. Contains all function pointers for a given feature. This is
+ * typically created when a module is loaded, and stored in a global list of
+ * feature instances.
+ */
+struct di_feature_alg {
+	const char	*name;		/* Feature name. */
+	const int	type;		/* Unidirectional or bidirectional. */
+	volatile int	ref_count;	/* Number of instances in the system */
+
+	/*
+	 * Init instance.
+	 * param1: pointer to instance config
+	 * param2: config from userspace
+	 * return: non-zero on error
+	 */
+	int (*init_instance)(struct di_cdata *, struct di_oid *);
+
+	/*
+	 * Destroy instance.
+	 * param1: pointer to instance config
+	 * return: non-zero on error
+	 */
+	int (*destroy_instance)(struct di_cdata *);
+
+	/*
+	 * Init state for flow.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * return: non-zero on error
+	 */
+	int (*init_stats)(struct di_cdata *, struct di_fdata *);
+
+	/*
+	 * Destroy flow state.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * return: non-zero on error
+	 */
+	int (*destroy_stats)(struct di_cdata *, struct di_fdata *);
+
+	/*
+	 * Update feature, called for each packet.
+	 * pre: the packet is an IPv4 or IPv6 packet and the caller has done a
+	 *      pullup on the mbuf prior to calling.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * param3: packet (mbuf chain)
+	 * param4: protocol on top of IP
+	 * param5: pointer to upper layer protocol (e.g. UDP, TCP)
+	 * param6: direction of the packet (MATCH_FORWARD or MATCH_REVERSE)
+	 * return: non-zero on error
+	 */
+	int (*update_stats)(struct di_cdata *, struct di_fdata *, struct mbuf *,
+	    int proto, void *ulp, int dir);
+
+	/*
+	 * Reset stats.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * return: non-zero on error
+	 */
+	int (*reset_stats)(struct di_cdata *, struct di_fdata *);
+
+	/*
+	 * Get feature statistics.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * param3: pointer to stats
+	 * return: non-zero on error
+	 */
+        int (*get_stats)(struct di_cdata *, struct di_fdata *, int32_t **);
+
+	/*
+	 * Get one feature statistics.
+	 * param1: pointer to instance config
+	 * param2: pointer to flow work and stats data
+	 * param3: which one
+	 * param4: pointer to stat
+	 * return: non-zero on error
+	 */
+	int (*get_stat)(struct di_cdata *, struct di_fdata *, int, int32_t *);
+
+	/*
+	 * Get names of statistics.
+	 * param1: array of names
+	 * return: non-zero on error
+	 */
+	int (*get_stat_names)(char **[]);
+
+	/*
+	 * Get configuration data.
+	 * param1: pointer to instance config
+	 * param2: pointer to configuration
+	 * param3: only compute size (if 1)
+	 * return: non-zero on error
+	 */
+	int (*get_conf)(struct di_cdata *, struct di_oid *, int);
+
+	SLIST_ENTRY(di_feature_alg) next; /* Next feature in the list. */
+};
+
+#endif /* _NETINET_IPFW_DIFFUSE_FEATURE_H_ */

Added: projects/diffused_head/sys/netinet/ipfw/diffuse_private.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/diffused_head/sys/netinet/ipfw/diffuse_private.h	Sat Oct  8 02:58:23 2011	(r226125)
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 2010-2011
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Sebastian Zander, made
+ * possible in part by a gift from The Cisco University Research Program Fund, a
+ * corporate advised fund of Silicon Valley Community Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Internal stuff for DIFFUSE.
+ */
+
+#ifndef _NETINET_IPFW_DIFFUSE_PRIVATE_H_
+#define _NETINET_IPFW_DIFFUSE_PRIVATE_H_
+
+/*
+ * For platforms that do not have SYSCTL support, we wrap the SYSCTL_* into a
+ * function (one per file) to collect the values into an array at module
+ * initialization. The wrapping macros, SYSBEGIN() and SYSEND, are empty in the
+ * default case.
+ */
+#ifndef SYSBEGIN
+#define	SYSBEGIN(x)
+#endif
+#ifndef SYSEND
+#define	SYSEND
+#endif
+
+MALLOC_DECLARE(M_DIFFUSE);
+
+#define	DI_LOCK_INIT()		rw_init(&di_conf.mtx, "diffuse main lock")
+#define	DI_LOCK_DESTROY()	rw_destroy(&di_conf.mtx)
+#define	DI_RLOCK()		rw_rlock(&di_conf.mtx)
+#define	DI_WLOCK()		rw_wlock(&di_conf.mtx)
+#define	DI_UNLOCK()		rw_unlock(&di_conf.mtx)
+#define	DI_RLOCK_ASSERT()	rw_assert(&di_conf.mtx, RA_RLOCKED)
+#define	DI_WLOCK_ASSERT()	rw_assert(&di_conf.mtx, RA_WLOCKED)
+#define	DI_LOCK_ASSERT()	rw_assert(&di_conf.mtx, RA_LOCKED)
+
+SLIST_HEAD(di_feature_alg_head, di_feature_alg);
+LIST_HEAD(di_features_head, di_feature);
+SLIST_HEAD(di_classifier_alg_head, di_classifier_alg);
+LIST_HEAD(di_classifier_head, di_classifier);
+LIST_HEAD(di_export_head, di_export);
+/* One (big) list of export records (fifo) - double linked for fast removals. */
+TAILQ_HEAD(di_export_rec_head, di_export_rec);
+
+/*
+ * Configuration and global data for DIFFUSE.
+ *
+ * When a configuration is modified from userland, 'id' is incremented
+ * so we can use the value to check for stale pointers.
+ */
+struct di_parms {
+	uint32_t	id;			/* Configuration version. */
+
+	int		debug;
+	int		init_done;
+
+	int		an_rule_removal;	/* Explicit remove messages or timeouts. */
+
+	/* Counters of objects -- used for reporting space. */
+	int		feature_count;		/* Number of feature instances. */
+	int		classifier_count;	/* Number of classifier instances. */
+	int		export_count;		/* Number of exports. */
+	int		export_rec_count;	/* Number of exports recs. */
+
+	/* List of feature algorithms. */
+	struct di_feature_alg_head	feature_list;
+	/* List of feature instances. */
+	struct di_features_head		feature_inst_list;
+	
+	/* List of classifier algorithms. */
+	struct di_classifier_alg_head	classifier_list;
+	/* List of classifier instances. */
+	struct di_classifier_head	classifier_inst_list;
+
+	/* List of export instances. */
+	struct di_export_head		export_list;
+
+	/* List of export records. */
+	struct di_export_rec_head	export_rec_list;
+
+#ifdef _KERNEL
+	/*
+	 * This file is normally used in the kernel, unless we do some userland
+	 * tests, in which case we do not need a mtx.
+	 */
+#if defined( __linux__ ) || defined( _WIN32 )
+	spinlock_t mtx;
+#else
+	struct rwlock mtx;
+#endif
+#endif /* _KERNEL */
+};
+
+/* List of flow table timeouts. */
+struct di_to_entry {
+	struct di_ft_entry	*flow;
+	LIST_ENTRY(di_to_entry)	next;
+};
+
+typedef struct di_export_rec *(*di_to_handler_fn_t)
+    (struct di_ft_entry *q, struct di_export *, int);
+
+/* List of flow classes. */
+struct di_flow_class {
+	char		cname[DI_MAX_NAME_STR_LEN];	/* Classifier name. */
+	uint16_t	class;				/* Class ID. */
+	int16_t		prev_class; /* Prev class id, -1 if no previous class. */
+	uint16_t	confirm; /* How many identical consecutive classifications. */
+	SLIST_ENTRY(di_flow_class) next;
+};
+
+SLIST_HEAD(di_flow_class_head, di_flow_class);
+
+/* List of exporters. */
+struct di_exp {
+	struct di_export *ex;
+	SLIST_ENTRY(di_exp) next;
+};
+
+SLIST_HEAD(di_exp_list_head, di_exp);
+
+/* Flow table entry. */
+struct di_ft_entry {
+	struct di_ft_entry	*next;	/* Linked list of rules. */
+	struct ip_fw		*rule;	/* Used to pass up the rule number. */
+	struct ipfw_flow_id	id;	/* (masked) flow id. */
+	uint64_t		pcnt;	/* Packet match counter. */
+	uint64_t		bcnt;	/* Byte match counter. */
+	uint32_t		expire;	/* Expire time. */
+	uint32_t		bucket;	/* Which bucket in hash table. */
+	uint32_t		state;	/* State of this rule (typically a
+					 * combination of TCP flags). */
+	uint8_t			ftype;	/* Bidir vs unidir, match limiting. */
+	uint8_t			fcnt;	/* Number of features. */
+	uint8_t			tcnt;	/* Number of class tags. */
+	uint16_t		sample_int;	/* Sample interval. */
+	uint32_t		sample_prob;	/* Sample probability. */
+	uint16_t		pkts_after_last; /* Match limiting: packets n */
+	struct di_feature	*features[DI_MAX_FEATURES]; /* Feature ptrs. */
+	struct di_fdata		fwd_data[DI_MAX_FEATURES];
+	struct di_fdata		bck_data[DI_MAX_FEATURES];
+	struct timeval		ex_time;	/* Time last exported. */
+	struct di_flow_class_head	flow_classes;	/* List of class tags. */
+	struct di_to_entry	*to;		/* Timeout list entry ptr. */
+	struct di_exp_list_head	ex_list;	/* Ptrs to exporters. */
+};
+
+/* Export data record. */
+struct di_export_rec {
+	char ename[DI_MAX_NAME_STR_LEN]; /* Generating export instance. */
+	struct ipfw_flow_id id;	/* IPs, ports. */
+	struct timeval	time;	/* Generation time. */
+	struct timeval	no_earlier; /* Don't send before. */
+	/* XXX: Flow label, TOS missing */
+	uint8_t		mtype;		/* Message type. */
+	uint8_t		fcnt;		/* Number of features. */
+	uint8_t		tcnt; 		/* Number of tags. */
+	uint8_t		ftype;		/* Bidir vs unidir. */
+	uint8_t		match_dir;
+	uint8_t		action_dir;	/* Bidir vs unidir. */
+	uint8_t		ttype;		/* Timeout type. */
+	uint16_t	tval;		/* Timeout value in seconds. */
+	uint32_t	pcnt;		/* Flow packet counter. */
+	uint64_t	bcnt;		/* Flow byte counter. */
+	struct di_ft_flow_class class_tags[DI_MAX_CLASSES];
+	char action[DI_MAX_NAME_STR_LEN];
+	char act_params[DI_MAX_PARAM_STR_LEN];
+	struct di_ft_entry *ft_rec; /* Flow entry ptr. */
+	TAILQ_ENTRY(di_export_rec) next;
+};
+
+/* Feature. */
+struct di_feature {
+	char		*name; /* Instance name. */
+	volatile int	ref_count; /* Num rules referencing feature. */
+	struct di_cdata	conf;
+	struct di_feature_alg *alg; /* Feature algorithm ptr. */
+	LIST_ENTRY(di_feature) next; /* Next in list. */
+};
+
+/* Classifier. */
+struct di_feature_stat_ptr {
+	struct di_feature	*fptr;	/* Pointer to feature. */
+	uint8_t			sidx;	/* Statistic index. */
+};
+
+struct di_classifier {
+	char		*name;	/* Instance name. */
+	volatile int	ref_count; /* Num rules referencing classifier. */
+	struct di_classifier_alg *alg; /* Classifier algorithm ptr. */
+	struct di_cdata	conf;
+	int32_t		id;	/* Unique id used for tag cookie. */
+	uint16_t	*tags;
+	uint16_t	confirm; /* How many identical consecutive
+				  * classifications. */
+	uint8_t		fscnt;	/* Number of features. */
+	uint8_t		ccnt;	/* Number of classes. */
+	uint8_t		tcnt;	/* Tag count (ipfw tags). */
+	struct di_feature_stat	*fstats; /* Features + classes. */
+	struct di_feature_stat_ptr *fstats_ptr; /* Feature indices. */
+	LIST_ENTRY(di_classifier) next;  /* Next in list. */
+};
+
+/* Export. */
+struct di_export {
+	char			*name;	/* Instance name. */
+	volatile int		ref_count; /* Num rules referencing exporter. */
+	struct di_export_config	conf;	/* Config from userspace. */
+	struct socket		*sock;	/* Protocol socket. */
+	uint32_t		seq_no;	/* Sequence number. */
+	struct timeval		last_pkt_time; /* Most recently sent packet. */
+	struct mbuf		*mh;	/* First mbuf of export packet chain. */
+	struct mbuf		*mt;	/* Last mbuf of export packet chain. */
+	LIST_ENTRY(di_export)	next;	/* Next in list. */
+};
+
+/* For tagging mbufs (packets) with classes. */
+#define	MTAG_DIFFUSE_CLASS 1243750889
+
+struct di_class_tag {
+	struct m_tag	tag;
+	int		class;
+	int		prev_class;
+	int		confirm;
+};
+
+/* Global configuration. */
+extern struct di_parms di_conf;
+
+/* Function prototypes. */
+
+/* ip_diffuse.c  */
+int diffuse_get_feature_idx(const char *name);
+
+/* diffuse_flowtable.c */
+void diffuse_ft_attach(void);
+void diffuse_ft_detach(void);
+void diffuse_ft_init(void);
+void diffuse_ft_uninit(void);
+int diffuse_ft_len(int expired);
+struct di_ft_entry * diffuse_ft_install_state(struct ip_fw *rule,
+    ipfw_insn_features *cmd, struct ip_fw_args *args, void *ulp, int pktlen);
+struct di_ft_entry * diffuse_ft_lookup_entry(struct ipfw_flow_id *pkt,
+    struct ip_fw_args *args, void *ulp, int pktlen, int *match_direction);
+void diffuse_get_ft(char **pbp, const char *ep, int expired);
+int diffuse_ft_entries(void);
+void diffuse_ft_remove_entries(struct ip_fw *rule);
+void diffuse_ft_add_class(struct di_ft_entry *e, char *cname, int class,
+    int *prev_class, int *confirm);
+int diffuse_ft_get_class(struct di_ft_entry *e, char *cname, int *prev_class,
+    int *confirm);
+void diffuse_ft_remove_class(struct di_ft_entry *e, char *cname);
+void diffuse_ft_unlock(void);
+void diffuse_ft_check_timeouts(di_to_handler_fn_t f);
+void diffuse_ft_add_export(struct di_ft_entry *e,
+    struct di_export_rec *ex_rec, struct di_export *nex);
+void diffuse_ft_flush(int reset_counters_only);
+int diffuse_ft_get_stat(struct di_ft_entry *q, int fdir,
+    struct di_feature *fptr, int sidx, int32_t *val);
+int diffuse_ft_get_stats(struct di_ft_entry *q, int fscnt,
+    struct di_feature_stat *fstats, struct di_feature_stat_ptr *fstats_ptr,
+    int32_t *fvec);
+int diffuse_ft_do_export(struct di_ft_entry *q, uint16_t confirm);
+int diffuse_ft_update_features(struct di_ft_entry *q,
+    ipfw_insn_features *cmd, struct ip_fw_args *args, void *ulp);
+
+/* diffuse_export.c */
+int diffuse_export_remove_recs(char *ename);
+struct di_export_rec * diffuse_export_add_rec(struct di_ft_entry *q,
+    struct di_export *ex, int add_command);
+struct socket *diffuse_export_open(struct di_export_config *conf);
+int diffuse_export_send(struct di_export *ex);
+void diffuse_export_close(struct socket *s);
+void diffuse_export_init(void);
+void diffuse_export_uninit(void);
+void diffuse_export_prune_recs(void);
+
+#endif /* _NETINET_IPFW_DIFFUSE_PRIVATE_H_ */

Modified: projects/diffused_head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- projects/diffused_head/sys/netinet/ipfw/ip_fw2.c	Sat Oct  8 00:01:17 2011	(r226124)
+++ projects/diffused_head/sys/netinet/ipfw/ip_fw2.c	Sat Oct  8 02:58:23 2011	(r226125)
@@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
 #include <netinet/ip_fw.h>
-#include <netinet/ipfw/ip_fw_private.h>
+#include <netinet/ip_diffuse.h>
 #include <netinet/ip_carp.h>
 #include <netinet/pim.h>
 #include <netinet/tcp_var.h>
@@ -89,12 +89,18 @@ __FBSDID("$FreeBSD$");
 #include <netinet6/ip6_var.h>
 #endif
 
+#include <netinet/ipfw/diffuse_common.h>
+#include <netinet/ipfw/ip_fw_private.h>
+
 #include <machine/in_cksum.h>	/* XXX for in_cksum */
 
 #ifdef MAC
 #include <security/mac/mac_framework.h>
 #endif
 
+/* DIFFUSE */
+ipfw_ext_t *ipfw_diffuse_ext = NULL;
+
 /*
  * static variables followed by global ones.
  * All ipfw global variables are here.
@@ -914,6 +920,8 @@ ipfw_chk(struct ip_fw_args *args)
 	 *	MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL)
 	 */
 	int dyn_dir = MATCH_UNKNOWN;
+	/* For DIFFUSE features. */
+	int flow_dir = MATCH_UNKNOWN;
 	ipfw_dyn_rule *q = NULL;
 	struct ip_fw_chain *chain = &V_layer3_chain;
 
@@ -935,6 +943,12 @@ ipfw_chk(struct ip_fw_args *args)
 
 	int done = 0;		/* flag to exit the outer loop */
 
+	/*
+	 * DIFFUSE data container required for persistent storage between

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list