Commit | Line | Data |
---|---|---|
c01cd429 PM |
1 | #ifndef _NF_QUEUE_H |
2 | #define _NF_QUEUE_H | |
3 | ||
97a2d41c EL |
4 | #include <linux/ip.h> |
5 | #include <linux/ipv6.h> | |
6 | #include <linux/jhash.h> | |
7 | ||
c01cd429 | 8 | /* Each queued (to userspace) skbuff has one of these. */ |
02f014d8 PM |
9 | struct nf_queue_entry { |
10 | struct list_head list; | |
11 | struct sk_buff *skb; | |
12 | unsigned int id; | |
13 | ||
c01cd429 | 14 | struct nf_hook_ops *elem; |
1d1de89b | 15 | struct nf_hook_state state; |
a5fedd43 | 16 | u16 size; /* sizeof(entry) + saved route keys */ |
a5fedd43 FW |
17 | |
18 | /* extra space to store route keys */ | |
c01cd429 PM |
19 | }; |
20 | ||
02f014d8 | 21 | #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) |
c01cd429 PM |
22 | |
23 | /* Packet queuing */ | |
24 | struct nf_queue_handler { | |
02f014d8 | 25 | int (*outfn)(struct nf_queue_entry *entry, |
c01cd429 | 26 | unsigned int queuenum); |
8405a8ff EB |
27 | void (*nf_hook_drop)(struct net *net, |
28 | struct nf_hook_ops *ops); | |
c01cd429 PM |
29 | }; |
30 | ||
dc3ee32e EB |
31 | void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh); |
32 | void nf_unregister_queue_handler(struct net *net); | |
4e77be46 | 33 | void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); |
c01cd429 | 34 | |
ed78d09d | 35 | void nf_queue_entry_get_refs(struct nf_queue_entry *entry); |
a5fedd43 FW |
36 | void nf_queue_entry_release_refs(struct nf_queue_entry *entry); |
37 | ||
97a2d41c EL |
38 | static inline void init_hashrandom(u32 *jhash_initval) |
39 | { | |
40 | while (*jhash_initval == 0) | |
41 | *jhash_initval = prandom_u32(); | |
42 | } | |
43 | ||
44 | static inline u32 hash_v4(const struct sk_buff *skb, u32 jhash_initval) | |
45 | { | |
46 | const struct iphdr *iph = ip_hdr(skb); | |
47 | ||
48 | /* packets in either direction go into same queue */ | |
49 | if ((__force u32)iph->saddr < (__force u32)iph->daddr) | |
50 | return jhash_3words((__force u32)iph->saddr, | |
51 | (__force u32)iph->daddr, iph->protocol, jhash_initval); | |
52 | ||
53 | return jhash_3words((__force u32)iph->daddr, | |
54 | (__force u32)iph->saddr, iph->protocol, jhash_initval); | |
55 | } | |
56 | ||
97a2d41c EL |
57 | static inline u32 hash_v6(const struct sk_buff *skb, u32 jhash_initval) |
58 | { | |
59 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | |
60 | u32 a, b, c; | |
61 | ||
62 | if ((__force u32)ip6h->saddr.s6_addr32[3] < | |
63 | (__force u32)ip6h->daddr.s6_addr32[3]) { | |
64 | a = (__force u32) ip6h->saddr.s6_addr32[3]; | |
65 | b = (__force u32) ip6h->daddr.s6_addr32[3]; | |
66 | } else { | |
67 | b = (__force u32) ip6h->saddr.s6_addr32[3]; | |
68 | a = (__force u32) ip6h->daddr.s6_addr32[3]; | |
69 | } | |
70 | ||
71 | if ((__force u32)ip6h->saddr.s6_addr32[1] < | |
72 | (__force u32)ip6h->daddr.s6_addr32[1]) | |
73 | c = (__force u32) ip6h->saddr.s6_addr32[1]; | |
74 | else | |
75 | c = (__force u32) ip6h->daddr.s6_addr32[1]; | |
76 | ||
77 | return jhash_3words(a, b, c, jhash_initval); | |
78 | } | |
97a2d41c EL |
79 | |
80 | static inline u32 | |
81 | nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family, | |
82 | u32 jhash_initval) | |
83 | { | |
84 | if (family == NFPROTO_IPV4) | |
85 | queue += ((u64) hash_v4(skb, jhash_initval) * queues_total) >> 32; | |
97a2d41c EL |
86 | else if (family == NFPROTO_IPV6) |
87 | queue += ((u64) hash_v6(skb, jhash_initval) * queues_total) >> 32; | |
97a2d41c EL |
88 | |
89 | return queue; | |
90 | } | |
91 | ||
c01cd429 | 92 | #endif /* _NF_QUEUE_H */ |