diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-05 01:26:33 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 14:56:14 -0800 |
commit | 02f014d88831f73b895c1fe09badb66c88e932d3 (patch) | |
tree | 09aa75b8edeb240e62c4269f20630f8206c0e6d4 /net/netfilter | |
parent | 7a6c6653b3a977087ec64d76817c7ee6e1df5b60 (diff) |
[NETFILTER]: nf_queue: move list_head/skb/id to struct nf_info
Move common fields for queue management to struct nf_info and rename it
to struct nf_queue_entry. The avoids one allocation/free per packet and
simplifies the code a bit.
Alternatively we could add some private room at the tail, but since
all current users use identical structs this seems easier.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nf_queue.c | 65 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 74 |
2 files changed, 59 insertions, 80 deletions
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index bd71f433b85e..d9d3dc4ce1a3 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -93,7 +93,7 @@ static int __nf_queue(struct sk_buff *skb, unsigned int queuenum) { int status; - struct nf_info *info; + struct nf_queue_entry *entry; #ifdef CONFIG_BRIDGE_NETFILTER struct net_device *physindev = NULL; struct net_device *physoutdev = NULL; @@ -118,8 +118,8 @@ static int __nf_queue(struct sk_buff *skb, return 1; } - info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC); - if (!info) { + entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC); + if (!entry) { if (net_ratelimit()) printk(KERN_ERR "OOM queueing packet %p\n", skb); @@ -128,13 +128,20 @@ static int __nf_queue(struct sk_buff *skb, return 1; } - *info = (struct nf_info) { - (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn }; + *entry = (struct nf_queue_entry) { + .skb = skb, + .elem = list_entry(elem, struct nf_hook_ops, list), + .pf = pf, + .hook = hook, + .indev = indev, + .outdev = outdev, + .okfn = okfn, + }; /* If it's going away, ignore hook. */ - if (!try_module_get(info->elem->owner)) { + if (!try_module_get(entry->elem->owner)) { rcu_read_unlock(); - kfree(info); + kfree(entry); return 0; } @@ -153,8 +160,8 @@ static int __nf_queue(struct sk_buff *skb, dev_hold(physoutdev); } #endif - afinfo->saveroute(skb, info); - status = qh->outfn(skb, info, queuenum); + afinfo->saveroute(skb, entry); + status = qh->outfn(entry, queuenum); rcu_read_unlock(); @@ -170,8 +177,8 @@ static int __nf_queue(struct sk_buff *skb, if (physoutdev) dev_put(physoutdev); #endif - module_put(info->elem->owner); - kfree(info); + module_put(entry->elem->owner); + kfree(entry); kfree_skb(skb); return 1; @@ -220,19 +227,19 @@ int nf_queue(struct sk_buff *skb, return 1; } -void nf_reinject(struct sk_buff *skb, struct nf_info *info, - unsigned int verdict) +void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) { - struct list_head *elem = &info->elem->list; + struct sk_buff *skb = entry->skb; + struct list_head *elem = &entry->elem->list; struct nf_afinfo *afinfo; rcu_read_lock(); /* Release those devices we held, or Alexey will kill me. */ - if (info->indev) - dev_put(info->indev); - if (info->outdev) - dev_put(info->outdev); + if (entry->indev) + dev_put(entry->indev); + if (entry->outdev) + dev_put(entry->outdev); #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge) { if (skb->nf_bridge->physindev) @@ -243,7 +250,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, #endif /* Drop reference to owner of hook which queued us. */ - module_put(info->elem->owner); + module_put(entry->elem->owner); /* Continue traversal iff userspace said ok... */ if (verdict == NF_REPEAT) { @@ -252,28 +259,28 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, } if (verdict == NF_ACCEPT) { - afinfo = nf_get_afinfo(info->pf); - if (!afinfo || afinfo->reroute(skb, info) < 0) + afinfo = nf_get_afinfo(entry->pf); + if (!afinfo || afinfo->reroute(skb, entry) < 0) verdict = NF_DROP; } if (verdict == NF_ACCEPT) { next_hook: - verdict = nf_iterate(&nf_hooks[info->pf][info->hook], - skb, info->hook, - info->indev, info->outdev, &elem, - info->okfn, INT_MIN); + verdict = nf_iterate(&nf_hooks[entry->pf][entry->hook], + skb, entry->hook, + entry->indev, entry->outdev, &elem, + entry->okfn, INT_MIN); } switch (verdict & NF_VERDICT_MASK) { case NF_ACCEPT: case NF_STOP: - info->okfn(skb); + entry->okfn(skb); case NF_STOLEN: break; case NF_QUEUE: - if (!__nf_queue(skb, elem, info->pf, info->hook, - info->indev, info->outdev, info->okfn, + if (!__nf_queue(skb, elem, entry->pf, entry->hook, + entry->indev, entry->outdev, entry->okfn, verdict >> NF_VERDICT_BITS)) goto next_hook; break; @@ -281,7 +288,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, kfree_skb(skb); } rcu_read_unlock(); - kfree(info); + kfree(entry); return; } EXPORT_SYMBOL(nf_reinject); diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index cb901cf75776..a4937649d006 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -45,13 +45,6 @@ #define QDEBUG(x, ...) #endif -struct nfqnl_queue_entry { - struct list_head list; - struct nf_info *info; - struct sk_buff *skb; - unsigned int id; -}; - struct nfqnl_instance { struct hlist_node hlist; /* global list of queues */ atomic_t use; @@ -73,7 +66,7 @@ struct nfqnl_instance { struct list_head queue_list; /* packets in queue */ }; -typedef int (*nfqnl_cmpfn)(struct nfqnl_queue_entry *, unsigned long); +typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); static DEFINE_RWLOCK(instances_lock); @@ -212,7 +205,7 @@ instance_destroy(struct nfqnl_instance *inst) static void -issue_verdict(struct nfqnl_queue_entry *entry, int verdict) +issue_verdict(struct nf_queue_entry *entry, int verdict) { QDEBUG("entering for entry %p, verdict %u\n", entry, verdict); @@ -222,15 +215,12 @@ issue_verdict(struct nfqnl_queue_entry *entry, int verdict) * softirq, e.g. We therefore emulate this by local_bh_disable() */ local_bh_disable(); - nf_reinject(entry->skb, entry->info, verdict); + nf_reinject(entry, verdict); local_bh_enable(); - - kfree(entry); } static inline void -__enqueue_entry(struct nfqnl_instance *queue, - struct nfqnl_queue_entry *entry) +__enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry) { list_add_tail(&entry->list, &queue->queue_list); queue->queue_total++; @@ -265,10 +255,10 @@ __nfqnl_set_mode(struct nfqnl_instance *queue, return status; } -static struct nfqnl_queue_entry * +static struct nf_queue_entry * find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) { - struct nfqnl_queue_entry *entry = NULL, *i; + struct nf_queue_entry *entry = NULL, *i; spin_lock_bh(&queue->lock); @@ -292,7 +282,7 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id) static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) { - struct nfqnl_queue_entry *entry, *next; + struct nf_queue_entry *entry, *next; spin_lock_bh(&queue->lock); list_for_each_entry_safe(entry, next, &queue->queue_list, list) { @@ -307,7 +297,7 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) static struct sk_buff * nfqnl_build_packet_message(struct nfqnl_instance *queue, - struct nfqnl_queue_entry *entry, int *errp) + struct nf_queue_entry *entry, int *errp) { sk_buff_data_t old_tail; size_t size; @@ -316,7 +306,6 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, struct nfqnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - struct nf_info *entinf = entry->info; struct sk_buff *entskb = entry->skb; struct net_device *indev; struct net_device *outdev; @@ -336,7 +325,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); - outdev = entinf->outdev; + outdev = entry->outdev; spin_lock_bh(&queue->lock); @@ -379,23 +368,23 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); - nfmsg->nfgen_family = entinf->pf; + nfmsg->nfgen_family = entry->pf; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(queue->queue_num); pmsg.packet_id = htonl(entry->id); pmsg.hw_protocol = entskb->protocol; - pmsg.hook = entinf->hook; + pmsg.hook = entry->hook; NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg); - indev = entinf->indev; + indev = entry->indev; if (indev) { tmp_uint = htonl(indev->ifindex); #ifndef CONFIG_BRIDGE_NETFILTER NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint); #else - if (entinf->pf == PF_BRIDGE) { + if (entry->pf == PF_BRIDGE) { /* Case 1: indev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ @@ -425,7 +414,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, #ifndef CONFIG_BRIDGE_NETFILTER NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint); #else - if (entinf->pf == PF_BRIDGE) { + if (entry->pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ @@ -504,13 +493,11 @@ nla_put_failure: } static int -nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, - unsigned int queuenum) +nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) { int status = -EINVAL; struct sk_buff *nskb; struct nfqnl_instance *queue; - struct nfqnl_queue_entry *entry; QDEBUG("entered\n"); @@ -526,22 +513,11 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, goto err_out_put; } - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) { - if (net_ratelimit()) - printk(KERN_ERR - "nf_queue: OOM in nfqnl_enqueue_packet()\n"); - status = -ENOMEM; - goto err_out_put; - } - - entry->info = info; - entry->skb = skb; entry->id = atomic_inc_return(&queue->id_sequence); nskb = nfqnl_build_packet_message(queue, entry, &status); if (nskb == NULL) - goto err_out_free; + goto err_out_put; spin_lock_bh(&queue->lock); @@ -577,15 +553,13 @@ err_out_free_nskb: err_out_unlock: spin_unlock_bh(&queue->lock); -err_out_free: - kfree(entry); err_out_put: instance_put(queue); return status; } static int -nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) +nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) { int diff; int err; @@ -630,15 +604,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue, } static int -dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex) +dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) { - struct nf_info *entinf = entry->info; - - if (entinf->indev) - if (entinf->indev->ifindex == ifindex) + if (entry->indev) + if (entry->indev->ifindex == ifindex) return 1; - if (entinf->outdev) - if (entinf->outdev->ifindex == ifindex) + if (entry->outdev) + if (entry->outdev->ifindex == ifindex) return 1; #ifdef CONFIG_BRIDGE_NETFILTER if (entry->skb->nf_bridge) { @@ -748,7 +720,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, struct nfqnl_msg_verdict_hdr *vhdr; struct nfqnl_instance *queue; unsigned int verdict; - struct nfqnl_queue_entry *entry; + struct nf_queue_entry *entry; int err; queue = instance_lookup_get(queue_num); |