* [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue
@ 2009-11-20 4:56 Changli Gao
2009-11-20 13:12 ` Patrick McHardy
0 siblings, 1 reply; 5+ messages in thread
From: Changli Gao @ 2009-11-20 4:56 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, xiaosuo
Use hash to speed up finding entries in nfqueue.
If user implements QoS in userland, packet verdict won't be received in order. At this moment, a hash table is faster than a double linked list when finding the corresponding entries in nfqueue.
This patch also fixes a potential bug, which will allows more than one entries with the same id are in the same nfqueue in the extreme.
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
nfnetlink_queue.c | 86 ++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 61 insertions(+), 25 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a9dec9..38c7af1 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -37,6 +37,9 @@
#endif
#define NFQNL_QMAX_DEFAULT 1024
+#define NFQNL_QHT_BITS 8
+#define NFQNL_QHT_SIZE (1 << NFQNL_QHT_BITS)
+#define NFQNL_QHT_MASK (NFQNL_QHT_SIZE - 1)
struct nfqnl_instance {
struct hlist_node hlist; /* global list of queues */
@@ -56,7 +59,7 @@ struct nfqnl_instance {
spinlock_t lock;
- struct list_head queue_list; /* packets in queue */
+ struct list_head *queue_list;
};
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
@@ -111,12 +114,19 @@ instance_create(u_int16_t queue_num, int pid)
inst->copy_range = 0xfffff;
inst->copy_mode = NFQNL_COPY_NONE;
spin_lock_init(&inst->lock);
- INIT_LIST_HEAD(&inst->queue_list);
+ inst->queue_list = kcalloc(NFQNL_QHT_SIZE, sizeof(*inst->queue_list),
+ GFP_ATOMIC);
+ if (inst->queue_list == NULL) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+ for (h = 0; h < NFQNL_QHT_SIZE; h++)
+ INIT_LIST_HEAD(&inst->queue_list[h]);
INIT_RCU_HEAD(&inst->rcu);
if (!try_module_get(THIS_MODULE)) {
err = -EAGAIN;
- goto out_free;
+ goto out_free_queue;
}
h = instance_hashfn(queue_num);
@@ -126,6 +136,8 @@ instance_create(u_int16_t queue_num, int pid)
return inst;
+out_free_queue:
+ kfree(inst->queue_list);
out_free:
kfree(inst);
out_unlock:
@@ -143,6 +155,7 @@ instance_destroy_rcu(struct rcu_head *head)
rcu);
nfqnl_flush(inst, NULL, 0);
+ kfree(inst->queue_list);
kfree(inst);
module_put(THIS_MODULE);
}
@@ -162,32 +175,51 @@ instance_destroy(struct nfqnl_instance *inst)
spin_unlock(&instances_lock);
}
+static struct nf_queue_entry *
+__find_entry(struct nfqnl_instance *queue, unsigned int id)
+{
+ struct nf_queue_entry *i;
+
+ list_for_each_entry(i, &queue->queue_list[id & NFQNL_QHT_MASK], list) {
+ if (i->id == id)
+ return i;
+ }
+
+ return NULL;
+}
+
static inline void
__enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
{
- list_add_tail(&entry->list, &queue->queue_list);
- queue->queue_total++;
+ do {
+ entry->id = queue->id_sequence++;
+ } while (__find_entry(queue, entry->id) != NULL);
+ list_add_tail(&entry->list,
+ &queue->queue_list[entry->id & NFQNL_QHT_MASK]);
+ queue->queue_total++;
}
static struct nf_queue_entry *
-find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
+__dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
{
- struct nf_queue_entry *entry = NULL, *i;
-
- spin_lock_bh(&queue->lock);
-
- list_for_each_entry(i, &queue->queue_list, list) {
- if (i->id == id) {
- entry = i;
- break;
- }
- }
+ struct nf_queue_entry *entry;
+ entry = __find_entry(queue, id);
if (entry) {
list_del(&entry->list);
queue->queue_total--;
}
+ return entry;
+}
+
+static struct nf_queue_entry *
+dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
+{
+ struct nf_queue_entry *entry;
+
+ spin_lock_bh(&queue->lock);
+ entry = __dequeue_entry(queue, id);
spin_unlock_bh(&queue->lock);
return entry;
@@ -197,13 +229,17 @@ static void
nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
{
struct nf_queue_entry *entry, *next;
+ int i;
spin_lock_bh(&queue->lock);
- list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
- if (!cmpfn || cmpfn(entry, data)) {
- list_del(&entry->list);
- queue->queue_total--;
- nf_reinject(entry, NF_DROP);
+ for (i = 0; i < NFQNL_QHT_SIZE; i++) {
+ list_for_each_entry_safe(entry, next, &queue->queue_list[i],
+ list) {
+ if (!cmpfn || cmpfn(entry, data)) {
+ list_del(&entry->list);
+ queue->queue_total--;
+ nf_reinject(entry, NF_DROP);
+ }
}
}
spin_unlock_bh(&queue->lock);
@@ -262,7 +298,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
break;
}
- entry->id = queue->id_sequence++;
+ __enqueue_entry(queue, entry);
spin_unlock_bh(&queue->lock);
@@ -379,6 +415,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
nlmsg_failure:
nla_put_failure:
+ dequeue_entry(queue, entry->id);
if (skb)
kfree_skb(skb);
if (net_ratelimit())
@@ -426,14 +463,13 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
goto err_out_unlock;
}
- __enqueue_entry(queue, entry);
-
spin_unlock_bh(&queue->lock);
return 0;
err_out_free_nskb:
kfree_skb(nskb);
err_out_unlock:
+ __dequeue_entry(queue, entry->id);
spin_unlock_bh(&queue->lock);
err_out:
return -1;
@@ -645,7 +681,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
goto err_out_unlock;
}
- entry = find_dequeue_entry(queue, ntohl(vhdr->id));
+ entry = dequeue_entry(queue, ntohl(vhdr->id));
if (entry == NULL) {
err = -ENOENT;
goto err_out_unlock;
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue
2009-11-20 4:56 [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue Changli Gao
@ 2009-11-20 13:12 ` Patrick McHardy
2009-11-20 13:46 ` Changli Gao
0 siblings, 1 reply; 5+ messages in thread
From: Patrick McHardy @ 2009-11-20 13:12 UTC (permalink / raw)
To: xiaosuo; +Cc: netfilter-devel
Changli Gao wrote:
> Use hash to speed up finding entries in nfqueue.
>
> If user implements QoS in userland, packet verdict won't be received in order. At this moment, a hash table is faster than a double linked list when finding the corresponding entries in nfqueue.
>
> This patch also fixes a potential bug, which will allows more than one entries with the same id are in the same nfqueue in the extreme.
Instead of a double ID in a purely hypothetical case, we'd now
get an endless loop. This part doesn't make much sense to me,
please remove it from the patch.
> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
> index 7a9dec9..38c7af1 100644
> --- a/net/netfilter/nfnetlink_queue.c
> +++ b/net/netfilter/nfnetlink_queue.c
> @@ -37,6 +37,9 @@
> #endif
>
> #define NFQNL_QMAX_DEFAULT 1024
> +#define NFQNL_QHT_BITS 8
> +#define NFQNL_QHT_SIZE (1 << NFQNL_QHT_BITS)
> +#define NFQNL_QHT_MASK (NFQNL_QHT_SIZE - 1)
Have you considered making the size configurable by passing a new
attribute in the NFQNL_CFG_CMD_BIND cmd message?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue
2009-11-20 13:12 ` Patrick McHardy
@ 2009-11-20 13:46 ` Changli Gao
2009-11-20 13:56 ` Patrick McHardy
0 siblings, 1 reply; 5+ messages in thread
From: Changli Gao @ 2009-11-20 13:46 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel
On Fri, Nov 20, 2009 at 9:12 PM, Patrick McHardy <kaber@trash.net> wrote:
> Changli Gao wrote:
>> Use hash to speed up finding entries in nfqueue.
>>
>> If user implements QoS in userland, packet verdict won't be received in order. At this moment, a hash table is faster than a double linked list when finding the corresponding entries in nfqueue.
>>
>> This patch also fixes a potential bug, which will allows more than one entries with the same id are in the same nfqueue in the extreme.
>
> Instead of a double ID in a purely hypothetical case, we'd now
> get an endless loop. This part doesn't make much sense to me,
> please remove it from the patch.
>
It isn't a endless loop, as we limite the queue size.
>> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
>> index 7a9dec9..38c7af1 100644
>> --- a/net/netfilter/nfnetlink_queue.c
>> +++ b/net/netfilter/nfnetlink_queue.c
>> @@ -37,6 +37,9 @@
>> #endif
>>
>> #define NFQNL_QMAX_DEFAULT 1024
>> +#define NFQNL_QHT_BITS 8
>> +#define NFQNL_QHT_SIZE (1 << NFQNL_QHT_BITS)
>> +#define NFQNL_QHT_MASK (NFQNL_QHT_SIZE - 1)
>
> Have you considered making the size configurable by passing a new
> attribute in the NFQNL_CFG_CMD_BIND cmd message?
>
OK. It's better users can config the size.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
--
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue
2009-11-20 13:46 ` Changli Gao
@ 2009-11-20 13:56 ` Patrick McHardy
2009-11-20 14:00 ` Changli Gao
0 siblings, 1 reply; 5+ messages in thread
From: Patrick McHardy @ 2009-11-20 13:56 UTC (permalink / raw)
To: Changli Gao; +Cc: netfilter-devel
Changli Gao wrote:
> On Fri, Nov 20, 2009 at 9:12 PM, Patrick McHardy <kaber@trash.net> wrote:
>> Changli Gao wrote:
>>> Use hash to speed up finding entries in nfqueue.
>>>
>>> If user implements QoS in userland, packet verdict won't be received in order. At this moment, a hash table is faster than a double linked list when finding the corresponding entries in nfqueue.
>>>
>>> This patch also fixes a potential bug, which will allows more than one entries with the same id are in the same nfqueue in the extreme.
>> Instead of a double ID in a purely hypothetical case, we'd now
>> get an endless loop. This part doesn't make much sense to me,
>> please remove it from the patch.
>>
>
> It isn't a endless loop, as we limite the queue size.
It is if queue_maxlen is set to the maximum. In any case this change
adds a new lookup for ID assignment and complicates the code for a
case which I still consider purely hypothetical. Additionally it is
not related to the hashing change and shouldn't be in the same patch.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue
2009-11-20 13:56 ` Patrick McHardy
@ 2009-11-20 14:00 ` Changli Gao
0 siblings, 0 replies; 5+ messages in thread
From: Changli Gao @ 2009-11-20 14:00 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel
On Fri, Nov 20, 2009 at 9:56 PM, Patrick McHardy <kaber@trash.net> wrote:
> Changli Gao wrote:
>> On Fri, Nov 20, 2009 at 9:12 PM, Patrick McHardy <kaber@trash.net> wrote:
>>> Changli Gao wrote:
>>>> Use hash to speed up finding entries in nfqueue.
>>>>
>>>> If user implements QoS in userland, packet verdict won't be received in order. At this moment, a hash table is faster than a double linked list when finding the corresponding entries in nfqueue.
>>>>
>>>> This patch also fixes a potential bug, which will allows more than one entries with the same id are in the same nfqueue in the extreme.
>>> Instead of a double ID in a purely hypothetical case, we'd now
>>> get an endless loop. This part doesn't make much sense to me,
>>> please remove it from the patch.
>>>
>>
>> It isn't a endless loop, as we limite the queue size.
>
> It is if queue_maxlen is set to the maximum. In any case this change
> adds a new lookup for ID assignment and complicates the code for a
> case which I still consider purely hypothetical. Additionally it is
> not related to the hashing change and shouldn't be in the same patch.
>
Agree.
--
Regards,
Changli Gao(xiaosuo@gmail.com)
--
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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-11-20 13:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-20 4:56 [PATCH] nfnetlink_queue: Use hash to speed up finding entries in nfqueue Changli Gao
2009-11-20 13:12 ` Patrick McHardy
2009-11-20 13:46 ` Changli Gao
2009-11-20 13:56 ` Patrick McHardy
2009-11-20 14:00 ` Changli Gao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).