From owner-svn-src-projects@FreeBSD.ORG Sat Oct 8 02:58:24 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0B147106564A; Sat, 8 Oct 2011 02:58:24 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id ED56A8FC0C; Sat, 8 Oct 2011 02:58:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p982wNFx039046; Sat, 8 Oct 2011 02:58:23 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p982wNHN039039; Sat, 8 Oct 2011 02:58:23 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201110080258.p982wNHN039039@svn.freebsd.org> From: Lawrence Stewart Date: Sat, 8 Oct 2011 02:58:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r226125 - in projects/diffused_head/sys/netinet: . ipfw X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 Oct 2011 02:58:24 -0000 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 #include #include -#include +#include #include #include #include @@ -89,12 +89,18 @@ __FBSDID("$FreeBSD$"); #include #endif +#include +#include + #include /* XXX for in_cksum */ #ifdef MAC #include #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 ***