From e304252f4b5a05c4affd3cb78dd739a6078a66ba Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 2 Apr 2008 10:19:52 +0200 Subject: [PATCH] condition: greatly improve processing speed Replace the loop over all possible condvars by a simple deref. This changes the runtime from O(n) to O(1) at the expense of only 8 bytes for rule. --- extensions/libxt_condition.c | 3 +- extensions/xt_condition.c | 58 ++++++++++++++---------------------- extensions/xt_condition.h | 3 ++ 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/extensions/libxt_condition.c b/extensions/libxt_condition.c index 1719c58..71ad6dc 100644 --- a/extensions/libxt_condition.c +++ b/extensions/libxt_condition.c @@ -1,5 +1,6 @@ /* Shared library add-on to iptables for condition match */ #include +#include #include #include #include @@ -88,7 +89,7 @@ static struct xtables_match condition_mt6_reg = { .family = PF_INET6, .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_condition_mtinfo)), - .userspacesize = XT_ALIGN(sizeof(struct xt_condition_mtinfo)), + .userspacesize = offsetof(struct xt_condition_mtinfo, condvar), .help = condition_help, .parse = condition_parse, .final_check = condition_check, diff --git a/extensions/xt_condition.c b/extensions/xt_condition.c index 536ed51..5bfe242 100644 --- a/extensions/xt_condition.c +++ b/extensions/xt_condition.c @@ -104,19 +104,14 @@ condition_mt(const struct sk_buff *skb, const struct net_device *in, bool *hotdrop) { const struct xt_condition_mtinfo *info = matchinfo; - struct condition_variable *var; - int condition_status = 0; + const struct condition_variable *var = info->condvar; + bool x; rcu_read_lock(); - list_for_each_entry_rcu(var, &conditions_list, list) { - if (strcmp(info->name, var->status_proc->name) == 0) { - condition_status = var->enabled; - break; - } - } + x = rcu_dereference(var->enabled); rcu_read_unlock(); - return condition_status ^ info->invert; + return x ^ info->invert; } static bool @@ -124,8 +119,7 @@ condition_mt_check(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, unsigned int hook_mask) { - const struct xt_condition_mtinfo *info = matchinfo; - struct list_head *pos; + struct xt_condition_mtinfo *info = matchinfo; struct condition_variable *var; /* Forbid certain names */ @@ -144,11 +138,11 @@ condition_mt_check(const char *tablename, const void *entry, if (down_interruptible(&proc_lock)) return false; - list_for_each(pos, &conditions_list) { - var = list_entry(pos, struct condition_variable, list); + list_for_each_entry(var, &conditions_list, list) { if (strcmp(info->name, var->status_proc->name) == 0) { var->refcount++; up(&proc_lock); + info->condvar = var; return true; } } @@ -185,38 +179,30 @@ condition_mt_check(const char *tablename, const void *entry, up(&proc_lock); + info->condvar = var; return true; } static void condition_mt_destroy(const struct xt_match *match, void *matchinfo) { const struct xt_condition_mtinfo *info = matchinfo; - struct list_head *pos; - struct condition_variable *var; + struct condition_variable *var = info->condvar; down(&proc_lock); - - list_for_each(pos, &conditions_list) { - var = list_entry(pos, struct condition_variable, list); - if (strcmp(info->name, var->status_proc->name) == 0) { - if (--var->refcount == 0) { - list_del_rcu(pos); - remove_proc_entry(var->status_proc->name, proc_net_condition); - up(&proc_lock); - /* - * synchronize_rcu() would be good enough, but - * synchronize_net() guarantees that no packet - * will go out with the old rule after - * succesful removal. - */ - synchronize_net(); - kfree(var); - return; - } - break; - } + if (--var->refcount == 0) { + list_del_rcu(&var->list); + remove_proc_entry(var->status_proc->name, proc_net_condition); + up(&proc_lock); + /* + * synchronize_rcu() would be good enough, but + * synchronize_net() guarantees that no packet + * will go out with the old rule after + * succesful removal. + */ + synchronize_net(); + kfree(var); + return; } - up(&proc_lock); } diff --git a/extensions/xt_condition.h b/extensions/xt_condition.h index f8751ea..db37a31 100644 --- a/extensions/xt_condition.h +++ b/extensions/xt_condition.h @@ -8,6 +8,9 @@ enum { struct xt_condition_mtinfo { char name[CONDITION_NAME_LEN]; __u8 invert; + + /* Used internally by the kernel */ + void *condvar __attribute__((aligned(8))); }; #endif /* _XT_CONDITION_H */