Skip to content

Commit 02f014d

Browse files
kaberdavem330
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7a6c665 commit 02f014d

File tree

8 files changed

+132
-190
lines changed

8 files changed

+132
-190
lines changed

include/linux/netfilter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,17 @@ extern void nf_invalidate_cache(int pf);
270270
extern int skb_make_writable(struct sk_buff *skb, unsigned int writable_len);
271271

272272
struct flowi;
273-
struct nf_info;
273+
struct nf_queue_entry;
274274

275275
struct nf_afinfo {
276276
unsigned short family;
277277
__sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
278278
unsigned int dataoff, u_int8_t protocol);
279279
int (*route)(struct dst_entry **dst, struct flowi *fl);
280280
void (*saveroute)(const struct sk_buff *skb,
281-
struct nf_info *info);
281+
struct nf_queue_entry *entry);
282282
int (*reroute)(struct sk_buff *skb,
283-
const struct nf_info *info);
283+
const struct nf_queue_entry *entry);
284284
int route_key_size;
285285
};
286286

include/net/netfilter/nf_queue.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
#define _NF_QUEUE_H
33

44
/* Each queued (to userspace) skbuff has one of these. */
5-
struct nf_info {
5+
struct nf_queue_entry {
6+
struct list_head list;
7+
struct sk_buff *skb;
8+
unsigned int id;
9+
610
struct nf_hook_ops *elem;
711
int pf;
812
unsigned int hook;
@@ -11,12 +15,11 @@ struct nf_info {
1115
int (*okfn)(struct sk_buff *);
1216
};
1317

14-
#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
18+
#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
1519

1620
/* Packet queuing */
1721
struct nf_queue_handler {
18-
int (*outfn)(struct sk_buff *skb,
19-
struct nf_info *info,
22+
int (*outfn)(struct nf_queue_entry *entry,
2023
unsigned int queuenum);
2124
char *name;
2225
};
@@ -26,7 +29,6 @@ extern int nf_register_queue_handler(int pf,
2629
extern int nf_unregister_queue_handler(int pf,
2730
const struct nf_queue_handler *qh);
2831
extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
29-
extern void nf_reinject(struct sk_buff *skb, struct nf_info *info,
30-
unsigned int verdict);
32+
extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
3133

3234
#endif /* _NF_QUEUE_H */

net/ipv4/netfilter.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ struct ip_rt_info {
123123
u_int8_t tos;
124124
};
125125

126-
static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
126+
static void nf_ip_saveroute(const struct sk_buff *skb,
127+
struct nf_queue_entry *entry)
127128
{
128-
struct ip_rt_info *rt_info = nf_info_reroute(info);
129+
struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
129130

130-
if (info->hook == NF_INET_LOCAL_OUT) {
131+
if (entry->hook == NF_INET_LOCAL_OUT) {
131132
const struct iphdr *iph = ip_hdr(skb);
132133

133134
rt_info->tos = iph->tos;
@@ -136,11 +137,12 @@ static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
136137
}
137138
}
138139

139-
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_info *info)
140+
static int nf_ip_reroute(struct sk_buff *skb,
141+
const struct nf_queue_entry *entry)
140142
{
141-
const struct ip_rt_info *rt_info = nf_info_reroute(info);
143+
const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
142144

143-
if (info->hook == NF_INET_LOCAL_OUT) {
145+
if (entry->hook == NF_INET_LOCAL_OUT) {
144146
const struct iphdr *iph = ip_hdr(skb);
145147

146148
if (!(iph->tos == rt_info->tos

net/ipv4/netfilter/ip_queue.c

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,7 @@
3535
#define NET_IPQ_QMAX 2088
3636
#define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
3737

38-
struct ipq_queue_entry {
39-
struct list_head list;
40-
struct nf_info *info;
41-
struct sk_buff *skb;
42-
};
43-
44-
typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
38+
typedef int (*ipq_cmpfn)(struct nf_queue_entry *, unsigned long);
4539

4640
static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE;
4741
static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT;
@@ -56,22 +50,20 @@ static LIST_HEAD(queue_list);
5650
static DEFINE_MUTEX(ipqnl_mutex);
5751

5852
static void
59-
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
53+
ipq_issue_verdict(struct nf_queue_entry *entry, int verdict)
6054
{
6155
/* TCP input path (and probably other bits) assume to be called
6256
* from softirq context, not from syscall, like ipq_issue_verdict is
6357
* called. TCP input path deadlocks with locks taken from timer
6458
* softirq, e.g. We therefore emulate this by local_bh_disable() */
6559

6660
local_bh_disable();
67-
nf_reinject(entry->skb, entry->info, verdict);
61+
nf_reinject(entry, verdict);
6862
local_bh_enable();
69-
70-
kfree(entry);
7163
}
7264

7365
static inline void
74-
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
66+
__ipq_enqueue_entry(struct nf_queue_entry *entry)
7567
{
7668
list_add_tail(&entry->list, &queue_list);
7769
queue_total++;
@@ -114,10 +106,10 @@ __ipq_reset(void)
114106
__ipq_flush(NULL, 0);
115107
}
116108

117-
static struct ipq_queue_entry *
109+
static struct nf_queue_entry *
118110
ipq_find_dequeue_entry(unsigned long id)
119111
{
120-
struct ipq_queue_entry *entry = NULL, *i;
112+
struct nf_queue_entry *entry = NULL, *i;
121113

122114
write_lock_bh(&queue_lock);
123115

@@ -140,7 +132,7 @@ ipq_find_dequeue_entry(unsigned long id)
140132
static void
141133
__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
142134
{
143-
struct ipq_queue_entry *entry, *next;
135+
struct nf_queue_entry *entry, *next;
144136

145137
list_for_each_entry_safe(entry, next, &queue_list, list) {
146138
if (!cmpfn || cmpfn(entry, data)) {
@@ -160,7 +152,7 @@ ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
160152
}
161153

162154
static struct sk_buff *
163-
ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
155+
ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
164156
{
165157
sk_buff_data_t old_tail;
166158
size_t size = 0;
@@ -217,20 +209,20 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
217209
pmsg->timestamp_sec = tv.tv_sec;
218210
pmsg->timestamp_usec = tv.tv_usec;
219211
pmsg->mark = entry->skb->mark;
220-
pmsg->hook = entry->info->hook;
212+
pmsg->hook = entry->hook;
221213
pmsg->hw_protocol = entry->skb->protocol;
222214

223-
if (entry->info->indev)
224-
strcpy(pmsg->indev_name, entry->info->indev->name);
215+
if (entry->indev)
216+
strcpy(pmsg->indev_name, entry->indev->name);
225217
else
226218
pmsg->indev_name[0] = '\0';
227219

228-
if (entry->info->outdev)
229-
strcpy(pmsg->outdev_name, entry->info->outdev->name);
220+
if (entry->outdev)
221+
strcpy(pmsg->outdev_name, entry->outdev->name);
230222
else
231223
pmsg->outdev_name[0] = '\0';
232224

233-
if (entry->info->indev && entry->skb->dev) {
225+
if (entry->indev && entry->skb->dev) {
234226
pmsg->hw_type = entry->skb->dev->type;
235227
pmsg->hw_addrlen = dev_parse_header(entry->skb,
236228
pmsg->hw_addr);
@@ -252,28 +244,17 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
252244
}
253245

254246
static int
255-
ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
256-
unsigned int queuenum)
247+
ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
257248
{
258249
int status = -EINVAL;
259250
struct sk_buff *nskb;
260-
struct ipq_queue_entry *entry;
261251

262252
if (copy_mode == IPQ_COPY_NONE)
263253
return -EAGAIN;
264254

265-
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
266-
if (entry == NULL) {
267-
printk(KERN_ERR "ip_queue: OOM in ipq_enqueue_packet()\n");
268-
return -ENOMEM;
269-
}
270-
271-
entry->info = info;
272-
entry->skb = skb;
273-
274255
nskb = ipq_build_packet_message(entry, &status);
275256
if (nskb == NULL)
276-
goto err_out_free;
257+
return status;
277258

278259
write_lock_bh(&queue_lock);
279260

@@ -307,14 +288,11 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info,
307288

308289
err_out_unlock:
309290
write_unlock_bh(&queue_lock);
310-
311-
err_out_free:
312-
kfree(entry);
313291
return status;
314292
}
315293

316294
static int
317-
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
295+
ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
318296
{
319297
int diff;
320298
int err;
@@ -352,7 +330,7 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
352330
static int
353331
ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
354332
{
355-
struct ipq_queue_entry *entry;
333+
struct nf_queue_entry *entry;
356334

357335
if (vmsg->value > NF_MAX_VERDICT)
358336
return -EINVAL;
@@ -412,13 +390,13 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg,
412390
}
413391

414392
static int
415-
dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
393+
dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
416394
{
417-
if (entry->info->indev)
418-
if (entry->info->indev->ifindex == ifindex)
395+
if (entry->indev)
396+
if (entry->indev->ifindex == ifindex)
419397
return 1;
420-
if (entry->info->outdev)
421-
if (entry->info->outdev->ifindex == ifindex)
398+
if (entry->outdev)
399+
if (entry->outdev->ifindex == ifindex)
422400
return 1;
423401
#ifdef CONFIG_BRIDGE_NETFILTER
424402
if (entry->skb->nf_bridge) {

net/ipv6/netfilter.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,25 @@ struct ip6_rt_info {
5757
struct in6_addr saddr;
5858
};
5959

60-
static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
60+
static void nf_ip6_saveroute(const struct sk_buff *skb,
61+
struct nf_queue_entry *entry)
6162
{
62-
struct ip6_rt_info *rt_info = nf_info_reroute(info);
63+
struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
6364

64-
if (info->hook == NF_INET_LOCAL_OUT) {
65+
if (entry->hook == NF_INET_LOCAL_OUT) {
6566
struct ipv6hdr *iph = ipv6_hdr(skb);
6667

6768
rt_info->daddr = iph->daddr;
6869
rt_info->saddr = iph->saddr;
6970
}
7071
}
7172

72-
static int nf_ip6_reroute(struct sk_buff *skb, const struct nf_info *info)
73+
static int nf_ip6_reroute(struct sk_buff *skb,
74+
const struct nf_queue_entry *entry)
7375
{
74-
struct ip6_rt_info *rt_info = nf_info_reroute(info);
76+
struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
7577

76-
if (info->hook == NF_INET_LOCAL_OUT) {
78+
if (entry->hook == NF_INET_LOCAL_OUT) {
7779
struct ipv6hdr *iph = ipv6_hdr(skb);
7880
if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
7981
!ipv6_addr_equal(&iph->saddr, &rt_info->saddr))

0 commit comments

Comments
 (0)