* [PATCH 0/3] Further speedup of iptables when modifying an existing ruleset @ 2008-07-02 18:00 Thomas Jacob 2008-07-02 18:00 ` [PATCH 1/3] Speed up verdict to chain_head mapping by using binary search Thomas Jacob 0 siblings, 1 reply; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 18:00 UTC (permalink / raw) To: netfilter-devel This version includes the coding style changes, but still employs the macro to implement the binary interval search. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/3] Speed up verdict to chain_head mapping by using binary search 2008-07-02 18:00 [PATCH 0/3] Further speedup of iptables when modifying an existing ruleset Thomas Jacob @ 2008-07-02 18:00 ` Thomas Jacob 2008-07-02 18:00 ` [PATCH 2/3] Spelling Thomas Jacob 2008-07-02 20:57 ` Patches solving the same issue!? Jesper Dangaard Brouer 0 siblings, 2 replies; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 18:00 UTC (permalink / raw) To: netfilter-devel; +Cc: Thomas Jacob Signed-off-by: Thomas Jacob <jacob@internet24.de> --- libiptc/libiptc.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 192 insertions(+), 7 deletions(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index d0f51b4..e0c44c3 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -126,6 +126,26 @@ struct chain_head unsigned int foot_offset; /* offset in rule blob */ }; +/* Max. number of chain_head per offsets chunk */ +#define OFFSETS_CHUNK_SIZE (1024) + +struct offsets_create_chunk +{ + struct list_head list; + + unsigned int head_offset; /* of first entry */ + unsigned int foot_offset; /* of last entry */ + + unsigned int num_entries; /* #entries */ + struct chain_head * entries[OFFSETS_CHUNK_SIZE]; /* order by offset */ +}; + +struct offsets_lookup_table +{ + unsigned int num_entries; /* #entries */ + struct offsets_create_chunk ** entries; /* order by offset */ +}; + STRUCT_TC_HANDLE { int changed; /* Have changes been made? */ @@ -140,6 +160,9 @@ STRUCT_TC_HANDLE struct chain_head **chain_index; /* array for fast chain list access*/ unsigned int chain_index_sz;/* size of chain index array */ + struct list_head offsets_create_list; /* array chunks created during data acquisition */ + struct offsets_lookup_table offsets_search; /* final offsets search array */ + STRUCT_GETINFO info; STRUCT_GET_ENTRIES *entries; }; @@ -568,6 +591,61 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h) /********************************************************************** + * iptc offsets index utility functions + **********************************************************************/ + +/* Create offsets lookup table from the chunk list */ +static int iptcc_offsets_index_create(TC_HANDLE_T h) +{ + struct offsets_create_chunk * chunk; + unsigned int total_number=0; + + /* First pass: count non-empty chunks and set their ranges */ + list_for_each_entry(chunk, &h->offsets_create_list, list) { + if (chunk->num_entries>0) { + total_number++; + chunk->head_offset = chunk->entries[0]->head_offset; + chunk->foot_offset = chunk->entries[chunk->num_entries-1]->foot_offset; + } + } + + /* No chains->nothing to assign */ + if (total_number==0) + return 1; + + h->offsets_search.entries = malloc(sizeof(struct offsets_create_chunk *)*total_number); + if (!h->offsets_search.entries) + return -ENOMEM; + + /* Second pass: fill chunk table */ + unsigned int i=0; + list_for_each_entry(chunk, &h->offsets_create_list, list) + if (chunk->num_entries>0) + h->offsets_search.entries[i++] = chunk; + + h->offsets_search.num_entries = total_number; + + return 1; +} + +/* Free offsets lookup table AND the individual chunks */ +static void iptcc_offsets_index_free(TC_HANDLE_T h) +{ + struct offsets_create_chunk * chunk, *tmp; + + if (h->offsets_search.num_entries>0) { + free(h->offsets_search.entries); + h->offsets_search.num_entries=0; + } + + list_for_each_entry_safe(chunk, tmp, &h->offsets_create_list, list) + free(chunk); + + INIT_LIST_HEAD(&h->offsets_create_list); +} + + +/********************************************************************** * iptc cache utility functions (iptcc_*) **********************************************************************/ @@ -625,6 +703,67 @@ iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) return NULL; } + +/* + * Fast membership check on order arrays of inclusive intervals + * ( based on http://en.wikipedia.org/wiki/Binary_search ) + * + * value: value to search for + * array: array of struct points + * left: struct attribute denoting left inclusive range limiter in array items + * right: struct attribute denoting left inclusive range limiter in array items + * size: number of items in array + * low, high, mid: temporary int variables + * result: index of range that contains value, or -1 if not found + */ + +#define binary_array_range_search(value, array, left, right, size, low, high, mid, result) \ + low = 0; \ + high = size; \ + result = -1; \ + while(low<=high) \ + { \ + mid = (low + high) / 2; \ + if ((array)[mid]->left > value) \ + high = mid - 1; \ + else if ((array)[mid]->right < value) \ + low = mid + 1; \ + else { \ + if ((array)[mid]->left <= value && value <= (array)[mid]->right) \ + result = mid; \ + break; \ + } \ + } + +/* Returns chain head if found, otherwise NULL. */ +static struct chain_head * +iptcc_find_chain_by_offset_fast(TC_HANDLE_T handle, unsigned int offset) +{ + int low,high,mid,result; + + if (handle->offsets_search.num_entries==0) + return NULL; + + /* find the chunk */ + binary_array_range_search(offset, handle->offsets_search.entries, head_offset, foot_offset, + handle->offsets_search.num_entries, low, high, mid, result); + + if (result<0) + return NULL; + + /* find chain in chunk */ + struct chain_head ** chunk_chains = handle->offsets_search.entries[result]->entries; + unsigned int num_entries = handle->offsets_search.entries[result]->num_entries; + + binary_array_range_search(offset, chunk_chains, head_offset, foot_offset, + num_entries, low, high, mid, result); + + if (result<0) + return NULL; + + return chunk_chains[result]; +} + /* Returns chain head if found, otherwise NULL. */ static struct chain_head * iptcc_find_label(const char *name, TC_HANDLE_T handle) @@ -720,6 +859,19 @@ static void iptcc_delete_rule(struct rule_head *r) * RULESET PARSER (blob -> cache) **********************************************************************/ +/* Allocate another offsets chunk and append it to list */ +static int __iptcc_p_new_offsets_chunk(TC_HANDLE_T h) +{ + struct offsets_create_chunk * new_chunk = malloc(sizeof(struct offsets_create_chunk)); + + if (new_chunk) { + new_chunk->num_entries=0; + list_add_tail(&new_chunk->list, &h->offsets_create_list); + return 1; + } + return -1; +} + /* Delete policy rule of previous chain, since cache doesn't contain * chain policy rules. * WARNING: This function has ugly design and relies on a lot of context, only @@ -746,6 +898,19 @@ static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) h->chain_iterator_cur->foot_index = num; h->chain_iterator_cur->foot_offset = pr->offset; + /* do we need a new offsets chunk? */ + if (list_empty(&h->offsets_create_list) || + list_entry(h->offsets_create_list.prev, struct offsets_create_chunk, list)->num_entries + >=OFFSETS_CHUNK_SIZE) + if (__iptcc_p_new_offsets_chunk(h)<0) + return -1; + + /* add next chain to the current offsets chunk */ + struct offsets_create_chunk * occ = + list_entry(h->offsets_create_list.prev, struct offsets_create_chunk, list); + + occ->entries[occ->num_entries++]=h->chain_iterator_cur; + /* delete rule from cache */ iptcc_delete_rule(pr); h->chain_iterator_cur->num_rules--; @@ -799,13 +964,14 @@ static inline void iptc_insert_chain(TC_HANDLE_T h, struct chain_head *c) /* Another ugly helper function split out of cache_add_entry to make it less * spaghetti code */ -static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, +static int __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, unsigned int offset, unsigned int *num) { struct list_head *tail = h->chains.prev; struct chain_head *ctail; - __iptcc_p_del_policy(h, *num); + if ((__iptcc_p_del_policy(h, *num))<0) + return -1; c->head_offset = offset; c->index = *num; @@ -826,6 +992,8 @@ static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, } h->chain_iterator_cur = c; + + return 1; } /* main parser function: add an entry from the blob to the cache */ @@ -844,7 +1012,10 @@ static int cache_add_entry(STRUCT_ENTRY *e, /* This is the ERROR node at the end of the chain */ DEBUGP_C("%u:%u: end of table:\n", *num, offset); - __iptcc_p_del_policy(h, *num); + if ((__iptcc_p_del_policy(h, *num))<0) { + errno = -ENOMEM; + return -1; + } h->chain_iterator_cur = NULL; goto out_inc; @@ -864,8 +1035,10 @@ static int cache_add_entry(STRUCT_ENTRY *e, } h->num_chains++; /* New user defined chain */ - __iptcc_p_add_chain(h, c, offset, num); - + if ((__iptcc_p_add_chain(h, c, offset, num))<0) { + errno = -ENOMEM; + return -1; + } } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { struct chain_head *c = iptcc_alloc_chain_head((char *)hooknames[builtin-1], @@ -879,7 +1052,10 @@ static int cache_add_entry(STRUCT_ENTRY *e, c->hooknum = builtin; - __iptcc_p_add_chain(h, c, offset, num); + if ((__iptcc_p_add_chain(h, c, offset, num))<0) { + errno = -ENOMEM; + return -1; + } /* FIXME: this is ugly. */ goto new_rule; @@ -955,6 +1131,10 @@ static int parse_table(TC_HANDLE_T h) return -ENOMEM; iptcc_chain_index_build(h); + /* Build the offsets lookup table */ + if ((iptcc_offsets_index_create(h)) < 0) + return -ENOMEM; + /* Second pass: fixup parsed data from first pass */ list_for_each_entry(c, &h->chains, list) { struct rule_head *r; @@ -966,7 +1146,7 @@ static int parse_table(TC_HANDLE_T h) continue; t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); - lc = iptcc_find_chain_by_offset(h, t->verdict); + lc = iptcc_find_chain_by_offset_fast(h, t->verdict); if (!lc) return -1; r->jump = lc; @@ -974,6 +1154,9 @@ static int parse_table(TC_HANDLE_T h) } } + /* Don't need these tables anymore after beyond point */ + iptcc_offsets_index_free(h); + /* FIXME: sort chains */ return 1; @@ -1193,6 +1376,8 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) strcpy(h->entries->name, tablename); h->entries->size = size; + INIT_LIST_HEAD(&h->offsets_create_list); + return h; out_free_handle: -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] Spelling 2008-07-02 18:00 ` [PATCH 1/3] Speed up verdict to chain_head mapping by using binary search Thomas Jacob @ 2008-07-02 18:00 ` Thomas Jacob 2008-07-02 18:00 ` [PATCH 3/3] Coding style Thomas Jacob 2008-07-02 20:57 ` Patches solving the same issue!? Jesper Dangaard Brouer 1 sibling, 1 reply; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 18:00 UTC (permalink / raw) To: netfilter-devel; +Cc: Thomas Jacob Signed-off-by: Thomas Jacob <jacob@internet24.de> --- libiptc/libiptc.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index e0c44c3..c77455a 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -160,8 +160,8 @@ STRUCT_TC_HANDLE struct chain_head **chain_index; /* array for fast chain list access*/ unsigned int chain_index_sz;/* size of chain index array */ - struct list_head offsets_create_list; /* array chunks created during data acquisition */ - struct offsets_lookup_table offsets_search; /* final offsets search array */ + struct list_head offsets_create_list; /* Array chunks created during data acquisition */ + struct offsets_lookup_table offsets_search; /* Final offsets search array */ STRUCT_GETINFO info; STRUCT_GET_ENTRIES *entries; @@ -705,11 +705,11 @@ iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) /* - * Fast membership check on order arrays of inclusive intervals + * Fast membership check on ordered arrays of inclusive intervals * ( based on http://en.wikipedia.org/wiki/Binary_search ) * * value: value to search for - * array: array of struct points + * array: array of struct pointers * left: struct attribute denoting left inclusive range limiter in array items * right: struct attribute denoting left inclusive range limiter in array items * size: number of items in array @@ -744,14 +744,14 @@ iptcc_find_chain_by_offset_fast(TC_HANDLE_T handle, unsigned int offset) if (handle->offsets_search.num_entries==0) return NULL; - /* find the chunk */ + /* Find the chunk that could contain an appropriate interval */ binary_array_range_search(offset, handle->offsets_search.entries, head_offset, foot_offset, handle->offsets_search.num_entries, low, high, mid, result); if (result<0) return NULL; - /* find chain in chunk */ + /* Find chain in chunk */ struct chain_head ** chunk_chains = handle->offsets_search.entries[result]->entries; unsigned int num_entries = handle->offsets_search.entries[result]->num_entries; -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/3] Coding style 2008-07-02 18:00 ` [PATCH 2/3] Spelling Thomas Jacob @ 2008-07-02 18:00 ` Thomas Jacob 0 siblings, 0 replies; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 18:00 UTC (permalink / raw) To: netfilter-devel; +Cc: Thomas Jacob Signed-off-by: Thomas Jacob <jacob@internet24.de> --- libiptc/libiptc.c | 118 ++++++++++++++++++++++++++++++----------------------- 1 files changed, 67 insertions(+), 51 deletions(-) diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index c77455a..b89522b 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -129,21 +129,22 @@ struct chain_head /* Max. number of chain_head per offsets chunk */ #define OFFSETS_CHUNK_SIZE (1024) -struct offsets_create_chunk +struct offsets_chunk { struct list_head list; - unsigned int head_offset; /* of first entry */ - unsigned int foot_offset; /* of last entry */ + unsigned int first_offset; /* head_offset of first entry */ + unsigned int last_offset; /* foot_offset of last entry */ - unsigned int num_entries; /* #entries */ - struct chain_head * entries[OFFSETS_CHUNK_SIZE]; /* order by offset */ + unsigned int num_entries; + /* ordered by offset */ + struct chain_head *entries[OFFSETS_CHUNK_SIZE]; }; struct offsets_lookup_table { - unsigned int num_entries; /* #entries */ - struct offsets_create_chunk ** entries; /* order by offset */ + unsigned int num_entries; + struct offsets_chunk **entries; /* ordered by offset */ }; STRUCT_TC_HANDLE @@ -160,8 +161,10 @@ STRUCT_TC_HANDLE struct chain_head **chain_index; /* array for fast chain list access*/ unsigned int chain_index_sz;/* size of chain index array */ - struct list_head offsets_create_list; /* Array chunks created during data acquisition */ - struct offsets_lookup_table offsets_search; /* Final offsets search array */ + /* Array chunks created during data acquisition */ + struct list_head offsets_search_list; + /* Final offsets search array */ + struct offsets_lookup_table offsets_search; STRUCT_GETINFO info; STRUCT_GET_ENTRIES *entries; @@ -597,31 +600,35 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h) /* Create offsets lookup table from the chunk list */ static int iptcc_offsets_index_create(TC_HANDLE_T h) { - struct offsets_create_chunk * chunk; - unsigned int total_number=0; + struct offsets_chunk *ch; + unsigned int total_number = 0; + unsigned int i = 0; /* First pass: count non-empty chunks and set their ranges */ - list_for_each_entry(chunk, &h->offsets_create_list, list) { - if (chunk->num_entries>0) { + list_for_each_entry(ch, &h->offsets_search_list, list) { + if (ch->num_entries > 0) { total_number++; - chunk->head_offset = chunk->entries[0]->head_offset; - chunk->foot_offset = chunk->entries[chunk->num_entries-1]->foot_offset; + ch->first_offset = + ch->entries[0]->head_offset; + ch->last_offset = + ch->entries[ch->num_entries - 1]->foot_offset; } } /* No chains->nothing to assign */ - if (total_number==0) + if (total_number == 0) return 1; - h->offsets_search.entries = malloc(sizeof(struct offsets_create_chunk *)*total_number); + h->offsets_search.entries = + malloc(sizeof(struct offsets_chunk *)*total_number); + if (!h->offsets_search.entries) return -ENOMEM; /* Second pass: fill chunk table */ - unsigned int i=0; - list_for_each_entry(chunk, &h->offsets_create_list, list) - if (chunk->num_entries>0) - h->offsets_search.entries[i++] = chunk; + list_for_each_entry(ch, &h->offsets_search_list, list) + if (ch->num_entries > 0) + h->offsets_search.entries[i++] = ch; h->offsets_search.num_entries = total_number; @@ -631,17 +638,17 @@ static int iptcc_offsets_index_create(TC_HANDLE_T h) /* Free offsets lookup table AND the individual chunks */ static void iptcc_offsets_index_free(TC_HANDLE_T h) { - struct offsets_create_chunk * chunk, *tmp; + struct offsets_chunk *ch, *tmp; - if (h->offsets_search.num_entries>0) { + if (h->offsets_search.num_entries > 0) { free(h->offsets_search.entries); - h->offsets_search.num_entries=0; + h->offsets_search.num_entries = 0; } - list_for_each_entry_safe(chunk, tmp, &h->offsets_create_list, list) - free(chunk); + list_for_each_entry_safe(ch, tmp, &h->offsets_search_list, list) + free(ch); - INIT_LIST_HEAD(&h->offsets_create_list); + INIT_LIST_HEAD(&h->offsets_search_list); } @@ -721,7 +728,7 @@ iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) low = 0; \ high = size; \ result = -1; \ - while(low<=high) \ + while(low <= high) \ { \ mid = (low + high) / 2; \ if ((array)[mid]->left > value) \ @@ -740,25 +747,31 @@ static struct chain_head * iptcc_find_chain_by_offset_fast(TC_HANDLE_T handle, unsigned int offset) { int low,high,mid,result; + struct chain_head **chunk_chains; + unsigned int num_entries; - if (handle->offsets_search.num_entries==0) + if (handle->offsets_search.num_entries == 0) return NULL; /* Find the chunk that could contain an appropriate interval */ - binary_array_range_search(offset, handle->offsets_search.entries, head_offset, foot_offset, - handle->offsets_search.num_entries, low, high, mid, result); + binary_array_range_search(offset, handle->offsets_search.entries, + first_offset, last_offset, + handle->offsets_search.num_entries, + low, high, mid, result); - if (result<0) + if (result < 0) return NULL; /* Find chain in chunk */ - struct chain_head ** chunk_chains = handle->offsets_search.entries[result]->entries; - unsigned int num_entries = handle->offsets_search.entries[result]->num_entries; + chunk_chains = handle->offsets_search.entries[result]->entries; + num_entries = handle->offsets_search.entries[result]->num_entries; - binary_array_range_search(offset, chunk_chains, head_offset, foot_offset, - num_entries, low, high, mid, result); + binary_array_range_search(offset, chunk_chains, + head_offset, foot_offset, + num_entries, + low, high, mid, result); - if (result<0) + if (result < 0) return NULL; return chunk_chains[result]; @@ -862,11 +875,11 @@ static void iptcc_delete_rule(struct rule_head *r) /* Allocate another offsets chunk and append it to list */ static int __iptcc_p_new_offsets_chunk(TC_HANDLE_T h) { - struct offsets_create_chunk * new_chunk = malloc(sizeof(struct offsets_create_chunk)); + struct offsets_chunk *new_chunk = malloc(sizeof(struct offsets_chunk)); if (new_chunk) { - new_chunk->num_entries=0; - list_add_tail(&new_chunk->list, &h->offsets_create_list); + new_chunk->num_entries = 0; + list_add_tail(&new_chunk->list, &h->offsets_search_list); return 1; } return -1; @@ -878,6 +891,8 @@ static int __iptcc_p_new_offsets_chunk(TC_HANDLE_T h) * to be called from specific places within the parser */ static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) { + struct offsets_chunk *occ; + if (h->chain_iterator_cur) { /* policy rule is last rule */ struct rule_head *pr = (struct rule_head *) @@ -899,17 +914,18 @@ static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) h->chain_iterator_cur->foot_offset = pr->offset; /* do we need a new offsets chunk? */ - if (list_empty(&h->offsets_create_list) || - list_entry(h->offsets_create_list.prev, struct offsets_create_chunk, list)->num_entries - >=OFFSETS_CHUNK_SIZE) - if (__iptcc_p_new_offsets_chunk(h)<0) + if (list_empty(&h->offsets_search_list) || + list_entry(h->offsets_search_list.prev, + struct offsets_chunk, list)->num_entries + >= OFFSETS_CHUNK_SIZE) + if (__iptcc_p_new_offsets_chunk(h) < 0) return -1; /* add next chain to the current offsets chunk */ - struct offsets_create_chunk * occ = - list_entry(h->offsets_create_list.prev, struct offsets_create_chunk, list); + occ = list_entry(h->offsets_search_list.prev, + struct offsets_chunk, list); - occ->entries[occ->num_entries++]=h->chain_iterator_cur; + occ->entries[occ->num_entries++] = h->chain_iterator_cur; /* delete rule from cache */ iptcc_delete_rule(pr); @@ -1012,7 +1028,7 @@ static int cache_add_entry(STRUCT_ENTRY *e, /* This is the ERROR node at the end of the chain */ DEBUGP_C("%u:%u: end of table:\n", *num, offset); - if ((__iptcc_p_del_policy(h, *num))<0) { + if ((__iptcc_p_del_policy(h, *num)) < 0) { errno = -ENOMEM; return -1; } @@ -1035,7 +1051,7 @@ static int cache_add_entry(STRUCT_ENTRY *e, } h->num_chains++; /* New user defined chain */ - if ((__iptcc_p_add_chain(h, c, offset, num))<0) { + if ((__iptcc_p_add_chain(h, c, offset, num)) < 0) { errno = -ENOMEM; return -1; } @@ -1052,7 +1068,7 @@ static int cache_add_entry(STRUCT_ENTRY *e, c->hooknum = builtin; - if ((__iptcc_p_add_chain(h, c, offset, num))<0) { + if ((__iptcc_p_add_chain(h, c, offset, num)) < 0) { errno = -ENOMEM; return -1; } @@ -1376,7 +1392,7 @@ alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) strcpy(h->entries->name, tablename); h->entries->size = size; - INIT_LIST_HEAD(&h->offsets_create_list); + INIT_LIST_HEAD(&h->offsets_search_list); return h; -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Patches solving the same issue!? 2008-07-02 18:00 ` [PATCH 1/3] Speed up verdict to chain_head mapping by using binary search Thomas Jacob 2008-07-02 18:00 ` [PATCH 2/3] Spelling Thomas Jacob @ 2008-07-02 20:57 ` Jesper Dangaard Brouer 2008-07-02 21:47 ` Thomas Jacob 2008-07-03 12:42 ` Patrick McHardy 1 sibling, 2 replies; 13+ messages in thread From: Jesper Dangaard Brouer @ 2008-07-02 20:57 UTC (permalink / raw) To: Thomas Jacob; +Cc: netfilter-devel, Patrick McHardy, Jesper Dangaard Brouer I can see from the list that Thomas Jacob <jacob@internet24.de>, and I have just posted patches solving the same issue. I promised Patrick that I would work on this issue, and I did. Its running on our production servers, and I planned to release the patch today as it has proven stable on production. I guess Thomas was just slightly faster than me ;-) It was actually already released in the CPAN module IPTables::libiptc (ver.0.08 released 2008-06-16). We both use binary search, but with two slightly different approaches. - My patch uses the existing data structure, and the existing algorithm for binary searching. - Thomas builds a new data structure and implements a new binary search algorithm. I must give Thomas that this binary search algo (taken from wikipedia) is much more compact than the existing one. Guess I cannot judge what patch is the best, as I'm biased... ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-02 20:57 ` Patches solving the same issue!? Jesper Dangaard Brouer @ 2008-07-02 21:47 ` Thomas Jacob 2008-07-02 22:02 ` Thomas Jacob 2008-07-03 10:53 ` Jesper Dangaard Brouer 2008-07-03 12:42 ` Patrick McHardy 1 sibling, 2 replies; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 21:47 UTC (permalink / raw) To: Jesper Dangaard Brouer; +Cc: Thomas Jacob, netfilter-devel, Patrick McHardy [-- Attachment #1: Type: text/plain, Size: 1870 bytes --] Oops, sorry about that, I did notice your initial set of speed up patches (that's why I was enthusiastically playing around with large rule sets and became aware of the issue in the first place), but evidently I didn't follow the related thread very closely. I am not familiar enough with the iptables code to decide whether or not chains are always sorted by name in the kernel, and thus will be sorted if you read them back, but if that's the case, of course your method is better, as long as that's always the case... To be honest, I didn't really understand the chain_index code ;) On Wed, Jul 02, 2008 at 10:57:31PM +0200, Jesper Dangaard Brouer wrote: > > I can see from the list that Thomas Jacob <jacob@internet24.de>, and I > have just posted patches solving the same issue. > > I promised Patrick that I would work on this issue, and I did. > > Its running on our production servers, and I planned to release the > patch today as it has proven stable on production. I guess Thomas was > just slightly faster than me ;-) > > It was actually already released in the CPAN module IPTables::libiptc > (ver.0.08 released 2008-06-16). > > > We both use binary search, but with two slightly different approaches. > > - My patch uses the existing data structure, and the existing > algorithm for binary searching. > > - Thomas builds a new data structure and implements a new binary > search algorithm. > > I must give Thomas that this binary search algo (taken from wikipedia) > is much more compact than the existing one. > > Guess I cannot judge what patch is the best, as I'm biased... > > -- > To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-02 21:47 ` Thomas Jacob @ 2008-07-02 22:02 ` Thomas Jacob 2008-07-03 10:53 ` Jesper Dangaard Brouer 1 sibling, 0 replies; 13+ messages in thread From: Thomas Jacob @ 2008-07-02 22:02 UTC (permalink / raw) To: Thomas Jacob; +Cc: Jesper Dangaard Brouer, netfilter-devel, Patrick McHardy [-- Attachment #1: Type: text/plain, Size: 2154 bytes --] As addendum, your code runs just as fast, maybe even a tad faster as mine, and obviously uses less memory. Oh well... On Wed, Jul 02, 2008 at 11:47:36PM +0200, Thomas Jacob wrote: > Oops, sorry about that, I did notice your initial > set of speed up patches (that's why I was enthusiastically playing > around with large rule sets and became aware of the issue > in the first place), but evidently I didn't follow the > related thread very closely. > > I am not familiar enough with the iptables code to decide > whether or not chains are always sorted by name in the kernel, > and thus will be sorted if you read them back, but if that's > the case, of course your method is better, as long as that's > always the case... > > To be honest, I didn't really understand the chain_index code ;) > > > On Wed, Jul 02, 2008 at 10:57:31PM +0200, Jesper Dangaard Brouer wrote: > > > > I can see from the list that Thomas Jacob <jacob@internet24.de>, and I > > have just posted patches solving the same issue. > > > > I promised Patrick that I would work on this issue, and I did. > > > > Its running on our production servers, and I planned to release the > > patch today as it has proven stable on production. I guess Thomas was > > just slightly faster than me ;-) > > > > It was actually already released in the CPAN module IPTables::libiptc > > (ver.0.08 released 2008-06-16). > > > > > > We both use binary search, but with two slightly different approaches. > > > > - My patch uses the existing data structure, and the existing > > algorithm for binary searching. > > > > - Thomas builds a new data structure and implements a new binary > > search algorithm. > > > > I must give Thomas that this binary search algo (taken from wikipedia) > > is much more compact than the existing one. > > > > Guess I cannot judge what patch is the best, as I'm biased... > > > > -- > > To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-02 21:47 ` Thomas Jacob 2008-07-02 22:02 ` Thomas Jacob @ 2008-07-03 10:53 ` Jesper Dangaard Brouer 2008-07-03 11:17 ` Thomas Jacob 1 sibling, 1 reply; 13+ messages in thread From: Jesper Dangaard Brouer @ 2008-07-03 10:53 UTC (permalink / raw) To: Thomas Jacob Cc: Jesper Dangaard Brouer, Netfilter Developers, Patrick McHardy On Wed, 2 Jul 2008, Thomas Jacob wrote: > I am not familiar enough with the iptables code to decide > whether or not chains are always sorted by name in the kernel, > and thus will be sorted if you read them back, but if that's > the case, of course your method is better, as long as that's > always the case... It _is_ always the case that chains are sorted by name in the kernel, as libiptc puts them in sorted. Thats also what the chain_index code depends upon (although I have build in a safe guard that sorts them if they are not). There is also a safe guard for the offset binary search, but that simply reverts to the old (_slow_) search scheme. If Patrick might want to change this in the future, he should consider your solution over mine. > To be honest, I didn't really understand the chain_index code ;) It actually some what resembels your idea, with arrays of chain_head pointers. That points to the original chain list. I don't build "chunks" as I don't want to find an exact match, just a place in the chain list to start the list search. This is choosen because I need to support chains deletes and creates. Its more complicated because it needs to support chain deletes and creates. And needs to scale, when many chains are added, which requires rebuilding the chain_index, but not too often... BTW, I like your coding style, although it more compact that I would choose to write it... Hilsen Jesper Brouer -- ------------------------------------------------------------------- MSc. Master of Computer Science Dept. of Computer Science, University of Copenhagen Author of http://www.adsl-optimizer.dk ------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-03 10:53 ` Jesper Dangaard Brouer @ 2008-07-03 11:17 ` Thomas Jacob 0 siblings, 0 replies; 13+ messages in thread From: Thomas Jacob @ 2008-07-03 11:17 UTC (permalink / raw) To: Jesper Dangaard Brouer; +Cc: netfilter-devel [-- Attachment #1: Type: text/plain, Size: 927 bytes --] On Thu, 2008-07-03 at 12:53 +0200, Jesper Dangaard Brouer wrote: > Thats also what the chain_index code depends upon (although I have build > in a safe guard that sorts them if they are not). There is also a safe > guard for the offset binary search, but that simply reverts to the old > (_slow_) search scheme. I see, so that's no problem either => if (strcmp(c->name, ctail->name) > 0 || iptcc_is_builtin(ctail)) list_add_tail(&c->list, &h->chains); else { iptc_insert_chain(h, c);/* Was not sorted */ h->sorted_offsets = 0; The skip-list-like search infrastructure is also quite nice and integrates well with the current code, once one understands what it does anyway. So there is really no reason as to why my patch should be preferred over yours ;-) Regards, Thomas [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-02 20:57 ` Patches solving the same issue!? Jesper Dangaard Brouer 2008-07-02 21:47 ` Thomas Jacob @ 2008-07-03 12:42 ` Patrick McHardy 2008-07-03 14:30 ` Thomas Jacob 1 sibling, 1 reply; 13+ messages in thread From: Patrick McHardy @ 2008-07-03 12:42 UTC (permalink / raw) To: jdb; +Cc: Thomas Jacob, netfilter-devel Jesper Dangaard Brouer wrote: > I can see from the list that Thomas Jacob <jacob@internet24.de>, and I > have just posted patches solving the same issue. > > I promised Patrick that I would work on this issue, and I did. Sorry, I'm forgetful sometimes :) > Its running on our production servers, and I planned to release the > patch today as it has proven stable on production. I guess Thomas was > just slightly faster than me ;-) > > It was actually already released in the CPAN module IPTables::libiptc > (ver.0.08 released 2008-06-16). > > > We both use binary search, but with two slightly different approaches. > > - My patch uses the existing data structure, and the existing > algorithm for binary searching. > > - Thomas builds a new data structure and implements a new binary > search algorithm. > > I must give Thomas that this binary search algo (taken from wikipedia) > is much more compact than the existing one. > > Guess I cannot judge what patch is the best, as I'm biased... Me neither since you guys did all the work :) Please work this out among yourselves. I think we should just pick the faster one since both don't look very intrusive. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-03 12:42 ` Patrick McHardy @ 2008-07-03 14:30 ` Thomas Jacob 2008-07-03 14:33 ` Patrick McHardy 0 siblings, 1 reply; 13+ messages in thread From: Thomas Jacob @ 2008-07-03 14:30 UTC (permalink / raw) To: Patrick McHardy; +Cc: jdb, netfilter-devel On Thu, 2008-07-03 at 14:42 +0200, Patrick McHardy wrote: > Please work this out among yourselves. I think we should just pick > the faster one since both don't look very intrusive. Well, Jesper's version doesn't build any extra data-structures, so you save time&space there, and the offsets stuff is really only needed once, so the chain_index rebuilding penalty doesn't play a role. And since about 2/3s of time it takes to load my 50k Chains now is system time, it's probably irrelevant whether 0 + O(n * (log(n/40)+40)) is sometimes larger than O(n+n/1024) + O(log(n)). Mine vs. Jesper's: iptables-restore (50k chains, 120k rules), average for 10 runs: User: 2.558 s - System: 8.672 s - Total : 11.222 s vs User: 2.622 s - System: 8.520 s - Total : 11.140 s iptables -vnL SOMECHAIN (2 entries, with the above ruleset in kernel), average for 20 runs User: .094 s - System: .363 s - Total : .455 s vs User: .085 s - System: .389 s - Total : .472 s Those numbers are all within the standard deviations of each other, so there is no difference for practical purposes, I think :-) I would use Jesper's patch. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-03 14:30 ` Thomas Jacob @ 2008-07-03 14:33 ` Patrick McHardy 2008-07-04 7:09 ` Jesper Dangaard Brouer 0 siblings, 1 reply; 13+ messages in thread From: Patrick McHardy @ 2008-07-03 14:33 UTC (permalink / raw) To: Thomas Jacob; +Cc: jdb, netfilter-devel Thomas Jacob wrote: > On Thu, 2008-07-03 at 14:42 +0200, Patrick McHardy wrote: >> Please work this out among yourselves. I think we should just pick >> the faster one since both don't look very intrusive. > > Well, Jesper's version doesn't build any extra data-structures, > so you save time&space there, and the offsets stuff is really > only needed once, so the chain_index rebuilding penalty > doesn't play a role. > > And since about 2/3s of time it takes to load my 50k Chains now > is system time, it's probably irrelevant whether > 0 + O(n * (log(n/40)+40)) is sometimes larger than O(n+n/1024) + > O(log(n)). > > Mine vs. Jesper's: > > iptables-restore (50k chains, 120k rules), average for 10 runs: > > User: 2.558 s - System: 8.672 s - Total : 11.222 s > vs > User: 2.622 s - System: 8.520 s - Total : 11.140 s > > > iptables -vnL SOMECHAIN (2 entries, with the above ruleset in kernel), > average for 20 runs > > User: .094 s - System: .363 s - Total : .455 s > vs > User: .085 s - System: .389 s - Total : .472 s > > Those numbers are all within the standard deviations of each other, > so there is no difference for practical purposes, I think :-) > > I would use Jesper's patch. OK, thanks for the numbers and sorting this out so peacefully :) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Patches solving the same issue!? 2008-07-03 14:33 ` Patrick McHardy @ 2008-07-04 7:09 ` Jesper Dangaard Brouer 0 siblings, 0 replies; 13+ messages in thread From: Jesper Dangaard Brouer @ 2008-07-04 7:09 UTC (permalink / raw) To: Patrick McHardy; +Cc: Thomas Jacob, jdb, netfilter-devel On Thu, 3 Jul 2008, Patrick McHardy wrote: > Thomas Jacob wrote: >> >> I would use Jesper's patch. > > OK, thanks for the numbers and sorting this out so peacefully :) Thanks, Thomas! :-) Cheers, Jesper Brouer -- ------------------------------------------------------------------- MSc. Master of Computer Science Dept. of Computer Science, University of Copenhagen Author of http://www.adsl-optimizer.dk ------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-07-04 7:09 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-07-02 18:00 [PATCH 0/3] Further speedup of iptables when modifying an existing ruleset Thomas Jacob 2008-07-02 18:00 ` [PATCH 1/3] Speed up verdict to chain_head mapping by using binary search Thomas Jacob 2008-07-02 18:00 ` [PATCH 2/3] Spelling Thomas Jacob 2008-07-02 18:00 ` [PATCH 3/3] Coding style Thomas Jacob 2008-07-02 20:57 ` Patches solving the same issue!? Jesper Dangaard Brouer 2008-07-02 21:47 ` Thomas Jacob 2008-07-02 22:02 ` Thomas Jacob 2008-07-03 10:53 ` Jesper Dangaard Brouer 2008-07-03 11:17 ` Thomas Jacob 2008-07-03 12:42 ` Patrick McHardy 2008-07-03 14:30 ` Thomas Jacob 2008-07-03 14:33 ` Patrick McHardy 2008-07-04 7:09 ` Jesper Dangaard Brouer
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.