diff options
Diffstat (limited to 'include/net/inet_timewait_sock.h')
-rw-r--r-- | include/net/inet_timewait_sock.h | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h new file mode 100644 index 000000000000..3b070352e869 --- /dev/null +++ b/include/net/inet_timewait_sock.h | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * Definitions for a generic INET TIMEWAIT sock | ||
7 | * | ||
8 | * From code originally in net/tcp.h | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | #ifndef _INET_TIMEWAIT_SOCK_ | ||
16 | #define _INET_TIMEWAIT_SOCK_ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | |||
20 | #include <linux/ip.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/timer.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #include <net/sock.h> | ||
27 | #include <net/tcp_states.h> | ||
28 | |||
29 | #include <asm/atomic.h> | ||
30 | |||
31 | struct inet_hashinfo; | ||
32 | |||
33 | #define INET_TWDR_RECYCLE_SLOTS_LOG 5 | ||
34 | #define INET_TWDR_RECYCLE_SLOTS (1 << INET_TWDR_RECYCLE_SLOTS_LOG) | ||
35 | |||
36 | /* | ||
37 | * If time > 4sec, it is "slow" path, no recycling is required, | ||
38 | * so that we select tick to get range about 4 seconds. | ||
39 | */ | ||
40 | #if HZ <= 16 || HZ > 4096 | ||
41 | # error Unsupported: HZ <= 16 or HZ > 4096 | ||
42 | #elif HZ <= 32 | ||
43 | # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
44 | #elif HZ <= 64 | ||
45 | # define INET_TWDR_RECYCLE_TICK (6 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
46 | #elif HZ <= 128 | ||
47 | # define INET_TWDR_RECYCLE_TICK (7 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
48 | #elif HZ <= 256 | ||
49 | # define INET_TWDR_RECYCLE_TICK (8 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
50 | #elif HZ <= 512 | ||
51 | # define INET_TWDR_RECYCLE_TICK (9 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
52 | #elif HZ <= 1024 | ||
53 | # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
54 | #elif HZ <= 2048 | ||
55 | # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
56 | #else | ||
57 | # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG) | ||
58 | #endif | ||
59 | |||
60 | /* TIME_WAIT reaping mechanism. */ | ||
61 | #define INET_TWDR_TWKILL_SLOTS 8 /* Please keep this a power of 2. */ | ||
62 | |||
63 | #define INET_TWDR_TWKILL_QUOTA 100 | ||
64 | |||
65 | struct inet_timewait_death_row { | ||
66 | /* Short-time timewait calendar */ | ||
67 | int twcal_hand; | ||
68 | int twcal_jiffie; | ||
69 | struct timer_list twcal_timer; | ||
70 | struct hlist_head twcal_row[INET_TWDR_RECYCLE_SLOTS]; | ||
71 | |||
72 | spinlock_t death_lock; | ||
73 | int tw_count; | ||
74 | int period; | ||
75 | u32 thread_slots; | ||
76 | struct work_struct twkill_work; | ||
77 | struct timer_list tw_timer; | ||
78 | int slot; | ||
79 | struct hlist_head cells[INET_TWDR_TWKILL_SLOTS]; | ||
80 | struct inet_hashinfo *hashinfo; | ||
81 | int sysctl_tw_recycle; | ||
82 | int sysctl_max_tw_buckets; | ||
83 | }; | ||
84 | |||
85 | extern void inet_twdr_hangman(unsigned long data); | ||
86 | extern void inet_twdr_twkill_work(void *data); | ||
87 | extern void inet_twdr_twcal_tick(unsigned long data); | ||
88 | |||
89 | #if (BITS_PER_LONG == 64) | ||
90 | #define INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES 8 | ||
91 | #else | ||
92 | #define INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES 4 | ||
93 | #endif | ||
94 | |||
95 | struct inet_bind_bucket; | ||
96 | |||
97 | /* | ||
98 | * This is a TIME_WAIT sock. It works around the memory consumption | ||
99 | * problems of sockets in such a state on heavily loaded servers, but | ||
100 | * without violating the protocol specification. | ||
101 | */ | ||
102 | struct inet_timewait_sock { | ||
103 | /* | ||
104 | * Now struct sock also uses sock_common, so please just | ||
105 | * don't add nothing before this first member (__tw_common) --acme | ||
106 | */ | ||
107 | struct sock_common __tw_common; | ||
108 | #define tw_family __tw_common.skc_family | ||
109 | #define tw_state __tw_common.skc_state | ||
110 | #define tw_reuse __tw_common.skc_reuse | ||
111 | #define tw_bound_dev_if __tw_common.skc_bound_dev_if | ||
112 | #define tw_node __tw_common.skc_node | ||
113 | #define tw_bind_node __tw_common.skc_bind_node | ||
114 | #define tw_refcnt __tw_common.skc_refcnt | ||
115 | #define tw_prot __tw_common.skc_prot | ||
116 | volatile unsigned char tw_substate; | ||
117 | /* 3 bits hole, try to pack */ | ||
118 | unsigned char tw_rcv_wscale; | ||
119 | /* Socket demultiplex comparisons on incoming packets. */ | ||
120 | /* these five are in inet_sock */ | ||
121 | __u16 tw_sport; | ||
122 | __u32 tw_daddr __attribute__((aligned(INET_TIMEWAIT_ADDRCMP_ALIGN_BYTES))); | ||
123 | __u32 tw_rcv_saddr; | ||
124 | __u16 tw_dport; | ||
125 | __u16 tw_num; | ||
126 | /* And these are ours. */ | ||
127 | __u8 tw_ipv6only:1; | ||
128 | /* 31 bits hole, try to pack */ | ||
129 | int tw_hashent; | ||
130 | int tw_timeout; | ||
131 | unsigned long tw_ttd; | ||
132 | struct inet_bind_bucket *tw_tb; | ||
133 | struct hlist_node tw_death_node; | ||
134 | }; | ||
135 | |||
136 | static inline void inet_twsk_add_node(struct inet_timewait_sock *tw, | ||
137 | struct hlist_head *list) | ||
138 | { | ||
139 | hlist_add_head(&tw->tw_node, list); | ||
140 | } | ||
141 | |||
142 | static inline void inet_twsk_add_bind_node(struct inet_timewait_sock *tw, | ||
143 | struct hlist_head *list) | ||
144 | { | ||
145 | hlist_add_head(&tw->tw_bind_node, list); | ||
146 | } | ||
147 | |||
148 | static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw) | ||
149 | { | ||
150 | return tw->tw_death_node.pprev != NULL; | ||
151 | } | ||
152 | |||
153 | static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw) | ||
154 | { | ||
155 | tw->tw_death_node.pprev = NULL; | ||
156 | } | ||
157 | |||
158 | static inline void __inet_twsk_del_dead_node(struct inet_timewait_sock *tw) | ||
159 | { | ||
160 | __hlist_del(&tw->tw_death_node); | ||
161 | inet_twsk_dead_node_init(tw); | ||
162 | } | ||
163 | |||
164 | static inline int inet_twsk_del_dead_node(struct inet_timewait_sock *tw) | ||
165 | { | ||
166 | if (inet_twsk_dead_hashed(tw)) { | ||
167 | __inet_twsk_del_dead_node(tw); | ||
168 | return 1; | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | #define inet_twsk_for_each(tw, node, head) \ | ||
174 | hlist_for_each_entry(tw, node, head, tw_node) | ||
175 | |||
176 | #define inet_twsk_for_each_inmate(tw, node, jail) \ | ||
177 | hlist_for_each_entry(tw, node, jail, tw_death_node) | ||
178 | |||
179 | #define inet_twsk_for_each_inmate_safe(tw, node, safe, jail) \ | ||
180 | hlist_for_each_entry_safe(tw, node, safe, jail, tw_death_node) | ||
181 | |||
182 | static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk) | ||
183 | { | ||
184 | return (struct inet_timewait_sock *)sk; | ||
185 | } | ||
186 | |||
187 | static inline u32 inet_rcv_saddr(const struct sock *sk) | ||
188 | { | ||
189 | return likely(sk->sk_state != TCP_TIME_WAIT) ? | ||
190 | inet_sk(sk)->rcv_saddr : inet_twsk(sk)->tw_rcv_saddr; | ||
191 | } | ||
192 | |||
193 | static inline void inet_twsk_put(struct inet_timewait_sock *tw) | ||
194 | { | ||
195 | if (atomic_dec_and_test(&tw->tw_refcnt)) { | ||
196 | #ifdef SOCK_REFCNT_DEBUG | ||
197 | printk(KERN_DEBUG "%s timewait_sock %p released\n", | ||
198 | tw->tw_prot->name, tw); | ||
199 | #endif | ||
200 | kmem_cache_free(tw->tw_prot->twsk_slab, tw); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, | ||
205 | const int state); | ||
206 | |||
207 | extern void __inet_twsk_kill(struct inet_timewait_sock *tw, | ||
208 | struct inet_hashinfo *hashinfo); | ||
209 | |||
210 | extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw, | ||
211 | struct sock *sk, | ||
212 | struct inet_hashinfo *hashinfo); | ||
213 | |||
214 | extern void inet_twsk_schedule(struct inet_timewait_sock *tw, | ||
215 | struct inet_timewait_death_row *twdr, | ||
216 | const int timeo, const int timewait_len); | ||
217 | extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, | ||
218 | struct inet_timewait_death_row *twdr); | ||
219 | #endif /* _INET_TIMEWAIT_SOCK_ */ | ||