OSDN Git Service

inet: frags: use rhashtables for reassembly units
[android-x86/kernel.git] / include / net / inet_frag.h
1 #ifndef __NET_FRAG_H__
2 #define __NET_FRAG_H__
3
4 #include <linux/rhashtable.h>
5
6 struct netns_frags {
7         struct rhashtable       rhashtable ____cacheline_aligned_in_smp;
8
9         /* Keep atomic mem on separate cachelines in structs that include it */
10         atomic_t                mem ____cacheline_aligned_in_smp;
11         /* sysctls */
12         int                     timeout;
13         int                     high_thresh;
14         int                     low_thresh;
15         int                     max_dist;
16         struct inet_frags       *f;
17 };
18
19 /**
20  * fragment queue flags
21  *
22  * @INET_FRAG_FIRST_IN: first fragment has arrived
23  * @INET_FRAG_LAST_IN: final fragment has arrived
24  * @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
25  */
26 enum {
27         INET_FRAG_FIRST_IN      = BIT(0),
28         INET_FRAG_LAST_IN       = BIT(1),
29         INET_FRAG_COMPLETE      = BIT(2),
30 };
31
32 struct frag_v4_compare_key {
33         __be32          saddr;
34         __be32          daddr;
35         u32             user;
36         u32             vif;
37         __be16          id;
38         u16             protocol;
39 };
40
41 struct frag_v6_compare_key {
42         struct in6_addr saddr;
43         struct in6_addr daddr;
44         u32             user;
45         __be32          id;
46         u32             iif;
47 };
48
49 /**
50  * struct inet_frag_queue - fragment queue
51  *
52  * @node: rhash node
53  * @key: keys identifying this frag.
54  * @timer: queue expiration timer
55  * @lock: spinlock protecting this frag
56  * @refcnt: reference count of the queue
57  * @fragments: received fragments head
58  * @fragments_tail: received fragments tail
59  * @stamp: timestamp of the last received fragment
60  * @len: total length of the original datagram
61  * @meat: length of received fragments so far
62  * @flags: fragment queue flags
63  * @max_size: maximum received fragment size
64  * @net: namespace that this frag belongs to
65  * @rcu: rcu head for freeing deferall
66  */
67 struct inet_frag_queue {
68         struct rhash_head       node;
69         union {
70                 struct frag_v4_compare_key v4;
71                 struct frag_v6_compare_key v6;
72         } key;
73         struct timer_list       timer;
74         spinlock_t              lock;
75         atomic_t                refcnt;
76         struct sk_buff          *fragments;
77         struct sk_buff          *fragments_tail;
78         ktime_t                 stamp;
79         int                     len;
80         int                     meat;
81         __u8                    flags;
82         u16                     max_size;
83         struct netns_frags      *net;
84         struct rcu_head         rcu;
85 };
86
87 struct inet_frags {
88         int                     qsize;
89
90         void                    (*constructor)(struct inet_frag_queue *q,
91                                                const void *arg);
92         void                    (*destructor)(struct inet_frag_queue *);
93         void                    (*frag_expire)(unsigned long data);
94         struct kmem_cache       *frags_cachep;
95         const char              *frags_cache_name;
96         struct rhashtable_params rhash_params;
97 };
98
99 int inet_frags_init(struct inet_frags *);
100 void inet_frags_fini(struct inet_frags *);
101
102 static inline int inet_frags_init_net(struct netns_frags *nf)
103 {
104         atomic_set(&nf->mem, 0);
105         return rhashtable_init(&nf->rhashtable, &nf->f->rhash_params);
106 }
107 void inet_frags_exit_net(struct netns_frags *nf);
108
109 void inet_frag_kill(struct inet_frag_queue *q);
110 void inet_frag_destroy(struct inet_frag_queue *q);
111 struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key);
112 void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
113                                    const char *prefix);
114
115 static inline void inet_frag_put(struct inet_frag_queue *q)
116 {
117         if (atomic_dec_and_test(&q->refcnt))
118                 inet_frag_destroy(q);
119 }
120
121 static inline bool inet_frag_evicting(struct inet_frag_queue *q)
122 {
123         return false;
124 }
125
126 /* Memory Tracking Functions. */
127
128 static inline int frag_mem_limit(struct netns_frags *nf)
129 {
130         return atomic_read(&nf->mem);
131 }
132
133 static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
134 {
135         atomic_sub(i, &nf->mem);
136 }
137
138 static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
139 {
140         atomic_add(i, &nf->mem);
141 }
142
143 static inline int sum_frag_mem_limit(struct netns_frags *nf)
144 {
145         return atomic_read(&nf->mem);
146 }
147
148 /* RFC 3168 support :
149  * We want to check ECN values of all fragments, do detect invalid combinations.
150  * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
151  */
152 #define IPFRAG_ECN_NOT_ECT      0x01 /* one frag had ECN_NOT_ECT */
153 #define IPFRAG_ECN_ECT_1        0x02 /* one frag had ECN_ECT_1 */
154 #define IPFRAG_ECN_ECT_0        0x04 /* one frag had ECN_ECT_0 */
155 #define IPFRAG_ECN_CE           0x08 /* one frag had ECN_CE */
156
157 extern const u8 ip_frag_ecn_table[16];
158
159 #endif