diff options
Diffstat (limited to 'include/net/inet_connection_sock.h')
-rw-r--r-- | include/net/inet_connection_sock.h | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h new file mode 100644 index 000000000000..651f824c1008 --- /dev/null +++ b/include/net/inet_connection_sock.h | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * NET Generic infrastructure for INET connection oriented protocols. | ||
3 | * | ||
4 | * Definitions for inet_connection_sock | ||
5 | * | ||
6 | * Authors: Many people, see the TCP sources | ||
7 | * | ||
8 | * From code originally in TCP | ||
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_CONNECTION_SOCK_H | ||
16 | #define _INET_CONNECTION_SOCK_H | ||
17 | |||
18 | #include <linux/ip.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/timer.h> | ||
21 | #include <net/request_sock.h> | ||
22 | |||
23 | #define INET_CSK_DEBUG 1 | ||
24 | |||
25 | /* Cancel timers, when they are not required. */ | ||
26 | #undef INET_CSK_CLEAR_TIMERS | ||
27 | |||
28 | struct inet_bind_bucket; | ||
29 | struct inet_hashinfo; | ||
30 | struct tcp_congestion_ops; | ||
31 | |||
32 | /** inet_connection_sock - INET connection oriented sock | ||
33 | * | ||
34 | * @icsk_accept_queue: FIFO of established children | ||
35 | * @icsk_bind_hash: Bind node | ||
36 | * @icsk_timeout: Timeout | ||
37 | * @icsk_retransmit_timer: Resend (no ack) | ||
38 | * @icsk_rto: Retransmit timeout | ||
39 | * @icsk_ca_ops Pluggable congestion control hook | ||
40 | * @icsk_ca_state: Congestion control state | ||
41 | * @icsk_retransmits: Number of unrecovered [RTO] timeouts | ||
42 | * @icsk_pending: Scheduled timer event | ||
43 | * @icsk_backoff: Backoff | ||
44 | * @icsk_syn_retries: Number of allowed SYN (or equivalent) retries | ||
45 | * @icsk_probes_out: unanswered 0 window probes | ||
46 | * @icsk_ack: Delayed ACK control data | ||
47 | */ | ||
48 | struct inet_connection_sock { | ||
49 | /* inet_sock has to be the first member! */ | ||
50 | struct inet_sock icsk_inet; | ||
51 | struct request_sock_queue icsk_accept_queue; | ||
52 | struct inet_bind_bucket *icsk_bind_hash; | ||
53 | unsigned long icsk_timeout; | ||
54 | struct timer_list icsk_retransmit_timer; | ||
55 | struct timer_list icsk_delack_timer; | ||
56 | __u32 icsk_rto; | ||
57 | struct tcp_congestion_ops *icsk_ca_ops; | ||
58 | __u8 icsk_ca_state; | ||
59 | __u8 icsk_retransmits; | ||
60 | __u8 icsk_pending; | ||
61 | __u8 icsk_backoff; | ||
62 | __u8 icsk_syn_retries; | ||
63 | __u8 icsk_probes_out; | ||
64 | /* 2 BYTES HOLE, TRY TO PACK! */ | ||
65 | struct { | ||
66 | __u8 pending; /* ACK is pending */ | ||
67 | __u8 quick; /* Scheduled number of quick acks */ | ||
68 | __u8 pingpong; /* The session is interactive */ | ||
69 | __u8 blocked; /* Delayed ACK was blocked by socket lock */ | ||
70 | __u32 ato; /* Predicted tick of soft clock */ | ||
71 | unsigned long timeout; /* Currently scheduled timeout */ | ||
72 | __u32 lrcvtime; /* timestamp of last received data packet */ | ||
73 | __u16 last_seg_size; /* Size of last incoming segment */ | ||
74 | __u16 rcv_mss; /* MSS used for delayed ACK decisions */ | ||
75 | } icsk_ack; | ||
76 | u32 icsk_ca_priv[16]; | ||
77 | #define ICSK_CA_PRIV_SIZE (16 * sizeof(u32)) | ||
78 | }; | ||
79 | |||
80 | #define ICSK_TIME_RETRANS 1 /* Retransmit timer */ | ||
81 | #define ICSK_TIME_DACK 2 /* Delayed ack timer */ | ||
82 | #define ICSK_TIME_PROBE0 3 /* Zero window probe timer */ | ||
83 | #define ICSK_TIME_KEEPOPEN 4 /* Keepalive timer */ | ||
84 | |||
85 | static inline struct inet_connection_sock *inet_csk(const struct sock *sk) | ||
86 | { | ||
87 | return (struct inet_connection_sock *)sk; | ||
88 | } | ||
89 | |||
90 | static inline void *inet_csk_ca(const struct sock *sk) | ||
91 | { | ||
92 | return (void *)inet_csk(sk)->icsk_ca_priv; | ||
93 | } | ||
94 | |||
95 | extern struct sock *inet_csk_clone(struct sock *sk, | ||
96 | const struct request_sock *req, | ||
97 | const unsigned int __nocast priority); | ||
98 | |||
99 | enum inet_csk_ack_state_t { | ||
100 | ICSK_ACK_SCHED = 1, | ||
101 | ICSK_ACK_TIMER = 2, | ||
102 | ICSK_ACK_PUSHED = 4 | ||
103 | }; | ||
104 | |||
105 | extern void inet_csk_init_xmit_timers(struct sock *sk, | ||
106 | void (*retransmit_handler)(unsigned long), | ||
107 | void (*delack_handler)(unsigned long), | ||
108 | void (*keepalive_handler)(unsigned long)); | ||
109 | extern void inet_csk_clear_xmit_timers(struct sock *sk); | ||
110 | |||
111 | static inline void inet_csk_schedule_ack(struct sock *sk) | ||
112 | { | ||
113 | inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_SCHED; | ||
114 | } | ||
115 | |||
116 | static inline int inet_csk_ack_scheduled(const struct sock *sk) | ||
117 | { | ||
118 | return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED; | ||
119 | } | ||
120 | |||
121 | static inline void inet_csk_delack_init(struct sock *sk) | ||
122 | { | ||
123 | memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack)); | ||
124 | } | ||
125 | |||
126 | extern void inet_csk_delete_keepalive_timer(struct sock *sk); | ||
127 | extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout); | ||
128 | |||
129 | #ifdef INET_CSK_DEBUG | ||
130 | extern const char inet_csk_timer_bug_msg[]; | ||
131 | #endif | ||
132 | |||
133 | static inline void inet_csk_clear_xmit_timer(struct sock *sk, const int what) | ||
134 | { | ||
135 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
136 | |||
137 | if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) { | ||
138 | icsk->icsk_pending = 0; | ||
139 | #ifdef INET_CSK_CLEAR_TIMERS | ||
140 | sk_stop_timer(sk, &icsk->icsk_retransmit_timer); | ||
141 | #endif | ||
142 | } else if (what == ICSK_TIME_DACK) { | ||
143 | icsk->icsk_ack.blocked = icsk->icsk_ack.pending = 0; | ||
144 | #ifdef INET_CSK_CLEAR_TIMERS | ||
145 | sk_stop_timer(sk, &icsk->icsk_delack_timer); | ||
146 | #endif | ||
147 | } | ||
148 | #ifdef INET_CSK_DEBUG | ||
149 | else { | ||
150 | pr_debug("%s", inet_csk_timer_bug_msg); | ||
151 | } | ||
152 | #endif | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Reset the retransmission timer | ||
157 | */ | ||
158 | static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what, | ||
159 | unsigned long when, | ||
160 | const unsigned long max_when) | ||
161 | { | ||
162 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
163 | |||
164 | if (when > max_when) { | ||
165 | #ifdef INET_CSK_DEBUG | ||
166 | pr_debug("reset_xmit_timer: sk=%p %d when=0x%lx, caller=%p\n", | ||
167 | sk, what, when, current_text_addr()); | ||
168 | #endif | ||
169 | when = max_when; | ||
170 | } | ||
171 | |||
172 | if (what == ICSK_TIME_RETRANS || what == ICSK_TIME_PROBE0) { | ||
173 | icsk->icsk_pending = what; | ||
174 | icsk->icsk_timeout = jiffies + when; | ||
175 | sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout); | ||
176 | } else if (what == ICSK_TIME_DACK) { | ||
177 | icsk->icsk_ack.pending |= ICSK_ACK_TIMER; | ||
178 | icsk->icsk_ack.timeout = jiffies + when; | ||
179 | sk_reset_timer(sk, &icsk->icsk_delack_timer, icsk->icsk_ack.timeout); | ||
180 | } | ||
181 | #ifdef INET_CSK_DEBUG | ||
182 | else { | ||
183 | pr_debug("%s", inet_csk_timer_bug_msg); | ||
184 | } | ||
185 | #endif | ||
186 | } | ||
187 | |||
188 | extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err); | ||
189 | |||
190 | extern struct request_sock *inet_csk_search_req(const struct sock *sk, | ||
191 | struct request_sock ***prevp, | ||
192 | const __u16 rport, | ||
193 | const __u32 raddr, | ||
194 | const __u32 laddr); | ||
195 | extern int inet_csk_get_port(struct inet_hashinfo *hashinfo, | ||
196 | struct sock *sk, unsigned short snum); | ||
197 | |||
198 | extern struct dst_entry* inet_csk_route_req(struct sock *sk, | ||
199 | const struct request_sock *req); | ||
200 | |||
201 | static inline void inet_csk_reqsk_queue_add(struct sock *sk, | ||
202 | struct request_sock *req, | ||
203 | struct sock *child) | ||
204 | { | ||
205 | reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child); | ||
206 | } | ||
207 | |||
208 | extern void inet_csk_reqsk_queue_hash_add(struct sock *sk, | ||
209 | struct request_sock *req, | ||
210 | const unsigned timeout); | ||
211 | |||
212 | static inline void inet_csk_reqsk_queue_removed(struct sock *sk, | ||
213 | struct request_sock *req) | ||
214 | { | ||
215 | if (reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req) == 0) | ||
216 | inet_csk_delete_keepalive_timer(sk); | ||
217 | } | ||
218 | |||
219 | static inline void inet_csk_reqsk_queue_added(struct sock *sk, | ||
220 | const unsigned long timeout) | ||
221 | { | ||
222 | if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0) | ||
223 | inet_csk_reset_keepalive_timer(sk, timeout); | ||
224 | } | ||
225 | |||
226 | static inline int inet_csk_reqsk_queue_len(const struct sock *sk) | ||
227 | { | ||
228 | return reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue); | ||
229 | } | ||
230 | |||
231 | static inline int inet_csk_reqsk_queue_young(const struct sock *sk) | ||
232 | { | ||
233 | return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue); | ||
234 | } | ||
235 | |||
236 | static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk) | ||
237 | { | ||
238 | return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue); | ||
239 | } | ||
240 | |||
241 | static inline void inet_csk_reqsk_queue_unlink(struct sock *sk, | ||
242 | struct request_sock *req, | ||
243 | struct request_sock **prev) | ||
244 | { | ||
245 | reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req, prev); | ||
246 | } | ||
247 | |||
248 | static inline void inet_csk_reqsk_queue_drop(struct sock *sk, | ||
249 | struct request_sock *req, | ||
250 | struct request_sock **prev) | ||
251 | { | ||
252 | inet_csk_reqsk_queue_unlink(sk, req, prev); | ||
253 | inet_csk_reqsk_queue_removed(sk, req); | ||
254 | reqsk_free(req); | ||
255 | } | ||
256 | |||
257 | extern void inet_csk_reqsk_queue_prune(struct sock *parent, | ||
258 | const unsigned long interval, | ||
259 | const unsigned long timeout, | ||
260 | const unsigned long max_rto); | ||
261 | |||
262 | extern void inet_csk_destroy_sock(struct sock *sk); | ||
263 | |||
264 | /* | ||
265 | * LISTEN is a special case for poll.. | ||
266 | */ | ||
267 | static inline unsigned int inet_csk_listen_poll(const struct sock *sk) | ||
268 | { | ||
269 | return !reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue) ? | ||
270 | (POLLIN | POLLRDNORM) : 0; | ||
271 | } | ||
272 | |||
273 | extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries); | ||
274 | extern void inet_csk_listen_stop(struct sock *sk); | ||
275 | |||
276 | #endif /* _INET_CONNECTION_SOCK_H */ | ||