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