[NETFILTER]: nfnetlink_queue: deobfuscate entry lookups
authorPatrick McHardy <kaber@trash.net>
Wed, 5 Dec 2007 09:25:30 +0000 (01:25 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:56:12 +0000 (14:56 -0800)
A queue entry lookup currently looks like this:

find_dequeue_entry -> __find_dequeue_entry ->
__find_entry -> cmpfn -> id_cmp

Use simple open-coded list walking and kill the cmpfn for
find_dequeue_entry. Instead add it to nfqnl_flush (after
similar cleanups) and use nfqnl_flush for both complete
flushes and flushing entries related to a device.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/netfilter/nfnetlink_queue.c

index 74d5ed9490a9814bd8b14ebcb391361e2c822ef0..cb901cf757760ce4118fc08ea97374c160ffa020 100644 (file)
@@ -171,7 +171,8 @@ out_unlock:
        return NULL;
 }
 
-static void nfqnl_flush(struct nfqnl_instance *queue, int verdict);
+static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
+                       unsigned long data);
 
 static void
 _instance_destroy2(struct nfqnl_instance *inst, int lock)
@@ -188,7 +189,7 @@ _instance_destroy2(struct nfqnl_instance *inst, int lock)
                write_unlock_bh(&instances_lock);
 
        /* then flush all pending skbs from the queue */
-       nfqnl_flush(inst, NF_DROP);
+       nfqnl_flush(inst, NULL, 0);
 
        /* and finally put the refcount */
        instance_put(inst);
@@ -235,54 +236,6 @@ __enqueue_entry(struct nfqnl_instance *queue,
        queue->queue_total++;
 }
 
-/*
- * Find and return a queued entry matched by cmpfn, or return the last
- * entry if cmpfn is NULL.
- */
-static inline struct nfqnl_queue_entry *
-__find_entry(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn,
-                  unsigned long data)
-{
-       struct nfqnl_queue_entry *entry;
-
-       list_for_each_entry(entry, &queue->queue_list, list) {
-               if (!cmpfn || cmpfn(entry, data))
-                       return entry;
-       }
-       return NULL;
-}
-
-static inline void
-__dequeue_entry(struct nfqnl_instance *q, struct nfqnl_queue_entry *entry)
-{
-       list_del(&entry->list);
-       q->queue_total--;
-}
-
-static inline struct nfqnl_queue_entry *
-__find_dequeue_entry(struct nfqnl_instance *queue,
-                    nfqnl_cmpfn cmpfn, unsigned long data)
-{
-       struct nfqnl_queue_entry *entry;
-
-       entry = __find_entry(queue, cmpfn, data);
-       if (entry == NULL)
-               return NULL;
-
-       __dequeue_entry(queue, entry);
-       return entry;
-}
-
-
-static inline void
-__nfqnl_flush(struct nfqnl_instance *queue, int verdict)
-{
-       struct nfqnl_queue_entry *entry;
-
-       while ((entry = __find_dequeue_entry(queue, NULL, 0)))
-               issue_verdict(entry, verdict);
-}
-
 static inline int
 __nfqnl_set_mode(struct nfqnl_instance *queue,
                 unsigned char mode, unsigned int range)
@@ -313,23 +266,42 @@ __nfqnl_set_mode(struct nfqnl_instance *queue,
 }
 
 static struct nfqnl_queue_entry *
-find_dequeue_entry(struct nfqnl_instance *queue,
-                        nfqnl_cmpfn cmpfn, unsigned long data)
+find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
 {
-       struct nfqnl_queue_entry *entry;
+       struct nfqnl_queue_entry *entry = NULL, *i;
 
        spin_lock_bh(&queue->lock);
-       entry = __find_dequeue_entry(queue, cmpfn, data);
+
+       list_for_each_entry(i, &queue->queue_list, list) {
+               if (i->id == id) {
+                       entry = i;
+                       break;
+               }
+       }
+
+       if (entry) {
+               list_del(&entry->list);
+               queue->queue_total--;
+       }
+
        spin_unlock_bh(&queue->lock);
 
        return entry;
 }
 
 static void
-nfqnl_flush(struct nfqnl_instance *queue, int verdict)
+nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
 {
+       struct nfqnl_queue_entry *entry, *next;
+
        spin_lock_bh(&queue->lock);
-       __nfqnl_flush(queue, verdict);
+       list_for_each_entry_safe(entry, next, &queue->queue_list, list) {
+               if (!cmpfn || cmpfn(entry, data)) {
+                       list_del(&entry->list);
+                       queue->queue_total--;
+                       issue_verdict(entry, NF_DROP);
+               }
+       }
        spin_unlock_bh(&queue->lock);
 }
 
@@ -644,12 +616,6 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
        return 0;
 }
 
-static inline int
-id_cmp(struct nfqnl_queue_entry *e, unsigned long id)
-{
-       return (id == e->id);
-}
-
 static int
 nfqnl_set_mode(struct nfqnl_instance *queue,
               unsigned char mode, unsigned int range)
@@ -706,12 +672,8 @@ nfqnl_dev_drop(int ifindex)
                struct nfqnl_instance *inst;
                struct hlist_head *head = &instance_table[i];
 
-               hlist_for_each_entry(inst, tmp, head, hlist) {
-                       struct nfqnl_queue_entry *entry;
-                       while ((entry = find_dequeue_entry(inst, dev_cmp,
-                                                          ifindex)) != NULL)
-                               issue_verdict(entry, NF_DROP);
-               }
+               hlist_for_each_entry(inst, tmp, head, hlist)
+                       nfqnl_flush(inst, dev_cmp, ifindex);
        }
 
        read_unlock_bh(&instances_lock);
@@ -811,7 +773,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
                goto err_out_put;
        }
 
-       entry = find_dequeue_entry(queue, id_cmp, ntohl(vhdr->id));
+       entry = find_dequeue_entry(queue, ntohl(vhdr->id));
        if (entry == NULL) {
                err = -ENOENT;
                goto err_out_put;