mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-08 13:44:56 +02:00
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.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/* Shared library add-on to iptables for condition match */
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -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,
|
||||
|
@@ -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,22 +179,18 @@ 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);
|
||||
list_del_rcu(&var->list);
|
||||
remove_proc_entry(var->status_proc->name, proc_net_condition);
|
||||
up(&proc_lock);
|
||||
/*
|
||||
@@ -213,10 +203,6 @@ static void condition_mt_destroy(const struct xt_match *match, void *matchinfo)
|
||||
kfree(var);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
up(&proc_lock);
|
||||
}
|
||||
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user