SOURCES (LINUX_2_6): nf-hipac-0.9.1.patch (NEW) - high performance...

pluto pluto at pld-linux.org
Thu Oct 13 20:01:49 CEST 2005


Author: pluto                        Date: Thu Oct 13 18:01:49 2005 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- high performance packet classification.
  HiPAC is a novel framework for packet classification which uses
  an advanced algorithm to reduce the number of memory lookups per packet.
  it is ideal for environments involving large rulesets and/or high 
  bandwidth networks.

---- Files affected:
SOURCES:
   nf-hipac-0.9.1.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/nf-hipac-0.9.1.patch
diff -u /dev/null SOURCES/nf-hipac-0.9.1.patch:1.1.2.1
--- /dev/null	Thu Oct 13 20:01:49 2005
+++ SOURCES/nf-hipac-0.9.1.patch	Thu Oct 13 20:01:44 2005
@@ -0,0 +1,15663 @@
+ include/linux/netfilter_ipv4/ip_tables.h      |    2 
+ net/ipv4/netfilter/Kconfig                    |   35 
+ net/ipv4/netfilter/Makefile                   |    3 
+ net/ipv4/netfilter/ip_tables.c                |   12 
+ net/ipv4/netfilter/nf-hipac/Makefile          |   33 
+ net/ipv4/netfilter/nf-hipac/dimtree.c         | 4307 ++++++++++++++++++++++++++
+ net/ipv4/netfilter/nf-hipac/dimtree.h         |  280 +
+ net/ipv4/netfilter/nf-hipac/global.c          |  964 +++++
+ net/ipv4/netfilter/nf-hipac/global.h          |  387 ++
+ net/ipv4/netfilter/nf-hipac/hipac.c           | 3750 ++++++++++++++++++++++
+ net/ipv4/netfilter/nf-hipac/hipac.h           |  623 +++
+ net/ipv4/netfilter/nf-hipac/ihash.c           |  463 ++
+ net/ipv4/netfilter/nf-hipac/ihash.h           |  285 +
+ net/ipv4/netfilter/nf-hipac/mode.h            |  240 +
+ net/ipv4/netfilter/nf-hipac/nf_hipac_cthelp.c |   49 
+ net/ipv4/netfilter/nf-hipac/nfhp_com.h        |  330 +
+ net/ipv4/netfilter/nf-hipac/nfhp_dev.c        |  308 +
+ net/ipv4/netfilter/nf-hipac/nfhp_dev.h        |   66 
+ net/ipv4/netfilter/nf-hipac/nfhp_mod.c        | 1734 ++++++++++
+ net/ipv4/netfilter/nf-hipac/nfhp_mod.h        |   47 
+ net/ipv4/netfilter/nf-hipac/nfhp_proc.c       |  888 +++++
+ net/ipv4/netfilter/nf-hipac/nfhp_proc.h       |   24 
+ net/ipv4/netfilter/nf-hipac/rlp.c             |  537 +++
+ net/ipv4/netfilter/nf-hipac/rlp.h             |  142 
+ 24 files changed, 15509 insertions(+)
+
+diff -purN --exclude=.svn 2.6.13/include/linux/netfilter_ipv4/ip_tables.h 2.6.13-patched/include/linux/netfilter_ipv4/ip_tables.h
+--- 2.6.13/include/linux/netfilter_ipv4/ip_tables.h	2005-09-10 14:50:33.000000000 +0200
++++ 2.6.13-patched/include/linux/netfilter_ipv4/ip_tables.h	2005-09-10 14:50:33.000000000 +0200
+@@ -455,6 +455,8 @@ struct ipt_table
+ 
+ /* net/sched/ipt.c: Gimme access to your targets!  Gets target->me. */
+ extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
++/* Gimme access to your matches too! */
++extern struct ipt_match *ipt_find_match(const char *name, u8 revision);
+ 
+ /* Standard entry. */
+ struct ipt_standard
+diff -purN --exclude=.svn 2.6.13/net/ipv4/netfilter/Kconfig 2.6.13-patched/net/ipv4/netfilter/Kconfig
+--- 2.6.13/net/ipv4/netfilter/Kconfig	2005-09-10 14:50:33.000000000 +0200
++++ 2.6.13-patched/net/ipv4/netfilter/Kconfig	2005-09-10 14:50:34.000000000 +0200
+@@ -663,7 +663,42 @@ config IP_NF_TARGET_NOTRACK
+ 	  If you want to compile it as a module, say M here and read
+ 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+ 
++config IP_NF_HIPAC
++	tristate  'nf-HiPAC support (High Performance Packet Classification)'
++	depends on IP_NF_IPTABLES
++	help
++	  nf-HiPAC is a high performance packet classification framework on
++	  top of netfilter. It is based on a novel classification algorithm
++	  that is very much superior to the linear classication algorithm
++	  implemented by iptables. It provides highly efficient packet
++	  matching which is especially useful when large rulesets and/or high
++	  bandwidth networks are involved. Ruleset updates are submitted
++	  dynamically to the kernel via netlink on a per rule basis.
++	  In addition to its native matches (e.g. ip, proto, port match)
++	  nf-HiPAC allows the usage of iptables matches and targets and thus
++	  provides the same flexibility as iptables. Furthermore the semantics
++	  and construction of a ruleset is identical to the iptables way so
++	  that the internal representation is completely transparent to the
++	  user.
++	  Basically, you can think of nf-HiPAC as an alternative, optimized
++	  iptables filter table. Note that it cannot be used for packet
++	  mangling or NAT but you can still adopt iptables' mangle or nat
++	  table for that purpose since nf-HiPAC and iptables can be used
++	  together at the same time.
++
++config IP_NF_HIPAC_SINGLE_PATH
++	bool 'Single path optimization'
++	depends on IP_NF_HIPAC
++	help
++	   This optimization will significantly improve the performance of
++	   nf-HiPAC but may lead to an unacceptable memory usage. Whether memory
++	   consumption becomes a problem depends on your rule set. You can
++	   monitor the memory used by NF-HIPAC via /proc/net/nf-hipac/info.
++	   In almost all scenarios the performance will already be more than good
++	   enough without this optimization. 
+ 
++	   If unsure, say N.
++				    
+ # ARP tables
+ config IP_NF_ARPTABLES
+ 	tristate "ARP tables support"
+diff -purN --exclude=.svn 2.6.13/net/ipv4/netfilter/Makefile 2.6.13-patched/net/ipv4/netfilter/Makefile
+--- 2.6.13/net/ipv4/netfilter/Makefile	2005-09-10 14:50:33.000000000 +0200
++++ 2.6.13-patched/net/ipv4/netfilter/Makefile	2005-09-10 14:50:34.000000000 +0200
+@@ -79,6 +79,9 @@ obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt
+ obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
+ obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
+ 
++# nf-hipac/Makefile
++obj-$(CONFIG_IP_NF_HIPAC) += nf-hipac/
++
+ # generic ARP tables
+ obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
+ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
+diff -purN --exclude=.svn 2.6.13/net/ipv4/netfilter/ip_tables.c 2.6.13-patched/net/ipv4/netfilter/ip_tables.c
+--- 2.6.13/net/ipv4/netfilter/ip_tables.c	2005-09-10 14:50:33.000000000 +0200
++++ 2.6.13-patched/net/ipv4/netfilter/ip_tables.c	2005-09-10 14:50:34.000000000 +0200
+@@ -453,6 +453,17 @@ static inline struct ipt_match *find_mat
+ 	return ERR_PTR(err);
+ }
+ 
++struct ipt_match *ipt_find_match(const char *name, u8 revision)
++{
++	struct ipt_match *match;
++
++	match = try_then_request_module(find_match(name, revision),
++					"ipt_%s", name);
++	if (IS_ERR(match) || !match)
++		return NULL;
++	return match;
++}
++
+ /* Find target, grabs ref.  Returns ERR_PTR() on error. */
+ static inline struct ipt_target *find_target(const char *name, u8 revision)
+ {
+@@ -1954,6 +1965,7 @@ EXPORT_SYMBOL(ipt_register_table);
+ EXPORT_SYMBOL(ipt_unregister_table);
+ EXPORT_SYMBOL(ipt_register_match);
+ EXPORT_SYMBOL(ipt_unregister_match);
++EXPORT_SYMBOL(ipt_find_match);
+ EXPORT_SYMBOL(ipt_do_table);
+ EXPORT_SYMBOL(ipt_register_target);
+ EXPORT_SYMBOL(ipt_unregister_target);
+diff -purN --exclude=.svn 2.6.13/net/ipv4/netfilter/nf-hipac/Makefile 2.6.13-patched/net/ipv4/netfilter/nf-hipac/Makefile
+--- 2.6.13/net/ipv4/netfilter/nf-hipac/Makefile	1970-01-01 01:00:00.000000000 +0100
++++ 2.6.13-patched/net/ipv4/netfilter/nf-hipac/Makefile	2005-09-10 14:50:34.000000000 +0200
+@@ -0,0 +1,33 @@
++#
++# Makefile for nf-hipac on top of IPv4.
++#
++
++obj-$(CONFIG_IP_NF_HIPAC) += nf_hipac.o
++nf_hipac-objs := ihash.o global.o rlp.o dimtree.o hipac.o nfhp_dev.o nfhp_proc.o nfhp_mod.o
++
++ifdef CONFIG_IP_NF_HIPAC
++ifeq ($(CONFIG_IP_NF_CONNTRACK),m)
++obj-m += nf_hipac_cthelp.o
++EXTRA_CFLAGS += -D CONNTRACK_MODULE
++endif
++endif
++
++ifdef CONFIG_IP_NF_HIPAC_SINGLE_PATH
++EXTRA_CFLAGS += -D SINGLE_PATH
++endif
++
++ifneq ($(ARCH), alpha)
++ifneq ($(ARCH), ia64)
++ifneq ($(ARCH), ppc64)
++ifneq ($(ARCH), s390x)
++ifneq ($(ARCH), sh64)
++ifneq ($(ARCH), sparc64)
++ifneq ($(ARCH), x86_64)
++EXTRA_CFLAGS += -D BIT32_ARCH
++endif
++endif
++endif
++endif
++endif
++endif
++endif
+diff -purN --exclude=.svn 2.6.13/net/ipv4/netfilter/nf-hipac/dimtree.c 2.6.13-patched/net/ipv4/netfilter/nf-hipac/dimtree.c
+--- 2.6.13/net/ipv4/netfilter/nf-hipac/dimtree.c	1970-01-01 01:00:00.000000000 +0100
++++ 2.6.13-patched/net/ipv4/netfilter/nf-hipac/dimtree.c	2005-10-11 18:49:59.000000000 +0200
+@@ -0,0 +1,4307 @@
++/*
++ *             High performance packet classification 
++ *                     <http://www.hipac.org>
++ *
++ * (c) 2004-2005   MARA Systems AB <http://www.marasystems.com>
++ *                 +-----------------------------+
++ *                 |       Michael Bellion       |
++ *                 |  <michael at marasystems.com>  |
++ *                 +-----------------------------+
++ *
++ * (c) 2002-2003   hipac core team <nf at hipac.org>:
++ *     +---------------------------+--------------------------+
++ *     |      Michael Bellion      |       Thomas Heinz       |
++ *     |   <mbellion at hipac.org>    |   <creatix at hipac.org>    |
++ *     +---------------------------+--------------------------+
++ *
++ * Licenced under the GNU General Public Licence, version 2.
++ */
++
++
++#include "global.h"
++#include "ihash.h"
++#include "rlp.h"
++#include "dimtree.h"
++
++#define HAS_DT_MATCH(rule)      ((rule)->dt_match_len > 0)
++#define ITH_DT_MATCH(rule, i)   ((rule)->first_dt_match + (i))
++#define LAST_DT_MATCH(rule)     ITH_DT_MATCH(rule, (rule)->dt_match_len - 1)
++#define LEN(array)              (sizeof(array) / sizeof(*(array)))
++
++/*
++ * newspec keeps track of the rlps and elementary intervals that have been
++ * newly allocated during a series of dimtree operations;
++ * orgspec keeps track of the rlps and elementary intervals that can be
++ * freed after the series of dimtree operations has been successfully finished
++ */
++static struct ptrlist orgspec = {LIST_HEAD_INIT(orgspec.head), 0};
++static struct ihash *newspec  = NULL;
++
++
++
++static inline void
++elem_free(struct dt_elem *e)
++{
++	if (unlikely(e == NULL)) {
++		ARG_MSG;
++		return;
++	}
++	hp_free(e);
++}
++
++
++/* free s which can be an elemtary interval or a rlp */
++static inline void
++rlp_elem_free(struct gen_spec *s)
++{
++	if (unlikely(s == NULL)) {
++		ARG_MSG;
++		return;
++	}
++	if (IS_RLP(s)) {
++		rlp_free((struct rlp_spec *) s);
++	} else {
++		/* s must be elemtary interval */
++		assert(IS_ELEM(s));
++		elem_free((struct dt_elem *) s);
++	}
++}
++
++/* set newspec bit of s which can be an elementary interval or a rlp to 0 */
++static inline void
++rlp_elem_newspec_set(struct gen_spec *s, int newspec_set)
++{
++	if (unlikely(s == NULL)) {
++		ARG_MSG;
++		return;
++	}
++	if (IS_RLP(s)) {
++		((struct rlp_spec *) s)->newspec = !!newspec_set;
++	} else {
++		/* s must be elemtary interval */
++		assert(IS_ELEM(s));
++		((struct dt_elem_spec *) s)->newspec = !!newspec_set;
++	}
++}
++
++/* call rlp_elem_free for each member of orgspec and empty orgspec */
++static inline void
++orgspec_dofree(void)
++{
++	struct list_head *lh;
++	struct ptrlist_entry* e;
++
++	for (lh = orgspec.head.next; lh != &orgspec.head;) {
++		e = list_entry(lh, struct ptrlist_entry, head);
++		lh = lh->next;
++		assert((IS_RLP(e->p) &&
++			!((struct rlp_spec *) e->p)->newspec) ||
++		       (IS_ELEM(e->p) &&
++			!((struct dt_elem_spec *) e->p)->newspec));
++		rlp_elem_free(e->p);
++		mini_free(e);
++	}
++	INIT_LIST_HEAD(&orgspec.head);
++	orgspec.len = 0;
++}
++
++/* call rlp_elem_free for each member of newspec and empty newspec */
++static inline void
++newspec_dofree(void)
++{
++	if (unlikely(newspec == NULL)) {
++		return;
++	}
++	IHASH_KEY_ITERATE(newspec, struct gen_spec *, rlp_elem_free);
++	ihash_free(newspec);
++	newspec = NULL;
++}
++
++/* add s to orgspec;
++   possible errors: HE_LOW_MEMORY, HE_IMPOSSIBLE_CONDITION */
++static inline hipac_error
++orgspec_add(struct gen_spec *s)
++{
++	if (unlikely(s == NULL)) {
++		ARG_ERR;
++	}
++	assert((IS_RLP(s) && !((struct rlp_spec *) s)->newspec) ||
++	       (IS_ELEM(s) && !((struct dt_elem_spec *) s)->newspec));
++#ifdef DEBUG
++	return ptrlist_add(&orgspec, s, 1);
++#else
++	return ptrlist_add(&orgspec, s, 0);
++#endif
++}
++
++/* empty orgspec */
++static inline void
++orgspec_flush(void)
++{
++	ptrlist_flush(&orgspec);
++}
++
++/* empty newspec; if newspec_reset is not 0 the newspec bit is set
++   to 0 for each element of newspec */
++static inline void
++newspec_flush(int newspec_reset)
++{
++	if (unlikely(newspec == NULL)) {
++		return;
++	}
++	if (newspec_reset) {
++		IHASH_KEY_ITERATE(newspec, struct gen_spec *,
++				  rlp_elem_newspec_set, 0);
++	}
++	ihash_free(newspec);
++	newspec = NULL;
++}
++
++
++/*
++ * history operations
++ */
++
++static void
++history_undo(void)
++{
++	newspec_dofree();
++	orgspec_flush();
++}
++
++static void
++history_commit(int newspec_set)
++{
++	orgspec_dofree();
++	newspec_flush(newspec_set);
++}
++
++#ifdef DEBUG
++/* return 1 if orgspec and newspec are empty and 0 otherwise */
++static int
++history_is_empty(void)
++{
++	return newspec == NULL && list_empty(&orgspec.head);
++}
++#endif
++
++/* s is a new rlp or elementary interval layer which does __not__
++   replace another */
++static hipac_error
++history_new(struct gen_spec *s, int newspec_set)
++{
++	int stat;
++
++	if (unlikely(s == NULL)) {
++		ARG_ERR;
++	}
++
++	assert((IS_RLP(s) || IS_ELEM(s)));
++	if (unlikely(newspec == NULL)) {
++		newspec = ihash_new(INITIAL_NEWSPEC_LEN, 0,
++				    NEWSPEC_AVRG_ELEM_PER_BUCKET,
++				    ihash_func_val, eq_val);
++		if (newspec == NULL) {
++			return HE_LOW_MEMORY;
++		}
++	}
++	stat = ihash_insert(&newspec, s, NULL);
++	if (stat < 0) {
++		return stat;
++	}
++	if (newspec_set) {
++		rlp_elem_newspec_set(s, 1);
++	}
++	return stat;
++}
++
++static hipac_error
++history_replace(struct gen_spec *old, struct gen_spec *new, int newspec_set)
++{
++	int stat;
++
++	if (unlikely(old == NULL || new == NULL)) {
++		ARG_ERR;
++	}
++
++	assert((IS_RLP(old) && IS_RLP(new)) ||
++	       (IS_ELEM(old) && IS_ELEM(new)));
++	assert(newspec_set ||
++	       (IS_RLP(old) && !((struct rlp_spec *) old)->newspec) ||
++	       (IS_ELEM(old) && !((struct dt_elem_spec *) old)->newspec));
++	assert(newspec_set ||
++	       (IS_RLP(new) && !((struct rlp_spec *) new)->newspec) ||
++	       (IS_ELEM(new) && !((struct dt_elem_spec *) new)->newspec));
++	if (unlikely(newspec == NULL)) {
++		if (newspec_set &&
++		    ((IS_RLP(old) &&
++		      ((struct rlp_spec *) old)->newspec) ||
++		     (IS_ELEM(old) &&
++		      ((struct dt_elem_spec *) old)->newspec))) {
++			IMPOSSIBLE_CONDITION("old must be contained in new"
++					     "spec but newspec is empty");
++		}
++		newspec = ihash_new(INITIAL_NEWSPEC_LEN, 0,
++				    NEWSPEC_AVRG_ELEM_PER_BUCKET,
++				    ihash_func_val, eq_val);
++		if (newspec == NULL) {
++			return HE_LOW_MEMORY;
++		}
++	}
++	if (newspec_set &&
++	    ((IS_RLP(old) && ((struct rlp_spec *) old)->newspec) ||
++	     (IS_ELEM(old) && ((struct dt_elem_spec *) old)->newspec))) {
++		
++		stat = ihash_replace(&newspec, old, NULL, new, NULL);
++		if (stat == HE_OK) {
++			rlp_elem_newspec_set(new, 1);
++			rlp_elem_free(old);
++		}
++	} else {
++		stat = orgspec_add(old);
++		if (stat < 0) {
++			return stat;
++		}
++		stat = ihash_insert(&newspec, new, NULL);
++		if (stat < 0) {
++			return stat;
++		}
++		if (newspec_set) {
++			rlp_elem_newspec_set(new, 1);
++		}
++	}
++	return stat;
++}
++
++/* s is an obsolete rlp or elementary interval layer */
++static hipac_error
++history_obsolete(struct gen_spec *s, int newspec_set)
++{
++	if (unlikely(s == NULL)) {
++		ARG_ERR;
++	}
++
++	assert((IS_RLP(s) || IS_ELEM(s)));
++	assert(newspec_set ||
++	       (IS_RLP(s) && !((struct rlp_spec *) s)->newspec) ||
++	       (IS_ELEM(s) && !((struct dt_elem_spec *) s)->newspec));
++	if (unlikely(newspec == NULL && newspec_set &&
++		     ((IS_RLP(s) && ((struct rlp_spec *) s)->newspec) ||
++		      (IS_ELEM(s) && ((struct dt_elem_spec *) s)->newspec)))) {
++		IMPOSSIBLE_CONDITION("s is obsolete, newspec_set is not 0 and"
++				     " the newspec bit of s is set __but__ s "
++				     "is not contained in newspec");
++	}
++	if (newspec_set &&
++	    ((IS_RLP(s) && ((struct rlp_spec *) s)->newspec) ||
++	     (IS_ELEM(s) && ((struct dt_elem_spec *) s)->newspec))) {
++		if (ihash_delete(newspec, s, NULL) < 0) {
++			IMPOSSIBLE_CONDITION("unable to remove s from "
++					     "newspec");
++		}
++		rlp_elem_free(s);
++		return HE_OK;
++	}
++	return orgspec_add(s);
++}
++
++/* hp_realloc can result in a pointer becoming invalid; this function is used
++   to apply this fact to the history */
++static void
++history_del_invalid(struct gen_spec *s)
++{
++	if (unlikely(s == NULL)) {
++		ARG_MSG;
++		return;
++	}
++	if (ihash_delete(newspec, s, NULL) < 0) {
++		ERR("unable to remove invalid pointer from newspec");
++	}
++}
++
++
++
++/*
++ * termrule operations
++ */
++
++/* insert 'rule' in 'term' in sorted order (sorted after pointer addresses);
++   'term' must be sorted before */
++static inline hipac_error
++termrule_insert(struct ptrblock **term, struct dt_rule *rule)
++{
++	__u32 i;
++
++	if (unlikely(term == NULL || rule == NULL)) {
++		ARG_ERR;
++	}
++
++	if (*term == NULL) {
++		*term = ptrblock_new(rule, 1);
++		if (*term == NULL) {
++			return HE_LOW_MEMORY;
++		}
++		return HE_OK;
++	}
++
++#ifdef BIT32_ARCH
++	for (i = 0; i < (*term)->len && 
++		     (__u32) (*term)->p[i] < (__u32) rule; i++);
++#else
++	for (i = 0; i < (*term)->len && 
++		     (__u64) (*term)->p[i] < (__u64) rule; i++);
++#endif
++	if (i < (*term)->len && (*term)->p[i] == rule) {
++		IMPOSSIBLE_CONDITION("rule is already contained in term");
++	}
++	return ptrblock_insert(term, rule, i);
++}
++
++/* delete 'rule' from 'term' which must be in sorted order (sorted after
++   pointer addresses) */
++static inline hipac_error
++termrule_delete(struct ptrblock **term, const struct dt_rule *rule)
++{
++	__u32 i;
++
++	if (unlikely(term == NULL || rule == NULL)) {
++		ARG_ERR;
++	}
++	if (*term == NULL) {
++		/* rule is not in term */
++		return HE_OK;
++	}
++
++#ifdef BIT32_ARCH
++	for (i = 0; i < (*term)->len && 
++		     (__u32) (*term)->p[i] < (__u32) rule; i++);
++#else
++	for (i = 0; i < (*term)->len && 
++		     (__u64) (*term)->p[i] < (__u64) rule; i++);
++#endif
++	
++	if (i >= (*term)->len || (*term)->p[i] != rule) {
++		/* rule is not in term */
++		return HE_OK;
++	}
++	return ptrblock_delete_pos(term, i);
++}
++
++/* delete those rules from 'term' whose match boundaries in dimension 'dimid'
++   lie completely within ['left', 'right'] */
++static inline hipac_error
++termrule_delete_ovl(struct ptrblock **term, __u32 left, __u32 right,
++		    __u8 dimid)
++{
++	__u32 i, curleft, curight;
++	struct dt_match *match;
++	int stat;
++
++	if (unlikely(term == NULL || left > right ||
++		     left > MAXKEY(dim2btype[dimid]) ||
++		     right > MAXKEY(dim2btype[dimid]))) {
++		ARG_ERR;
++	}
++	if (*term == NULL) {
++		return HE_OK;
++	}
++
++       	for (i = 0; i < (*term)->len;) {
++		match = HAS_DT_MATCH((struct dt_rule *) (*term)->p[i]) ?
++			LAST_DT_MATCH((struct dt_rule *) (*term)->p[i]) : NULL;
++		if (match != NULL && match->dimid == dimid) {
++			assert(match->left > 0 ||
++			       match->right < MAXKEY(dim2btype[dimid]));
++			curleft = match->left;
++			curight = match->right;
++		} else {
++			curleft = 0;
++			curight = MAXKEY(dim2btype[dimid]);
++		}
++		if (curleft >= left && curight <= right) {
++			stat = ptrblock_delete_pos(term, i);
++			if (stat < 0) {
++				return stat;
<<Diff was trimmed, longer than 597 lines>>



More information about the pld-cvs-commit mailing list